『テスト駆動開発』第1部をC#で写経してみる(第3章)

第3章 三角測量

第3章ではValue Objectを作成し、別名参照問題を防ぐ方法を見ていく。

まずはDollarオブジェクトの等価性について確認する。

namespace TddStudyTest
{
    [TestClass]
    public class MoneyTest
    {
        [TestMethod]
        public void TestMultiplication()
        {
            Dollar five = new Dollar(5);
            Dollar product = five.times(2);
            Assert.AreEqual(10, product.amount);
            product = five.times(3);
            Assert.AreEqual(15, product.amount);
        }

        [TestMethod]
        public void TestEquality()
        {
            Assert.IsTrue(new Dollar(5).Equals(new Dollar(5)));
        }
    }
}

TestEquality()を追加した。当然のごとくテストは失敗するので、trueを返すだけの仮実装を行う。

namespace TddStudy.Money
{
    public class Dollar
    {
        public int amount;

        public Dollar(int amount)
        {
            this.amount = amount;
        }

        public Dollar times(int multiplier)
        {
            return new Dollar(this.amount * multiplier);
        }

        public override bool Equals(object obj)
        {
            return true;
        }
    }
}

テストが通ったので、今度は別の等価性確認を行ってみる。

namespace TddStudyTest
{
    [TestClass]
    public class MoneyTest
    {
        [TestMethod]
        public void TestMultiplication()
        {
            Dollar five = new Dollar(5);
            Dollar product = five.times(2);
            Assert.AreEqual(10, product.amount);
            product = five.times(3);
            Assert.AreEqual(15, product.amount);
        }

        [TestMethod]
        public void TestEquality()
        {
            Assert.IsTrue(new Dollar(5).Equals(new Dollar(5)));
            Assert.IsFalse(new Dollar(5).Equals(new Dollar(6)));
        }
    }
}

追加したテストが失敗するので、ここで透過性比較を一般化する必要性が見えてくる。

namespace TddStudy.Money
{
    public class Dollar
    {
        public int amount;

        public Dollar(int amount)
        {
            this.amount = amount;
        }

        public Dollar times(int multiplier)
        {
            return new Dollar(this.amount * multiplier);
        }

        public override bool Equals(object obj)
        {
            var dollar = (Dollar)obj;
            return amount == dollar.amount;
        }
    }
}

equals()をoverrideしたときはHashCode()もoverrideする必要があるが、今の時点ではスルーする。

このように、2つの異なる視点からのテストメソッドを作成することにより、コードの一般化を行うことができた。『テスト駆動開発』では、この手法を三角測量と呼んでいる。

雑感

三角測量を用いてコードの一般化を行うケースは少ないかもしれないが、本書に書いてある通り、どうやってリファクタリングしてよいか分からないときや、設計に迷ったときは重宝しそうだ。

Scythe拡張 – 彼方よりの侵攻 開封レビュー

着弾

昨年発売の本体と同じく予約開始直後に瞬殺されたScythe日本語版の拡張が届いた。(決して大鎌戦役とは言わない)予約に際してまたしてもJoshinに助けられた。本当にありがとうJoshin。行ったことないけど。そして今Amazon見たら普通に売っているという…。

外観

外観はこんな感じ。大きさはパンデミックを縦に割った半分ほど。厚さはパンデミックの倍ほど。中身は追加の二勢力分のトークンなので、箱はそれほど大きくない。

開封

さっそく開けて中身を取り出してみる。

まずは緑のアルビオン氏族。

コナー&マックス!スカートのおっさんとイノシシ!…イノシシか?

続いて紫の戸川幕府。

彰子と次郎!AKIKOとJIRO!アキコて…。アキコからほとばしるコスプレ感。あと帯刀するのは腰の左側だと思うぞ。(クソリプ)

雑感

本体はまだ三回ほどしか遊べていないが、これでようやく全勢力が揃った。夢の7人プレイができる日は来るのか…。しかしやはりScytheのこまごましたコンポーネントは本当に素晴らしい。眺めているだけで多幸感に包まれる。積まないようにせねば。

『テスト駆動開発』第1部をC#で写経してみる(第2章)

第2章 明白な実装 (Degenerate Objects)

第1章に引き続き進めていく。

Dollarオブジェクトの times メソッドに以前とは異なる引数を渡し、期待値が得られるかを確認したい。現段階ではどう考えてもテストは失敗するのだが、失敗させるのが重要なのでテストを追加してみる。

namespace TddStudyTest
{
    [TestClass]
    public class MoneyTest
    {
        [TestMethod]
        public void TestMultiplication()
        {
            Dollar five = new Dollar(5);
            five.times(2);
            Assert.AreEqual(10, five.amount);
            five.times(3);
            Assert.AreEqual(15, five.amount);
        }
    }
}

テストを実行し、失敗することを確認後、即座にグリーンバーを目指すため、times メソッドに対して以下の修正を行う。

  • 戻り値をDollarクラスに変更
  • multiplieramout を掛け合わせて新しい金額のDollarオブジェクトを返す
namespace TddStudy.Money
{
    public class Dollar
    {
        public int amount;

        public Dollar(int amount)
        {
            this.amount = amount;
        }

        public Dollar times(int multiplier)
        {
            return new Dollar(this.amount * multiplier);
        }
    }
}

上記修正に伴いテストは以下のようになる。

namespace TddStudyTest
{
    [TestClass]
    public class MoneyTest
    {
        [TestMethod]
        public void TestMultiplication()
        {
            Dollar five = new Dollar(5);
            Dollar product = five.times(2);
            Assert.AreEqual(10, product.amount);
            product = five.times(3);
            Assert.AreEqual(15, product.amount);
        }
    }
}

これでグリーンバーが復活した。

雑感

第1章ではベタ書きの値を徐々に変数に置き換えていく仮実装を行ったが、今回はいきなり実装に入る明白な実装を行った。具体例から徐々に抽象度を上げていく仮実装の方がセーフティーということか。

しかしテストコードの修正から入るというのにはまだまだ慣れそうにない。

『テスト駆動開発』第1部をC#で写経してみる(第1章)

はじめに

和田卓人さん訳の『テスト駆動開発』を以前に読了していたが、ふと思い立ったので復習がてら第1部の内容をC#で写経してみることにした。第1部は債権ポートフォリオ管理システムを多国通貨対応させる、というシナリオで話が進む。なお、写経に際して前提条件や細かい説明は省くので、詳細は実際に『テスト駆動開発』を読んで確認してみてほしい。

また、第1部は全部で17章あるので、実際にコードを書きながらチマチマ進めていきたい。

写経環境

言語

いわずもがなC#

IDE

Visual Studio 2017 Professional

テスティングフレームワーク

MSTest v2

第1章 仮実装 (Multi-Currency Money)

いきなりテストコードを書いてみる。

namespace TddStudyTest
{
    [TestClass]
    public class MoneyTest
    {
        [TestMethod]
        public void TestMultiplication()
        {
            Dollar five = new Dollar(5);
            five.times(2);
            Assert.AreEqual(10, five.amount);
        }
    }
}

この時点ではコンパイルエラーが発生する。Dollarクラスなど存在しないので当然だ。

そこでDollarクラスを作成し、times メソッドと amount フィールドを追加する。

namespace TddStudy.Money
{
    public class Dollar
    {
        public int amount;

        public Dollar(int amount)
        {
        }

        public void times(int multiplier)
        {
        }
    }
}

コンパイルエラーは取れたが、この状態でテストを実行させるとエラーになるので、最小限の対応を行ってみる。

namespace TddStudy.Money
{
    public class Dollar
    {
        public int amount = 10;

        public Dollar(int amount)
        {
        }

        public void times(int multiplier)
        {
        }
    }
}

10を2と5に分解し、テストコードと値を重複させてみる。

namespace TddStudy.Money
{
    public class Dollar
    {
        public int amount;

        public Dollar(int amount)
        {
        }

        public void times(int multiplier)
        {
            this.amount = 5 * 2;
        }
    }
}

仕上げにコンストラクタ内で amout の代入を行い、 times メソッド内で amout フィールドを参照するようにする。

namespace TddStudy.Money
{
    public class Dollar
    {
        public int amount;

        public Dollar(int amount)
        {
            this.amount = amount;
        }

        public void times(int multiplier)
        {
            this.amount *= multiplier;
        }
    }
}

これで一旦テストがパスできる状態になった。めでたしめでたし…ではないので、第2章に続く。

雑感

テスト対象クラスが存在しない状態からテストコードを書くことが非常に新鮮な体験だった。
小刻みな修正を行って一歩ずつ歩みを進めつつ、テストをパスしてグリーンバーを眺める安心感は何物にも代えがたいが、仮初めのグリーンバーなことも多々ある点に要注意。

プログラマの数学 第2版 雑感

再読

エンジニア界隈で絶大な知名度を誇る結城浩さんの名著、『プログラマの数学』の第2版が2018年1月に出版された。第2版では書籍サイズも小さくなり、付録として機械学習についての章が追加された。プログラミングを始めて2年目くらいの時期に第1版を購入して読んだ経験はあるが、すっかり内容を忘れていたため、読み直した上での雑感をメモしてみる。

“プログラマの数学 第2版 雑感” の続きを読む

クランズオブカレドニア開封レビュー

着弾

今年購入を決めていたボドゲの一つ、クランズオブカレドニアが先日届いた。昨年のスカウトアクションで第1位ということもあり買えるか心配だったが、テンデイズゲームスさんで無事購入できた。

開封

シュリンクを破ってみる。大きさ、厚さともにパンデミックと同じくらいか。(分かりづらい)箱を開けて中身をだしてみる。小さなコマがたくさんあるので適当に並べてみる。思ったよりも小さかったが、それがさらにコマの可愛さを増長させている。

牛乳とパン可愛すぎなのでは。

お預け

ルールブックは読んだが、まだプレイはできていない。一つ一つのルールはそれほど複雑なではないが、選択肢が多くて迷いそう。何にせよ早くプレイしたい。

2018年になったけど2017年を振り返りつつ今年の目標を掲げてみる

今更だが2017年を振り返りつつ2018年の目標を掲げてみる。

2017年の振り返り

仕事面

退職

新卒でSIerに入って早7年弱、娘の誕生を目前にして転職を考え出していた。受託メインのビジネスモデルへの疑念、このままここにいていいのだろうか、スーパーマンのようにバリバリ働く上司のようにはなれない、もっと家庭を顧みた生活が送れるような労働環境に身を置きたい、等々の思いが積もりつつあったある日の深夜、帰宅してなんとなく某エンジニア用転職サイトを開いてみた。

数か月前に登録したそのサイトを真面目に使ってみるのは初めてだった。自分がメインで使ってきたC#で検索すると、ヒット数が恐ろしく少ない。しかしその中にひとつだけ気になる応募があった。Web系なのに落ち着いた雰囲気で、サービス内容も硬めで自分に合いそうだと思い、早速コンタクトを取ってみた。すると翌日返信が来たので日程調整して訪問。イメージ通りの会社で良さそうだ。後日若手の方々と食事の席を設けてもらい、色々質問させていただく。やはり良さそうだ。後日CEOと面接し、一発OKをもらえた。

という流れで初めての転職活動はわずか3週間で終了した。次が決まれば後は退職あるのみ。退職届を社長に提出し、3月いっぱいまでの有休消化をスタートさせた。(有休消化といいつつ実態は育児休暇でヘロヘロになったことは後述。)

新たなスタート

4月からいよいよ新職場での仕事が始まった。担当はWindowsデスクトップアプリ。前任者から引き継ぐ形でいきなりのぼっち開発がスタートした。

前職では諸事情によりVisualStudio2008という旧石器時代的IDEを2017年まで使い続けていたのだが、今回はいきなりVisualStudio2017である。9年飛び越えてしまった。アイキャンフライ。Windows FormsしかやってこなかったのでWPFに戸惑う。未だにWPFかよと思うかもしれないが、Windows7のサポートがまだまだ続く限りそこは仕方ない。え?Windows8.1?聞こえない聞こえない。

そんなこんなでぼっち開発を続けて早10か月。新規開発と障害対応に追われながら、ようやく一人で仕事を回せるようになってきたと思う。前職ではなんちゃって営業から開発、顧客サポートまでなんでもやらざるを得ない状況だったので、業務範囲が狭まり開発に専念できるようになったことは本当にありがたい。また、肝心の開発業務でも前職での経験が生きていると感じることが多くなった。鍛えてくれた前職上司には感謝しかない。

日々の成長を感じつつ、ぼっち開発は続く。いや続けたくないけど。一緒にBtoB SaaS開発をしてくれるC#erの方、お待ちしてます。

家庭面

娘が生まれた。難産ではなかったが、出産直後に妻の出血が止まらず大学病院に緊急搬送→手術という肝を冷やす出産だった。母子が退院後、いよいよ赤ちゃんとの生活が始まった。慣れない。寝た後も息が止まっているのではないかと思って気が気でない。寝不足でヘロヘロな毎日が続いた。

有休消化という名の育児休暇がひと月半ほどで終わり、4月からは仕事に復帰。娘の成長は止まらない。日々重くなる娘。夜は抱っこしないと寝ない。仕事から帰宅後に抱っこして寝かしつける日々。腰の痛みが酷くなりヘルニア気味に。育児戦隊ヘルニアン。0歳児に破壊されるアラサーの腰。今は多少回復しているが騙し騙し状態の日々。娘よ、もう抱っこはしてやれん。

そんな娘ももうすぐ一歳になろうとしている。特に大きな病気も怪我もせず、本当にありがたい。父親に似てマイペースで、母親に似て好奇心旺盛な娘。父親に似て目が小さく、母親に似て顔が丸い娘。そろそろ歩いてほしいが、まだまだ歩く気配なし。誰かに似てマイペースだからだろう。

趣味面

義姉夫妻を完全にボドゲ沼に沈めることに成功した一年だった。特に宝石の煌めきを買ってもらえたのはありがたかった。しかし義兄には歯が立たない。悔しいのでiPhoneのアプリを買って特訓中。

今年一番の買い物はScythe。チマチマしたコンポーネントがぎっしりで満足度が大変高い。Amazonでは予約開始→即売り切れが続いて買えないかと思ったけど、Joshinに助けられた。ありがとうJoshin。転売ヤーは本当に滅びてほしい。

2018年の目標

仕事面

エンジニア採用

もう一人のWindows担当者を採用し、ワンオペ開発からの脱却を図りたい。もう一人いないと機能開発と不具合対応に追われて諸々の整備が全く進まない。

C#

基本に立ち返ってWPFへの理解を深める。UWPも忘れずに。

QA

二足の草鞋になるが、品質を担保しながら開発できるようなスキルを高めていきたい。新機能より品質アップを。

LTデビュー

高望みかもしれないけどこの目標を掲げてみる。どこかでの記事で読んだけど、LTを始めるに、まずはゆるいイベント(=失敗してもごめんなさいで許されるレベル)でLT枠を抑え、その後でLT内容を考えるのが良いらしい。これならハードルが低そうだ。しかしニッチな分野の開発をしている身としては、自分のネタに興味がある人がどれほどいるのだろうかとも思う。とはいえまだ慌てる時間じゃないと言って登壇を先延ばしにすると、いつまでたっても登壇しないのが目に見えているので、さっさと登壇したほうが良い気がする。頑張れ明日以降の俺。今日の俺は疲れたので寝る。

仕事とプライベートの狭間

今まで仕事とプライベートは明確に区別していたが、最近はプログラミング周りでその境界が薄れつつある気がする。家族に迷惑を掛けない範囲でコードを書いていきたい。一番やりたいのはXamarin。自宅用にMacBookProほしい。お金がないWindows開発者の苦悩は続く。

あとブログに開発ネタを最低月に一回は書きたい。気づいたら育児と開発ポエムとボドゲのことしか書かなそうで怖い。

家庭面

妻の育児休暇が終わり、仕事に復帰予定なのでサポートを頑張る。保育園の送り迎えも頑張る。おそらく送りは毎日。迎えは週1でいきたい。まずは保育園に受からないと何もできないけど。早生まれに厳しすぎるこんな世の中じゃ。

趣味面

今年のマストバイは

  • クランズオブカレドニア
  • センチュリー・イースタンワンダーズ
  • ワイナリーの四季拡張
  • Scythe拡張

で確定済み。

会社で発足した非公式ボドゲ部が停滞気味なので復活させたい。もういっそ公式部活にして定期開催にしたほうが良いかもしれないと思う今日この頃。


そんなわけで今年も色々あると思うけどあっという間に来年になるのだろう。慌てず一歩ずつ行こう。

 

ブログを始めてみた

この地に至るまで

迷走

日々を振り返る場所が欲しい。技術ネタだけでなく、とりとめのない日常を書き殴る場所が欲しい。一緒に働いてくれる仲間が欲しい。もしかしたら採用に繋がるかもしれない。ならばいっちょブログでも書いてみるかと思い立ち、数あるブログサービスを吟味すること数時間、はてなブログとMediumに候補を絞った。シンプルでかっこいいというミーハーな気持ちでMediumを選択し、夜中のテンションで書いて即公開。しかし、公開直後に何とも言えない閉塞感を感じた。このまま記事を書き続けて自分はMediumの世界の外に出られるのだろうか、Mediumの中でしか生きられないのではないか、と虚しく思ってしまった。記事を公開するまでそのことに気づけなかった。浅はかなり。

気づき

しょげていても仕方ない。何かを書いてみたいという気持ちは抑えられない。悶々とすること数日、ブログ系サービスに依存しない、自分だけが好き勝手やれる場所を求めてWordPressに辿り着いた。恥ずかしながらWordPressが何なのかよく分かっていなかった。が、調べれば調べるほど自分に合っているように思えた。テーマを色々変えられるとか素敵。レンタルサーバーを借りたりドメインを取得したり、ブログ開設にはお金がかかりそうだが、運用コストは月1000円程度。お父さんな、小遣いの範囲内で何とかやっていこうと思うんだ。

悩み

ここまで来たらあとは突っ走るだけと思いきや、今度はドメイン名が決められない。悩みに悩んだ。通勤中もずっと悩んだ。悩みぬいてこの結果となった。悩みぬいてこれか。深夜のテンションで決めた気もするが気にしない。

由来

自分の色を出すため、ブログ名とドメイン名は一致させたかった。ブログ名は割と初期に決まっていた。


「それはそれとして」

我が故郷が生んだ仏教学者、鈴木大拙の言葉だ。私はこの言葉がとても好きだ。常に前に進もうとする意志を示す言葉だと思っている。この言葉をブログ名に拝借した。ありがとう大拙先生。

そんなこんなで

ドメインを取得し、レンタルサーバーと契約。即ブログを開設できた。なんて便利な世の中。WordPressのテーマはおいおい変更したい。楽しみ。

自己紹介

ここまで来てようやく自己紹介である。ごめんなさい。神保町にあるSaaS提供企業でWindowsデスクトップアプリの開発をしている30歳。一児の父。趣味はボドゲ。SaaSでWindowsデスクトップアプリというニッチなことをやっており、ワンオペ開発が続いている。共に戦ってくれる仲間がほしい。というか助けていただきたい。

何を書くか

一応開発者なので開発ネタメインにしたいところだが、自分だけが好き勝手できる場所なので、思うがままになんでも書いてみたいと思う。余談だが、ごった煮な記事を書くような世界観ではなさそうだと感じたのも、Mediumをやめた理由の一つだったりする。というわけで以下のような記事を書いていきたい。

  • 技術ネタ
    • C#メイン(WPF, UWP, Xamarin)
  • その他開発ネタ
    • QAとかチームビルディングとかTDDとか
  • 育児
    • 娘がもうすぐ1歳
  • ボドゲ
    • 好きなジャンルはワーカープレースメント

おわりに

軽い自己紹介程度に留めるつもりがここ数日間の振り返りになってしまった。だがそれもよし。それはそれとして。