脳に収まるコードの書き方 ―複雑さを避け持続可能にするための経験則とテクニック(Mark Seemann)
書籍情報
- 著者:Mark Seemann(著), 吉羽龍太郎(訳), 原田騎郎(訳)
- 発行日:2024-06-14
- ISBN:9784814400799
- URL:https://www.oreilly.co.jp/books/9784814400799/
書籍目次
- 推薦の言葉
- シリーズエディターによるまえがき
- はじめに
- 第I部 加速
- 1章 アートかサイエンスか
- 1.1 家を建てる
- 1.1.1 プロジェクトの問題
- 1.1.2 フェーズの問題
- 1.1.3 依存関係
- 1.2 庭を育てる
- 1.2.1 何が庭を育てるのか?
- 1.3 エンジニアリングに向けて
- 1.3.1 工芸品としてのソフトウェア
- 1.3.2 経験則
- 1.3.3 ソフトウェアエンジニアリングの初期の概念
- 1.3.4 ソフトウェアエンジニアリングの前進
- 1.4 まとめ
- 1.1 家を建てる
- 2章 チェックリスト
- 2.1 記憶の補助
- 2.2 新規コードベースのためのチェックリスト
- 2.2.1 Gitを使え
- 2.2.2 ビルドを自動化せよ
- 2.2.3 エラーメッセージをすべて有効にせよ
- 2.3 既存のコードベースにチェックを追加する
- 2.3.1 漸進的改善
- 2.3.2 組織をハックする
- 2.4 まとめ
- 3章 複雑さに対処する
- 3.1 目的
- 3.1.1 持続可能性
- 3.1.2 価値
- 3.2 なぜプログラミングは難しいのか
- 3.2.1 脳のメタファー
- 3.2.2 コードは書く回数より読む回数のほうが多い
- 3.2.3 可読性
- 3.2.4 知的労働
- 3.3 ソフトウェアエンジニアリングに向けて
- 3.3.1 コンピューターサイエンスとの関係性
- 3.3.2 ヒューマンフレンドリーなコード
- 3.4 まとめ
- 3.1 目的
- 4章 バーティカルスライス
- 4.1 動くソフトウェアから始める
- 4.1.1 データ入力からデータ永続化まで
- 4.1.2 最小のバーティカルスライス
- 4.2 ウォーキングスケルトン
- 4.2.1 特性評価テスト
- 4.2.2 Arrange-Act-Assert
- 4.2.3 静的解析の節度
- 4.3 外側から内側へ(アウトサイドイン)
- 4.3.1 JSON を受け取る
- 4.3.2 予約をポストする
- 4.3.3 ユニットテスト
- 4.3.4 DTOとドメインモデル
- 4.3.5 フェイクオブジェクト
- 4.3.6 リポジトリインターフェイス
- 4.3.7 リポジトリ内での作成
- 4.3.8 依存を構成する
- 4.4 バーティカルスライスを完成させる
- 4.4.1 スキーマ
- 4.4.2 SQLリポジトリ
- 4.4.3 データベースの構成
- 4.4.4 スモークテストの実施
- 4.4.5 フェイクデータベースによる境界テスト
- 4.5 まとめ
- 4.1 動くソフトウェアから始める
- 5章 カプセル化
- 5.1 データの保存
- 5.1.1 変換の優先順位
- 5.1.2 パラメーター化テスト
- 5.1.3 DTOをドメインモデルにコピーする
- 5.2 バリデーション
- 5.2.1 不正な日付
- 5.2.2 レッド/グリーン/リファクタリング
- 5.2.3 自然数
- 5.2.4 ポステルの法則
- 5.3 不変条件の保護
- 5.3.1 常に有効
- 5.4 まとめ
- 5.1 データの保存
- 6章 三角測量
- 6.1 短期記憶と長期記憶
- 6.1.1 レガシーコードと記憶
- 6.2 定員
- 6.2.1 オーバーブッキング
- 6.2.2 悪魔の代弁者
- 6.2.3 既存の予約
- 6.2.4 悪魔の代弁者vsレッド/グリーン/リファクタリング
- 6.2.5 どれだけテストを書けば十分か?
- 6.3 まとめ
- 6.1 短期記憶と長期記憶
- 7章 分解
- 7.1 コードの腐敗
- 7.1.1 しきい値
- 7.1.2 サイクロマティック複雑度
- 7.1.3 80/24ルール
- 7.2 脳に収まるコード
- 7.2.1 ヘックスフラワー
- 7.2.2 凝集
- 7.2.3 特性の横恋慕
- 7.2.4 ロスト・イン・トランスレーション
- 7.2.5 検証せずにパースする
- 7.2.6 フラクタルアーキテクチャー
- 7.2.7 変数を数える
- 7.3 まとめ
- 7.1 コードの腐敗
- 8章 API設計
- 8.1 API設計の原則
- 8.1.1 アフォーダンス
- 8.1.2 ポカヨケ
- 8.1.3 読む人のために書く
- 8.1.4 コメントよりもわかりやすい名前のコードを
- 8.1.5 名前をXで置き換える
- 8.1.6 コマンドクエリ分離
- 8.1.7 コミュニケーション階層
- 8.2 API設計の例
- 8.2.1 メートル・ドテル
- 8.2.2 カプセル化されたオブジェクトとやりとりする
- 8.2.3 実装の詳細
- 8.3 まとめ
- 8.1 API設計の原則
- 9章 チームワーク
- 9.1 Git
- 9.1.1 コミットメッセージ
- 9.1.2 継続的インテグレーション
- 9.1.3 小さなコミット
- 9.2 コードの共同所有
- 9.2.1 ペアプログラミング
- 9.2.2 モブプログラミング
- 9.2.3 コードレビューの遅延
- 9.2.4 チェンジセットを拒否する
- 9.2.5 コードレビュー
- 9.2.6 プルリクエスト
- 9.3 まとめ
- 9.1 Git
- 1章 アートかサイエンスか
- 第II部 持続可能性
- 10章 コードの増大
- 10.1 フィーチャーフラグ
- 10.1.1 カレンダーフラグ
- 10.2 ストラングラーパターン
- 10.2.1 メソッドレベルストラングラー
- 10.2.2 クラスレベルストラングラー
- 10.3 バージョニング
- 10.3.1 事前警告
- 10.4 まとめ
- 10.1 フィーチャーフラグ
- 11章 ユニットテストを編集する
- 11.1 ユニットテストのリファクタリング
- 11.1.1 セーフティネットの変更
- 11.1.2 新しいテストコードの追加
- 11.1.3 テストとプロダクションコードを別々にリファクタリングする
- 11.2 テストの失敗を確認する
- 11.3 まとめ
- 11.1 ユニットテストのリファクタリング
- 12章 トラブルシューティング
- 12.1 理解
- 12.1.1 科学的手法
- 12.1.2 シンプルさ
- 12.1.3 ラバーダッキング
- 12.2 欠陥
- 12.2.1 欠陥をテストとして再現する
- 12.2.2 スローテスト
- 12.2.3 非決定論的欠陥
- 12.3 二分法
- 12.3.1 Git による二分法
- 12.4 まとめ
- 12.1 理解
- 13章 関心事の分離
- 13.1 合成
- 13.1.1 ネストした合成
- 13.1.2 逐次合成
- 13.1.3 参照透明性
- 13.2 横断的関心事
- 13.2.1 ロギング
- 13.2.2 デコレーター
- 13.2.3 何をログに出力するか
- 13.3 まとめ
- 13.1 合成
- 14章 リズム
- 14.1 個人のリズム
- 14.1.1 タイムボックス
- 14.1.2 休憩を取る
- 14.1.3 意識して時間を使う
- 14.1.4 タッチタイプ
- 14.2 チームのリズム
- 14.2.1 定期的に依存を更新する
- 14.2.2 他のことも予定を入れる
- 14.2.3 コンウェイの法則
- 14.3 まとめ
- 14.1 個人のリズム
- 15章 いつもの顔ぶれ
- 15.1 パフォーマンス
- 15.1.1 過去の遺物
- 15.1.2 視認性
- 15.2 セキュリティ
- 15.2.1 STRIDE
- 15.2.2 なりすまし
- 15.2.3 改ざん
- 15.2.4 否認
- 15.2.5 情報漏えい
- 15.2.6 サービス妨害
- 15.2.7 権限昇格
- 15.3 その他のテクニック
- 15.3.1 プロパティベーステスト
- 15.3.2 行動コード解析
- 15.4 まとめ
- 15.1 パフォーマンス
- 16章 ツアー
- 16.1 ナビゲーション
- 16.1.1 全体像を見る
- 16.1.2 ファイル構成
- 16.1.3 詳細を見つける
- 16.2 アーキテクチャー
- 16.2.1 モノリス
- 16.2.2 循環参照
- 16.3 使ってみる
- 16.3.1 テストから学ぶ
- 16.3.2 テストの声を聞く
- 16.4 まとめ
- 16.1 ナビゲーション
- 10章 コードの増大
- 付録A プラクティス一覧
- A.1 50/72ルール
- A.2 80/24ルール
- A.3 Arrange-Act-Assert
- A.4 二分法
- A.5 新しいコードベースのためのチェックリスト
- A.6 コマンドクエリ分離
- A.7 変数を数える
- A.8 サイクロマティック複雑度
- A.9 横断的関心事のためのデコレーター
- A.10 悪魔の代弁者
- A.11 フィーチャーフラグ
- A.12 関数型コア・命令型シェル
- A.13 コミュニケーション階層
- A.14 ルールの例外を正当化する
- A.15 検証せずにパースする
- A.16 ポステルの法則
- A.17 レッド/グリーン/リファクタリング
- A.18 依存関係を定期的に更新する
- A.19 欠陥をテストとして再現する
- A.20 コードをレビューする
- A.21 セマンティックバージョニング
- A.22 テストとプロダクションコードを別々にリファクタリングする
- A.23 スライス
- A.24 ストラングラー
- A.25 脅威モデル
- A.26 変換の優先順位
- A.27 X駆動開発
- A.28 名前をXで置き換える
- コラム
- デプロイパイプラインを確立するときによくある課題
- null許容参照型
- ArgumentNullExceptionがNullReferenceExceptionよりも優れている理由は?
- テスト駆動開発のサイエンス
- 契約による設計
- ポステルの法則
- 昇順に数値表現を書く
- Maybe
- 適切な文章
- 機動性
- バス係数
1章 アートかサイエンスか
[概論]
- ソフトウェア開発は本質的にアート
- ソフトウェアサイエンスは上手く機能しなかった
2章 チェックリスト
[概論]
- 仕事を助けるためにチェックリストを使おう
3章 複雑さに対処する
[概論]
- 何故ソフトウェアかいはつはこんなにも難しいのか
- ソフトウェア開発のプロセスをもって規則正しくし、組織と持続可能にするべき
- ソフトウェア開発が難しい理由は、ソフトウェアは人間の認知能力を超える複雑さを持つから
4章 バーティカルスライス
[概論]
- バーティカル・スライス == 一番シンプルな機能をUIからデータストアまで一通り実装したプロトタイプ
- ソフトウェアが動くがどうかをなるべく早く確認するための実装
5章 カプセル化
[概論]
- オブジェクト自身が仕様上無効な状態にならないよう制御・保証するべき
- オブジェクト自身が「有効」である状態を検証・保証するべき
[KeyWord]
- パラメータテスト
- レッド/グリーン/リファクタリング
- ポステルの法則
- 不変条件の保証
- 常に有効
6章 三角測量
[概論]
- テストを利用してあるべき地点(完成)を導出する
- テストで正解を計測する考え方
7章 分解
[概論]
- レガシーコードについて
- レガシーコードはコードが徐々に劣化することで発生する
- なので、コードの劣化を防ぐために小さなコンポーネントに分解する
- コードは脳に収まるサイズを目指す
- マジックナンバー7が重要
[Keyword]
- コード行数
- サイクロマティック複雑度
- 変数の数
- 凝集度
- 特性の横恋慕
- マジックナンバー7
- フラクタルアーキテクチャ
8章 API設計
[概論]
- API設計について
- API設計の原則について
- API == モジュールのインターフェイス
[Keyword]
- アフォーダンス
- ポカヨケ
- 読む人の為に書く
- コメントよりもわかりやすい名前のコード
- コマンドクエリ分離
- コミュニケーション
9章 チームワーク
[概論]
- チームによるコードの共同所有とそのプラクティス
[Keyword]
- git
- コミットメッセージ
- CI
- 小さなコミット
- コードレビュー
10章 コードの増大
[概論]
- コードの追加/修正に関するプラクティス
[Keyword]
- フィーチャーフラグ
- ストラングラーパターン
- 1日2回はコミットする
- バージョニング
- フィーチャーフラグは使わない
11章 ユニットテストを編集する
[概論]
- ユニットテストを編集する際のプラクティス
12章 トラブルシューティング
[概論]
トラブルシューティングについてのプラクティス
13章 関心事の分離
[概論]
- コンポーネントの分離(== 関心の分離)に関する方法論
[Keyword]
- 合成
- 横断的関心事
14章 リズム
[概論]
- 開発プロセスについて
- 個人の生産性
- チームの生産性
15章 いつもの顔ぶれ
[概論]
- ソフトウェアエンジニアリングについて
- 性能やセキュリティなど非機能要件について
16章 ツアー
[概論]
- 本編で紹介されたサンプルコードの解説など
- アーキテクチャについての簡単な説明