達人プログラマー
第1章 達人の哲学
割れ窓理論
ネガティブは伝染する。問題を無視することでチーム全体がその考え方に流され、問題が蓄積し破滅に向かう。 「割れた窓=悪い設計、誤った意思決定、品質の低いコード」を放置スべからず。
石のスープ
みずらからの利益を守る側ではなく、石のスープで要求を引き出すための変化する触媒になる。
ゆでガエル
ゆるやかな変化(機能の追加やパッチによる変更)に気づかずにゆであがってしまうカエルにならないために、本来の構想を忘れず俯瞰すること。
第2章 達人のアプローチ
ETC原則
「Easier To Change」。良い設計は悪い設計より変更がしやすい。 いまつくってるものは本当にETCか問い続けよう!!
DRY原則
「Don’t Repeat Yourself」。「知識」や「意図」の繰り返しをしない。 類似のコードのことを繰り返しと読んでいるわけではない。コードが表現している知識が異なれば同じ内容でも異なるコード。 ドキュメントとコード間の2重化も繰り返し。開発者間、開発組織全体に対しても同様に言える。
直交性
関係しないもの同士の影響を排除する。単機能で目的に合わせて独立した凝集度の高いコンポーネントを設計する。 自分でコントロールできない属性に依存しないように設計を心がける。
曳光弾
今まで作ったことのない目標に対して、小さなコンポーネント単位で動くものを少しづつ作り、成果物のフィードバックをもとに目標を修正して、機能追加や修正を繰り返す。 プロトタイプはシステムのゴールを見定めるための使い捨てのコードを作成するが、曳光弾型の開発では動作する最小限のシステムを構築する。プロトタイプは曳光弾を発射する前の諜報活動みたいなものである。
プロトタイプ
今までつくったものがないものやリスクを測定する必要のあるものに適用できる。 プロトタイプの核心は構築のために得られた学習の経験にある。 適用できるケースは以下のパターン
- アーキテクチャ
- 新機能の追加
- 外部データの構造や内容
- サードパーティのツールやコンポーネント
- パフォーマンス
- ユーザーインターフェースの設計
見積もり
見積もりを正確にする一番の方法はプロジェクトを実際に経験することである。 要求から要件を洗い出し、リスクの分析、設計と実装、テストをおこない、ユーザーと検証をおこなう。 決まりをもとに見積もりと振り返りを繰り返して精度を高めていく。 象を1頭食べるには1くちずつ食べるしかないのだ。
第3章 基本的なツール
エンジニアリング日誌
作業内容やアイデア、学んだこと、落書きを記録する。
- 記憶より記録は確実
- アイデアを思いついたとき忘れないようにでき、今の作業に集中できる
- 書き留めることで新たな見識に気づける
第4章 妄想の達人
自分含めて信用しない
完璧なソフトウェアはつくることはできない。自らの過ちに対しても防衛的であるべきだ。
契約による設計(DbC)
Design by Concept。Effielという言語でモジュールの権利と責務を文書化する技法を提唱した。 処理を受け付ける条件は厳格に、終了後に確約する内容は少なくする。
- 事前条件:機能を呼び出すために満たすべき条件。呼び出し側の責務を定義
- 事後条件:機能が終了したときに機能が保証する内容
- 不変表明:処理終了後にクラスのメンバが不変であることを保証する
死んだプログラムは嘘をつかない
あり得ないなんてありえない。常に防衛的なプログラミングを心がける。 そして、エラーをにぎるのではなくエラーによって早めにクラッシュさせるべきである。
表明
起こるはずがないなら、それをチェックしよう。 ただし、エラー検出のために追加したコードで振る舞いを変えてしまわないように気をつけよう。(ハイゼンバグ) Go言語ではassertのような機能はないので、コードコメントによって表明している。
ヘッドライトを追い越そうとしない
ヘッドライトの視認距離より車の停止距離が長いときヘッドライトを追い越してしまう=見えないところに突っ込んでしまう。 ソフトウェア開発においても遠い未来に闇雲に前進せず、常にフィードバックを受けて軌道修正を加えながら見える範囲ですこしづつ進めるべし。 不確かな未来の予言に労力をかけるより、コードを交換可能なものにしておくことで柔軟に対処できるようにする。
第5章 柳に雪折れなし
尋ねるな命じよ
Tell, Don’t Ask. 別の関数でオブジェクトの内部状態を直接参照して更新すべきではない。オブジェクトの責務を考え、公開すべきメソッドを検討する。ドメイン知識の流出やカプセル化を守ることにつながる。
デメテルの法則
メソッドの呼び出しを連鎖させないこと。1ドットで完結させるべし。任意のオブジェクトが持っているプロパティやメソッドに対する仮定を最小にすること。ドットで繋いで参照すると結合度があがって変更影響が大きくなる可能性があるため、 ただし、言語がメソッドチェーンで処理を提供している場合は除く。
設定
外部設定でアプリをパラメーターで変更可能にする。 YAMLやJSONで静的なものとして管理することもできるが、APIとして設定の詳細を隠蔽するほうがよりよい。(CaaS:Configuration as a Service)
- 複数のアプリケーションで設定の共有ができる
- 設定の変更の適用
- 専用のUIとして管理できる
- 動的に変更できる
第6章 並行性
アクターモデル
共有メモリの同期をすることなく並行処理を実現する方法。個別の処理を定義されたアクターが処理を実行する。メッセージを受け取ったアクターが個別の処理を実行する。アクター間でメッセージを連携することで非同期に処理を実現する。
アクターモデルとアプリケーションアーキテクチャの関係 - nkty blog
第7章 コーディング段階
爬虫類脳に耳を傾ける
本能に耳を傾けうまくいかなくなったら足をとめてみる。ゴムのアヒルに話しかけてみる。行動してみる。
早めにリファクタリング、こまめにリファクタリング
Martin Fowlerのリファクタリングのヒント
- リファクタリングと機能追加を同時にしない
- リファクタリングより前にテストを十分に用意する。そして頻繁にテストを行う
- 局所的な箇所から変更とテストを行うことでデバッグの単位を減らす
テストはコードのユーザ第一号
テストができるコードを書く必要があるため、自然と疎結合を意識する必要がある。
プロパティベースのテスト
契約(入力の条件)と不変性(処理によって変わらないこと)を使ってテストを自動化する。 プロパティベースのランダムなテストにより誤った仮定を検出する。 GoだとFuzzingを使えばできる。
実世界の外敵から身をまもる
- 攻撃界面を最小化
- 最小権限の原則を厳守
- デフォルトをセキュアなものにする
- 機密データの暗号化
- セキュリティアップデートをおこなう
第8章 プロジェクトをはじめるまえに
要求はフィードバックループの中にある
要求を文書化する
本当の要求は相談者も把握していないため、分厚い仕様書をつくろうとしない。要求文書は計画のためにある。簡潔に記すことで相談者と開発者のフィードバックプロセスをまわしやすくする。
用語集をつくる
プロジェクトによって用語の意図が変わるため、1つの箇所でプロジェクトで使用する用語を定義する必要がある。整合性をもたせるためにすべてのスタッフがドキュメントにアクセスできる必要がある。
アジリティの本質
Agileはスタイルであって、決まったプロセスがあるわけではない。アジャイルソフトウェア宣言で明記された価値は、よりよい開発手法をみつけるための継続的な活動の中にある。アジャイルな方法で開発をするには、自分の立ち位置をきめて、目的に向けて最小の意味のある一歩をすすめ、評価する、フィードバックプロセスを回すことで継続的に改善をすることでアジャイルなチームになれる。
第9章 達人のプロジェクト
ことを成し遂げるためにスケジュールする
いつかやるは決して訪れない。チームの改善のための施策は必ずスケジュールを組む。
- システムのメンテナンス
- プロセスの振り返り
- 新しいテクノロジーの実験
- チームの学習とスキルの向上
流行を追いかけずに効果のあるものごとを実行する
方法論は背景にあるコンテキストがベースになっているため、方法に固執するのは無意味にである。自分たちにとって最適なものを取捨選択していく必要がある。
カーゴ・カルトに陥らないこと。