somemo programming etc.

プログラマ、雑記、プログラミング関係はLinkから、数式はこっちでまとめていることが多い

【TDD】テスト駆動開発入門16章完了

これで最後になりました。合計式と単項式の加法を行えるようにします。

Expressionにplusを追加

Sumにplusメソッドを実装します。考えられるパターンは、+単項式と、+合計の2つです。Moneyのplusも+合計が考えられます。

まずは式にplusメソッドを定義します。

と思いましたが、Money#plusの引数がMoneyだったので、まずExpressionに直しておきました。

Sumにもplusを仮実装して、グリーンバーにしておきます。

/**
 * 加法
 *
 * @param Expression $addend 加数
 */
public function plus(Expression $addend);

/**
* (non-PHPdoc)
* @see Expression::plus()
*/
public function plus(Expression $addend) {
    ;
}

合計#plus(式)

以下のテストコードで試します。

/**
 * レートが2:1の場合、(5ドル+10フラン)+5ドル=15ドルのテスト
 */
public function testSumPlusMoney() {
    $five_dollars = Money::dollar(5);
    $ten_francs   = Money::franc(10);

    $bank = new Bank();
    $bank->addRate('CHF', 'USD', 2);

    $sum = $five_dollars->plus($ten_francs)->plus($five_dollars);
    $result = $bank->reduce($sum, 'USD');
    $this->assertEquals(Money::dollar(15), $result);
}

Sum#plusはまだ仮実装なので、何も返さないため失敗します。

以下のように実装します。Sumの引数に渡せば、最終的に換金するときにSumのreduceによって変換されるので問題ありません。

return new Sum($this, $addend);

Sum#times(乗数)の実装

Sumも式なのでMoneyと同様にtimesを実装するようです。

その前に、式の持つ仕様をまとめておくために、Money#timesをExpressionに移動しておきます。

/**
 *
 * 総額の倍変更
 */
public function times($multiplier);

/**
 * (non-PHPdoc)
 * @see Expression::times()
 */
public function times($multiplier) {
    ;
}

下記のテストコードで、timesをテストします。

/**
 * レートが2:1の場合、(5ドル+10フラン)の2倍=20ドルのテスト
 */
public function testSumTimes() {
    $five_dollars = Money::dollar(5);
    $ten_francs   = Money::franc(10);

    $bank = new Bank();
    $bank->addRate('CHF', 'USD', 2);

    $sum = $five_dollars->plus($ten_francs)->times(2);
    $result = $bank->reduce($sum, 'USD');
    $this->assertEquals(Money::dollar(20), $result);
}

Sumの加数と被加数に対して、Moneyのようにtimesメソッドを実行することでSumのtimesとします。

return new Sum($this->augend->times($multiplier), $this->addend->times($multiplier));

これでようやく完成です。plusが被っているけど、解決法が分かりません・・・。インターフェースだと限界ですかね。