Node.js

FizzBuzz

仕様

  • 3で割り切れる場合はFizzを出力する

  • 5で割り切れる場合はBuzzを出力する

  • 両方で割り切れる場合はFizzBuzzを出力する

  • 指定された回数だけ繰り返し実行できるようにする

設計

TODOリスト

  • [STRIKEOUT:3ならばFizzを返すようにする]

  • [STRIKEOUT:5ならばBuzzを返すようにする]

  • [STRIKEOUT:15ならばFizzBuzzを返すようにする]

  • [STRIKEOUT:指定された回数だけだけ実行できるようにする]

[1]:
const fizzBuzz = class FizzBuzz {
    static generate(number) {
        let value = number;

        if (value % 3 === 0 && value % 5 === 0) {
            value = 'FizzBuzz'
        } else if (value % 3 === 0) {
            value = 'Fizz'
        } else if (value % 5 === 0) {
            value = 'Buzz'
        }

        return value;
    }

    static iterate(count) {
    const array = [];

    for (let i = 1; i <= count; i += 1) {
        array.push(FizzBuzz.generate(i));
    }

    return array;
    }
}

describe('TestFizzBuzz', function () {
    it('3ならばFizzを返すようにする', function () {
        expect(fizzBuzz.generate(3)).toBe('Fizz')
    });

    it('5ならばBuzzを返すようにする', function () {
        expect(fizzBuzz.generate(5)).toBe('Buzz')
    });

    it('15ならばFizzBuzzを返すようにする', function () {
        expect(fizzBuzz.generate(15)).toBe('FizzBuzz')
    });

    it('指定された回数だけ実行できるようにする', function () {
        expect(fizzBuzz.iterate(5)).toEqual([1, 2, 'Fizz', 4, 'Buzz'])
    })
});
evalmachine.<anonymous>:27
describe('TestFizzBuzz', function () {
^

ReferenceError: describe is not defined
    at evalmachine.<anonymous>:27:1
    at ContextifyScript.Script.runInThisContext (vm.js:50:33)
    at Object.runInThisContext (vm.js:139:38)
    at run ([eval]:1002:15)
    at onRunRequest ([eval]:829:18)
    at onMessage ([eval]:789:13)
    at emitTwo (events.js:126:13)
    at process.emit (events.js:214:7)
    at emit (internal/child_process.js:772:12)
    at _combinedTickCallback (internal/process/next_tick.js:141:11)

開発

イテレーション1

仕様を満たすアプリケーションをできるだけ早く試作するためにテストファーストプログラミングを実施する。実施にあたってまずTODOリストを作成する。

TODOリストを作成したらインクリメンタルな設計を実施する。実施するにあたってまず単一責任の原則に従い関心事を表すクラスを定義する。ここではFizzBuzzそのものを関心事として扱うことにする。

テストファーストでFizzBuzzとテストの関数を作成する。

クラスを定義したのでテストメソッドを作成に入る。まずTODOリストを元にアウトラインを作成する。

アウトラインをを作成したら一歩を示すテストに取り掛かる、TODOリストから失敗するはじめのテストを作成する。テストコードはアサートファーストでレッドになることを確認したら仮実装でグリーンにする。一つのプログラムには一つのことをうまくやらせることを心がける。アサーションは期待値を後に書く。

グリーンの状態になったら仮実装を経て本実装へ入る。明白な実装を行って最初のTODOリストを片付ける。条件分岐演算子を使って本実装を行う。YAGNIに従い今必要な機能だけを実装する。

引き続きTODOリストの2つ目に取り掛かる。はじめのテストを失敗させる。失敗することを確認したら明白な実装によりテスト結果をグリーンにする。最初のコードに追記するだけでは意図した結果にならなかったのでを変更して結果をグリーンにした。TODOリストの2つ目を完了にする。

続いて、TODOリストの3つ目に着手する。今回は複数の条件なので新たな演算子を使って実装する。実装に際してロジックの順番の間違いと判断条件の間違いとコピペによる間違いを犯していたが全てテストで気づくことができた。

TODOリストの割り算機能の最後のタスクに取り掛かる。今回のテストは前回のテストの派生系なので三角測量で実装する。まずは失敗するテストを追加する。明白な実装によりテストをグリーンにしてTODOリストの割り算機能のタスクを片付ける。テストのアウトラインがなくても意図は読み取れるようになったのでコメントは削除する。

続いて、TODOリストの残りの実行機能に取り組む。まずインクリメンタルな設計によりクラスのインタフェースを設計する。一つのプログラムには一つのことをうまくやらせることを意識する。

実行機能はまだ正しい実装が見えてこないので仮実装を経て本実装への前に三角測量を実施する。ローカル変数を初期化して繰り返しの制御構文で実行された最後の結果を返す実装をしたがテストにはまだパスしない。テストから演算子の間違いを発見しさらに仮実装の間違いがあることが判明したのでテストを修正してグリーンにする。

仕様を確認したところ間違いがあったので修正してテストも修正してグリーンになることを確認した。また、仕様に明記されていない条件が判明したのでTODOリストに追加する。

最初のイテレーションを完了させるにあたってふりかえりを実施する。

ふりかえり

Keep

  • 一つのプログラムには一つのことをうまくやらせる基本定理に従い単一責任の原則に沿ったクラス設計をを実施した。

  • できるだけ早く試作するためにインクリメンタルな設計テストファーストプログラミングと取り組むためのTODOリストを作成した。

  • 仕様に明記されていない項目をTODOリストに反映した。

  • TODOリストに従いテストファースト一歩を示すテストを作成した

  • まずはじめのテストアサートファーストで取り掛かりベイビーステップですすめて行った。

  • 何を書くべきかわかっているときは、明白な実装を行い、わからないときには仮実装を行い、まだ正しい実装が見えてこないときには三角測量を行いながら仮実装を経て本実装へと進めた。

Problem

  • Nodejsのスタティックメソッドの定義にはまる

Try

  • Jestを理解する

参照

[ ]: