実践テスト駆動開発

実践テスト駆動開発 テストに導かれてオブジェクト指向ソフトウェアを育てる (Object Oriented SELECTION)

実践テスト駆動開発 テストに導かれてオブジェクト指向ソフトウェアを育てる (Object Oriented SELECTION)

実践テスト駆動開発を読んだ。サブタイトルは「テストに導かれてオブジェクト指向ソフトウェアを育てる」。TDDの手法そのものだけでなく「オンラインオークションの自動biddingクライアントの作成」という実践テーマを通して、オブジェクト指向ソフトウェアの柔軟性を高めるためのノウハウと、アジャイルやプロトタイピングなどの顧客に提供する価値を高める方法が書いてある。

うまくまとまらなかったのでメモしたところだけ箇条書き的に。

  • 予期せぬ変化を早くつかむためにもフィードバックループは欠かせない

    • 仕事をタイムボックスに分割し、設定された期間中に分析・設計・実装をすませてそれをデプロイする
    • デプロイ後実地からのフィードバックを得る
  • テストを書くことはどこまでやれば作業完了なのかを表すことになるので、不必要なフィーチャを盛り込んでしまうことを防げる

    • テストに書いている要件に不必要なフィーチャが入り込むことは防げないけど、テストに書いてある以上のことはしない
  • ひとつの仕組みで複数の概念を表現すると再利用が難しくなるのでコードの重複が生じる

    • オブジェクトは疎結合・高凝集であれ
  • オブジェクトが意思決定を行うとき、自身の情報かメッセージとともに渡された情報のみを使うことを心がける(デメテルの掟)

    • 例えば、引数で渡されたオブジェクトのメソッドの戻り値に対して何らかのメッセージを送るということは、2つ先のオブジェクトの構造まで知る必要があるので結合度が増してしまう
  • デプロイプロセスなどのあるプロセスを自動化するということは、そのプロセスを理解することと明文化することに繋がるのでお得

  • 先にシステム全体のテストを書くことは事前の設計を完璧にすることではない

    • 最初に決めたことはたいてい間違っているのだから、詳細についてはTDDでシステムを育てながら決めていきたい
    • システム全体のテストが動き始め、フィードバックループが実行されるということが重要(TDDサイクルに火を入れる)
  • テストはそのクラスが何をするかという説明書でもある

    • メソッドのテストをするのではなく振る舞いのテストを書く
    • メソッド名だけではそのクラスが何を実現可能なのか分からない
      • フィーチャが実現されているかの確認に集中することが大事という話だと思うがちょっと極端に聞こえる
      • そもそも実装を知らないと書けないテストの部分はコンポーネントとして切り出せそうだが、持たせるべきフィーチャ以外のものも同じ所で実装しちゃうこともある(時と場合によりという言い訳付きで)
  • 様々なコンテキストに適用できる高凝集なオブジェクトを作る

    • オブジェクトの組み合わせ方を変えるだけでシステムの変更が可能となるように
  • 値型の包括性

    • 複数のフィールドが一緒に使われている時、何らかの構造体が欠けている可能性がある
    • それらのグループに名前をつけてまとめ、値型をシンプルに保つ
  • Javaインターフェースはオブジェクト間のプロトコルとして定義する

    • インターフェースを実装したものはロールを表わす
      • クラスは実装上の詳細であり、他のオブジェクトが知ることではない
      • インターフェースを小さくすることでロールがいっそう明確になる
      • オブジェクト間の暗黙的な結合を最小限に抑え、取替え可能なものとする
  • 設計をいつ変更するのか

    • 既存のコードをコピペすることもあるとき、設計を変えるかどうか、時間との相談だというコンテキストで…

「ちょっと変えただけのコードをコピーして使おうとしている。これは馬鹿馬鹿しいし、時間のむだだ」なのか、「今はこれを修正すべきときではない。まだよくわかっていないのだ」なのか。この方針について、再現可能でシンプルなテクニックは存在しない。スキルと経験が必要なのだ。だから、開発者は自分たちの活動について深く考えるよう習慣づけなければならない。この後のコーディングのために自分たちの時間を投資するもっともよい方法は何か、と。その結果、今までとまったく同じようにやることになるかもしれない。しかし、少なくともそれについて考えてはいるのだ。

(p.179より)

  • 心変わり万歳

    • 前に考えていた知識は、開発プロセスを何度も繰り返して得た今の知識と比較すると間違っていたり明確ではない
    • 知識が不明確な状態で考えた構造は脆いので、既にある構造に合わせるのではなくどんどん変えていく
  • 複雑なテストデータの構築

    • テスト対処のオブジェクトを生成するために必要なオブジェクトがあるとき、オブジェクト生成部分が長くなったりしてテストする振る舞いに関係ない情報でうめつくされる
    • テスト対象のオブジェクトが変わった時にテストも大きく変更する必要があるため、テストが脆くなる
    • オブジェクト生成をテストデータビルダーに任せればオブジェクト生成に関するノイズがなくなり、テストに必要なパラメータの明示が可能となる
  • 4段階のTDDサイクル

    • レッド・レポート・グリーン・リファクタリング
      • レポートは診断メッセージを分かりやすくすること
      • レポートがないとコードをグリーンにすることばかりに気を取られてしまいレッド時のメッセージが分かりにくいと、次にレッドになった時に失敗の意味が分からなくなる

なるほどUnixプロセス

http://tatsu-zine.com/books/naruhounix

Unixプロセスについて少し詳しく知りたい人が読むための本。短くてサクサク読める。本編は知ってる人から見ると「はい」というような内容だけど、付録の内容が面白くてResqueとUnicornのコードを部分的に持ちだして実用例として分かりやすく説明している。

日本語で書かれたUnixプロセス入門のドキュメントについてはShinpeim/process-book · GitHubもある。内容レベルでのなるUniとの違いはデーモンプロセスの作り方と付録があるかないかという点で、それらの情報が必要なければ無料のドキュメントでも学習できる。

Hachioji.pmとEmacsでテストっぽいファイルを開きたい話

八王子あんまり関係ないところに住んでるけど面白そうだからHachioji.pmに遊びに行ってきた。 良かった。Hachioji.pmは良い。本当に良い。

Hachioji.pm #37 : ATND

1枚資料: Hachioji.pm #37

現在書いているコードに対応するテストを開きたい欲求があって、実現への第一歩として、現在編集しているファイル名にtestとかspecとか付けてhelm-ls-gitで開くようにしてみた。helmで候補として表示されるファイルがテストっぽかったら決定して開く。便利。いつもファイル名+testとかを手で打ってたからそれを自動化しただけなので、自分にとって便利なのは当たり前だけど。

ファイル名ベースの解決策だと限界があるけど、テストクラスが含まれているファイルを探したり、他にもやり様があると思う。

DDD本を読んだ感想

DDD本を1周しての雑多な感想。

エリック・エヴァンスのドメイン駆動設計 (IT Architects’Archive ソフトウェア開発の実践)

エリック・エヴァンスのドメイン駆動設計 (IT Architects’Archive ソフトウェア開発の実践)

コーディングに早さと質の、うまい早い安いのバランスを求めたいのだけどモデリングでうだうだと悩んでて遅筆になっちゃってるし、最初は名案やと思ってた方向性で突き進んだ結果、結局コレジャナイ感の高いコードができあがる。

近況を述べますとリポジトリとかサービスだとかの用語をネットや会話やコードで見るようになって、俺の中でDDDが話題沸騰中という雰囲気になっていた。リポジトリって何するの?サービスじゃ抽象的すぎでよく分からん。何も考えずパターンに当てはめてるだけでは。なんて中身も見ずに思っていた。でもパターンというものは良いもので、人との認識をある程度共通化できるコミュニケーションツールとしてや、昔からのノウハウが蒸留された知識として決断を支援してくれることもある。僕が用語を理解していないだけで、実はかなり便利なものなのではという流れで読み始めた。

DDD本の内容

DDDでは取り組むドメインを理解し続けようと努め、その理解を具現化することに重点を置く。ドメインを理解していなければ、一時的にしか使われないようなところに力を入れてしまったりと的はずれな開発方針になる。なので、プロダクトの重要な部分においてドメインエキスパートと開発者達はプロダクトの成長という目的のために、二人三脚で進む。

ドメインエキスパートの考えている概念とそれを表現するコードの前提に齟齬があると、手戻りが発生することになる。概念とプロダクトのコードはモデルレベルでマッピングできるよう努めると、ドメインエキスパートと開発者間の溝は小さくなる。概念をそのままコードとして表現できれば、ソフトウェアとして表現したいものが全然表現されていなかった!ということが減る。

ドメインに対する深い理解を得るには時間がかかるし、そもそも完全な理解というものは無いので、探求し続ける必要がある。その中でブレイクスルーがあったり、理解がめちゃくちゃ間違ってたりで今まで具現化していたものに大幅に修正を加える必要が出てくる。そういう状況がきても対処できるような、しなやかな設計にできる高度なスキルが必要になる。

というのがDDD本を読んで知ったこと。納得のいく、まっとうな話だと思う。

DDDは、オブジェクト指向コミュニティの間で長年培われてきたドメインモデリングのノウハウやベストプラクティスを集大成した、1つの設計思想/哲学です。ドメインモデルをこれから構築しようとする人に、設計上の判断を下すための枠組みと、ドメイン設計について議論するためのボキャブラリを提供するものです。

http://wwww.ogis-ri.co.jp/otc/hiroba/technical/DDDEssence/chap1.html

DDD本は上記のように、ボキャブラリを提供してくれることが一番良い所だと感じている。モデリングに関するブログ記事とかコードとかも読みやすくなる。

DDDを適用するとき

ドメインへの理解があって開発も自分でするなら、自分が書きやすい・保守しやすいと思う方法を取れば良い。でも、自分がベストだと思っている方法が人から見ると分かりにくかったりすることは当たり前にある。ドメインという概念をベースに抽象化されたパターンは誰にでも分かりやすそうだと思うし、蒸留されたドメインモデルも扱いやすそうだと思う。出来上がっているモデルへの分かりやすさや手の入れやすさという点では良いと思うけど、高度なモデリングスキルをもってチーム全体で開発していくという点が厳しい。DDDを本格的に採用するにはドメインに対する深い理解があるドリームチームが望まれる。なので、できる部分はDDD本に書いてあることを実践しましょうという印象をもった。

個人的にはドメインへの理解がどうのこうのというよりも、ドメイン知識に頼らずとも取り回しやすいコードを書こうという意識が第一にありたいなと思う。そういう点では、レイヤ化アーキテクチャとかのDDD本に書いてあるいくつかのパターンが有効に使える。次の段階でドメインモデルの蒸留等のドメインへの理解を元にしたパターンがくる。

最後の結論に書いてあることが良かった。基本的に良い話が多く、しっかりプログラミングしよう!!!!!!!!!という気持ちになる。

実際に動く複雑なソフトウェアを、素人が作成できる時代にはなっていない。初歩的なスキルを持ったプログラマを大勢集めても、ある種のソフトウェアを作り出すことはできるが、そうやって作れるのは、土壇場にある企業を救い出せるような類のものではない。

agで検索しマッチしたファイル名をpercolで絞り込み、エディタで開く

$EDITORがvimemacsみたいに+LINEを受け付けるのだったらうまく動くと思う in zsh

最近はメモ環境がMarkdownファイルをDropboxに置くだけみたいになってて、あとは上記のスクリプトで検索している。ディレクトリ階層をタグ代わりに使ってるのが少しだるいかなと思っている昨今。

ディレクトリ階層を視覚的に&手軽に作ってメモをとれるという点では、Write for Macのベータ版が良かった。正式版出たら買う。

それにしてもpercolはanythingライクな絞り込みインターフェース厨にはたまらない。

あけまして

おめでとうございます。今年もよろしくお願いします。

f:id:jewel12:20140102033350p:plain

去年買ったものを思い出してたら、Bamboo Touchを買ったのを思い出して、1回も使ってないのはさすがにまずいだろうと引っ張りだして描いた絵。思い立ったが吉日の勢いで描いたので、お絵かき掲示板クオリティなのはご愛嬌。最近は全然描いてないので、元から下手なのがどんどん下手になっている……。

今年はもう少し汎用的な力を積極的に付けていきたい

新しい技術がこれからもいろいろ出てくるはずだけど、大抵のものは既にある技術や考え方がベースにあると思う。例えば、副作用のない機能は状態を考慮しないで済むから複雑にならなくて嬉しいよねということを知っていれば、Immutable Infrastructureという考え方に至るまでの道のりは短くなる(知識に捕らわれて遠回りするという可能性も考えられるけど、それは別な話)。こういうベースになりそうな考え方を知っておくと、新しい技術への理解が早くなったりするはずだし、自分でも何か新しいものを作るときに応用できる。何かを学ぶときは、学ぶものから汎用的に使える部分を意識的に切り出せると良いと思う。

今年は人とものを作るときにうまくいく方法についても何か学べたらと思う。それはコミュニケーションの仕方とか、システムの構成とか多岐に渡るけど、特にどんなインターフェースにすれば取り回しやすいかとかの、システムの構成に関わる部分について知りたい。

  1. 誰かが作った部分に手を加えるとき、テストが無かったりコンポーネントが大きかった時にどう対処すればいいのか
  2. 自分の作った部分に他人が手を加えるとき、容易に手を加えることができるか
  3. 不必要なものを作っていないか

というのが最近、自分にとって課題だな思うことのいくつか。 これらを考えることはコストでもある。2はテストを書いたり取り回しやすい設計を熟考することが必要になるし、3はシステム構成に関する情報の共有のため、ドキュメントを書くこともある。取り扱う対象にこれらのコストが果たして必要なのか判断するには〜〜〜というのも気になっている。

とりあえず、去年よりも良い年を過ごしましょう。