15 min/d

ぼうずやのにっき

2017-W28 ふりかえり

2017-W28 をふりかえる。

2017-07 の目標

2017-W28 の目標 とその記事

目標。

記事。

bouzuya/bs-android の 1.0.0 をつくるつもりだったけど、できなかった。みっつの問題があった。

ひとつは Heroku から Node.js の Hash flooding DoS についてのお知らせが来て、その対応に時間を取られたからだ。

Node.js で発生した Hash flooding DoS とその内容について - from scratch

もうひとつは bouzuya/beater の修正だ。使いたいときに使えなくて困ったので、 TypeScript 2.x 対応と合わせて大きく変更して 5.0.0 にした。

最後は bouzuya/bs-code の修正だ。リンクの展開処理に問題があったので直した。これはまた別で書く。

肝心の bs-android は Firebase Authentication と Firebase Realtime Database を試している。

ゼルダの伝説 神々のトライフォース』は目標通りにクリアした。

つくったもの

2017-07-10/2017-07-16

Node.js のバージョンアップに関する細かい変更および blog などは除外している。前述の通り beater, bs-android, bs-code だ。

その他

望んだ形ではないけど、いくつかのものをつくっており、良い。継続的に出していくことは大切だ。今回の beater のように今月・来月あたりで TypeScript で書いた npm パッケージの更新をしていくことはままありそうだ。そろそろ古くなってくる頃だろうから。

Android アプリ bs-android を引き続きつくっていく。できれば今週中には公開したい。 bouzuya/bs-codebouzuya/mr-jums から学んだことには、なるべく早い段階で公開するのが良さそう。ぼくが普段から使えるところまで持っていければ十分だ。 mr-jums はタイミングを逃したためにいつまでも未公開だし、 bs-code は万人向けにはできていないけどタイミングを逃さなかったので公開できて使えている。最初の一歩は小さくて良い。

早起きはわりとできている。当たり前のことだが、残業が増えて生活リズムが崩れると良くないようだ。腰痛の解消のために軽いトレーニングをはじめている。早起き・ストレッチとともに習慣化していきたい。

2017-W29 の目標

  • bouzuya/bs-code 1.5.4 のことを書く
  • bouzuya/bs-android 1.0.0 をつくる
  • 早起き・ストレッチ・トレーニングをする

bouzuya/beater 5.0.0 をつくった

bouzuya/beater 5.0.0 をつくった。あわせて beater 関連の npm パッケージを更新した。

5.0.0 はいくつかの破壊的な変更を含んでいる。

  • beater-cli を不要にした
  • fixture() を削除した
  • run() runWithOptions() test() を追加・変更した
  • 結果の表示を変更した (beater-cli-reporter -> beater-tap-reporter)
  • ブラウザのサポートを削除した (考慮していないが、おそらく以前よりうまく動く)

簡単に言うと「より簡単にした」。例を示す。

// index.ts
import * as assert from 'power-assert';
import { run, test } from 'beater';

run([
  test('simple test', () => {
    assert(1 + 1 === 2);
  }),
  test('async test', () => {
    return new Promise((resolve) => {
      assert(1 + 1 !== 200);
      assert((1 + 1) * 10 !== 200);
      resolve();
    });
  })
]).catch(() => process.exit(1));

test()Test を返す。以前は test() を呼んだ瞬間にキューへ入れられ実行されていたが、今回は動かない。あくまでもテストを表すオブジェクトを返すだけだ。以前と同様だが、非同期処理には Promise を使う。テストを失敗と見なす条件は、何かが throw される、または返された Promisereject の場合だ。assert() は↑のように power-assert を使ってもいいし、標準の assert でも、ほかのものでもいい。おそらく Error を投げるようになっているはずなので使えるだろう。

run()Test を実行する。以前は beater-cli 経由でファイル単位に require() して実行していたが、今回は違う。単純な関数の呼び出しだ。これによる大きな変更点は、あるテストが環境を破壊した場合に他のテストも影響を受けるということだ。「そんなことをする奴が悪い」で切り捨てることにした。

あとは Node.js に食わせればいい。既定では TAP の形式で出力される。

$ $(npm bin)/tsc --module commonjs --target es2017 index.ts
$ node index.js
TAP version 13
1..2
ok 1 - simple test
ok 2 - async test

出力の形式が気に入らないなら TAP から変換する reporter をかませるか、独自の reporter を runWithOptions() に渡せばいい。

$ yarn add tap-nyan
$ node index.js | $(npm bin)/tap-nyan
 2   -__,------,
 0   -__|  /\_/\
 0   -_~|_( ^ .^)
     -_ ""  ""
  Pass!

test() run() runWithOptions() の 3 つの関数しか export していないので、説明は以上だ。「これでテストフレームワーク?」という感じではあるが、たったのこれだけだ。実装も大したことはない。ぜひ bouzuya/beater を読んで「これを使うくらいなら自分でつくる」そう思ってほしい。

今後の展開としては、独自の reporter の例として AVA のような beater-mini-reporter をつくってみたい。ほかには fixture() やグループ化・ ObservableIterableIterator<T> に対応するための helper をつくってみても良さそう。使いながら足りない部分を補うつもりだ。


2017-07-08 に beta 公開した bouzuya/bbna 1.4.0 を正式公開した。 https://play.google.com/store/apps/details?id=net.bouzuya.blog

bouzuya/beater を変えている

bouzuya/beater を変えている。

2017-07-11 に書いた bouzuya/beater の直しをしている。2017-07-12 / 2017-07-13 と Heroku アプリの棚卸しが挟まったことで脱線した。戻ってきた。

beater は bouzuya easy test runner だ。名前に反して easy というよりは simple を目指していく。

また、できたら書くが、現状は↓のつもりだ。

  • fixture() は別のパッケージに移動する
  • const { test } = beater(); というボイラープレートコードを削除する
  • beater-cli パッケージなしで動くようにする
  • ファイル単位ではなくテスト (test() によって生成される) 単位で実行する

限界まで機能を抑えるつもりだ。なるべく小さくすることで、読める大きさの実装にしたい。「自分で書けるけど beater を使う」あるいは「 ( beater を見て) こんな簡単にテストフレームワークがつくれるなら、自分でもつくってみたい」と思わせたい。

すべては持てない、うまく捨てろ、捨てられないものに注意せよ

昨日 (2017-07-12) 書いた Heroku アプリの棚卸し。 Node.js のバージョンアップは完了したものの、半分くらいで投げた。

再認識したことがふたつある。

  • 多くのものを維持するのは難しい
  • 維持し続けないといけなくなるものには注意すべき

ひとつめ。多くのものを維持するのは難しい。大量のアプリケーションを最新状態に維持することは難しい。自動化できる部分もあるが、そうでない部分は難しい。住んでいない家を維持し続けるのがつらいのと似ている。

いま関心のないものに力を入れることは難しい。できるが、それをすると、いま関心のあるものに力を入れられなくなってしまうだろう。どこかで手を引く必要がある。

たとえば、いまさら Gruntfile や Backbone で書いたものを npm run script や React などに置き換えられるだろうか。不可能ではないが難しい。もちろん、そのシステムを新しい技術に置き換えながらでも進めるべきものならそうすべきだ。しかし、単発でつくったものや技術検証のためにつくった場合などは難しい。

先の住んでいない家の例のように、使っているものは維持していく、そうでないものはうまく捨てていくのが良いのだろう。

ふたつめ。維持し続けないといけなくなるものには注意すべき。先に書いたとおり、うまく捨てていく必要はあるのだけど、だからこそ捨てられない(捨てにくい)ものには注意したほうがいい。

たとえばドメイン名だ。ドメイン名は不用意に捨てられない。少額ではあるものの維持に費用もかかる。捨てたくなったときに維持し続けるのは苦痛だ。 URL も下手に切るとまずいだろう。

可能なら(名前にこだわりがなければ)絶対に手放さないドメインからリダイレクトすると良さそうだ。 bouzuya.net にもそういうリダイレクト用のパスなどをつくろうかな。

まとめると「すべては持てない、うまく捨てろ、捨てられないものに注意せよ」そういうことだ。

Heroku アプリの棚卸し / 『ゼルダの伝説 神々のトライフォース』をクリアした

Heroku からお知らせが来た。要約すると Node.js の全バージョン (?) に DoS脆弱性があり、それが修正されたので適用しろ、とのこと。

Heroku でまじめに運用しているアプリはないので DoS 攻撃がどうしたって感じではあるけど、せっかくなので Heroku のアプリを棚卸ししている。

数が多く、しばらくかかりそうだ。


ゼルダの伝説 神々のトライフォース』をクリアした。最後はあっけない感じだった。ぼくが最も難しいと感じたのは、ヘラの塔のデグテールだった。最も詰まったのは、水のほこらクリア後のチェーンフック入手後にドクロの森への行き方 (川を渡れる) に気づくところだった。

これでゲームはしばらくお休みするか……。

bouzuya/beater を直している

bouzuya/beater を直している。

ひさしぶりに使おうとしたら、 TypeScript 2.x で動かないことに気づいたからだ。大きな問題は test() の第二引数が () => void ではダメなことなどだ。

// ↓のようなおそらく最も簡単な場合からダメ。
test('1 === 1', () => {
  assert(1 === 1);
});

ほかにも TypeScript 1.8 だし typings を使っていたりと古い。

直している過程で、 ↓のようなコードが通らないことに気づいた。

const f = (): void => void 0;
Promise.resolve(f());

voidundefined の区別ってこんなに厳しかったかな……。どこかのタイミングで型定義ファイルが厳しくなったんじゃないかな……。

こうなっている理由はなんとなく分かる。 nullundefined を明確に分離するようになったことで、↓のような判断がされているのだろう。

// 良くない定義
type f = (x?: number): void | number;

// 良い定義
interface f {
  (): void;
  (x: number): number;
}

上記は ? によって undefined を許容してしまうし、「 省略したとき void を返す」という情報が落ちてしまう。

Promise.resolve() でも似たような判断があるのだろう。

直しついでに誰も使っていないであろう browser support を打ち切って、使いかたも変えてしまおうと思っている。当時は迷ってこれにしたのだけど、良くなかった。ぼく自身が使わない機能は腐っていく。誰かがサポートしないなら消していこう。

bouzuya/beater を直している

bouzuya/beater を直している。

ひさしぶりに使おうとしたら、 TypeScript 2.x で動かないことに気づいたからだ。大きな問題は test() の第二引数が () => void ではダメなことなどだ。

// ↓のようなおそらく最も簡単な場合からダメ。
test('1 === 1', () => {
  assert(1 === 1);
});

ほかにも TypeScript 1.8 だし typings を使っていたりと古い。

直している過程で、 ↓のようなコードが通らないことに気づいた。

const f = (): void => void 0;
Promise.resolve(f());

voidundefined の区別ってこんなに厳しかったかな……。どこかのタイミングで型定義ファイルが厳しくなったんじゃないかな……。

こうなっている理由はなんとなく分かる。 nullundefined を明確に分離するようになったことで、↓のような判断がされているのだろう。

// 良くない定義
type f = (x?: number): void | number;

// 良い定義
interface f {
  (): void;
  (x: number): number;
}

上記は ? によって undefined を許容してしまうし、「 省略したとき void を返す」という情報が落ちてしまう。

Promise.resolve() でも似たような判断があるのだろう。

直しついでに誰も使っていないであろう browser support を打ち切って、使いかたも変えてしまおうと思っている。当時は迷ってこれにしたのだけど、良くなかった。ぼく自身が使わない機能は腐っていく。誰かがサポートしないなら消していこう。