良いコードの道しるべ 変化に強いソフトウェアを作る原則と実践 (森篤史, 久野文菜)
書籍情報
- 著者:森篤史(著), 久野文菜(著)
- 発行日:2025-02-29
- ISBN:9784839982850
- URL:https://book.mynavi.jp/ec/products/detail/id=147381
書籍目次
- はじめに
- Chapter1 なぜ良いコードを書くのか
- 1.1 ソフトウェアの価値
- 1.2 保守性とスピード
- 失われる保守性
- ヒント: ゼロから作り直すという選択肢
- 1.3 技術的負債の発生と解消
- 技術的負債が発生する理由
- 意図的な負債
- 変化による負債
- 学びによる負債
- 技術的負債への向き合い方
- ヒント: 技術的借り入れ
- 1.4 良いコードを書くために
- Chapter2 動くコードから意図の伝わるコードへ
- 2.1 意図を表現する
- ヒント: 格好つけたコードを書かない
- Kotlin解説(1) when句
- Kotlin解説(2) 文字列テンプレート
- 2.2 名前で伝える
- 短い名前より意味のある名前
- ヒント: Checkって言わないで
- Kotlin解説(3) クラスのコンストラクタとプロパティ宣言
- 重要な情報を加える
- ヒント: 他にも使える前置詞/接続詞
- 長過ぎる名前も読みにくい
- 名前の省略には要注意
- 同じものには同じ名前を
- 英語の文法を無視しない
- ヒント: 真偽値 (Bool値)に良く使われる名前
- 言語やフレームワークに従う
- うまく名前が付けられないときは?
- 2.3 コメントで補足する
- コメントはなくても良い?
- コードから読み取れない情報を記述する
- 役に立つ情報を提供する
- ヒント: コメントは英語? 日本語?
- Kotlin解説(4) null値許容型
- 2.4 ドメイン知識をコードで表現する
- ヒント: ドメイン駆動設計とドメインエキスパート
- 必要な要素を洗い出す
- ヒント: ドメインオブジェクトの種類
- ドメインオブジェクトが持つ振る舞いをコードで表現する
- Kotlin解説(5) MapとMutableMap
- Kotlin解説(6) エルビス演算子
- ドメインオブジェクトが持つロジックを実装する
- Kotlin解説(7) リストを操作する高階関数
- 設計と現実の乖離を防ぐ
- 2.1 意図を表現する
- Chapter3 大きな問題は分割して考えよう
- 3.1 関数やクラスを分ける
- 関心ごとに分ける
- Kotlin解説(8) flatMapでリストの平坦化を行う
- ヒント: 補助的な操作を切り出す
- コードが変更される理由を1つにする
- ヒント: マネージャーは何する人?
- ドメインオブジェクトを分割する
- アプリケーションサービスを作る
- Kotlin解説(9) クラスとオブジェクト
- 3.2 詳細を読まなくても使えるようにする
- インターフェースを明確にする
- 必要な情報のみを公開する
- Kotlin解説(10) private修飾子
- 内部の状態を知らなくても使えるようにする
- 3.3 コードの複雑度を計測する
- コードの行数
- 循環的複雑度
- 3.4 凝集度を高める
- 関数の凝集度のレベル
- 関数の凝集度を上げるリファクタリング
- クラスの凝集度を上げる
- 凝集度のまとめ
- 3.1 関数やクラスを分ける
- Chapter4 コードの分類術
- 4.1 ディレクトリ単位での整理
- 関心ごとにグルーピングを行う
- 並列するディレクトリの抽象度を揃える
- 4.2 モジュール単位の整理
- モジュールの目的と効果
- 同じ理由、同じタイミングで変更されるものをまとめる
- 同時に使われるものをまとめる
- 4.1 ディレクトリ単位での整理
- Chapter5 絡まった依存関係を解きほぐせ
- 5.1 依存を意識する
- 依存と影響
- 5.2 依存の方向
- 循環依存を避ける
- 安定しているものに依存する
- ヒント: 安定度の目安
- 5.3 抽象に依存させる
- 抽象と具象
- 抽象をインターフェースで表現する
- ヒント: 動的型付け言語とインターフェース
- 依存関係を外から渡す
- ヒント: DIコンテナによる依存関係の解決
- グループ間の依存方向を逆転させる
- ヒント: 依存性逆転の原則 (Dependency inversion principle, DIP)
- いつインターフェースを作成すべきか
- 5.4 結合度を低くする
- 結合度のレベル
- 結合度の使い分け
- 5.1 依存を意識する
- Chapter6 良いコードを書く原則・教訓
- 6.1 KISS原則: シンプルに保つ
- 6.2 YAGNI原則: 必要になるまで実装しない
- Kotlin解説(11) sealedインターフェースとenumの違い
- 6.3 DRY原則: 重複する知識を減らす
- ヒント: DRY原則の適応対象
- 6.4 車輪の再発明: 同じものを作らない
- プログラミング言語の機能を使う
- ライブラリを使う
- ヒント: 「再発明」のメリット
- プロジェクト内に同じ目的のコードがないか確認する
- 6.5 ハンマーしか持っていなければ、すべてが釘のように見える
- 6.6 銀の弾丸などない
- ヒント: 生成AIは本質的困難を解消できるか
- Chapter7 うっかりミスを防ぐために
- 7.1 マジックナンバーを避ける
- 数値を定数に置き換える
- 数値を列挙型に置き換える
- マジックナンバーを隠さないで
- Kotlin解説(12) null値許容型を安全に処理するsafe call演算子
- 7.2 型による制限を有効活用する
- 値が取りうる範囲を制限する
- ヒント: 列挙型に値を持たせる
- カスタム型を作る
- Kotlin解説(13) require関数
- ヒント: インスタンスの生成を安全にする
- Kotlin解説14 コンパニオンオブジェクト
- 不正な状態を避ける
- 起こり得るエラーを列挙する
- ヒント: 例外を使うほうが適しているケース
- 判別可能なユニオン型を使う
- 7.3 変更できないデータを使う
- ミュータブルとイミュータブルの違い
- ヒント: イミュータブルと読み取り専用
- データを表す型はイミュータブルにする
- ヒント: イミュータブルとマルチスレッド
- ヒント: イミュータブルなオブジェクトのデメリット
- Kotlin解説(15) データクラスと copy 関数
- 短いスコープではミュータブルも使える
- リストのビルダー関数
- 7.4 データを一箇所で管理する
- 同じデータを複数箇所で保持しない
- キャッシュでの重複に注意
- 7.5 状態の変更と情報の取得を分ける
- コマンド・クエリ分離の原則
- ヒント さらに状態の変化をなくす
- コマンド・クエリ分離の原則の例外
- 7.1 マジックナンバーを避ける
- Chapter8 コードは書くよりも変更するほうが難しい
- 8.1 ボーイスカウトルール: 来たときよりも美しく
- 8.2 ゼロベースで コードを考える
- 既存のコードを変更する
- コードを分割する
- 共通部分を切り出す/共通化をやめる
- ヒント 関数を分けない解決策
- 命名もコメントも変更する
- 8.3 少しずつ変更する
- タスクを分割する
- Newって名前をつけないで
- 8.4 いらなくなったコードを削除する
- Chapter9 アーキテクチャを考える
- 9.1 レイヤを整理する
- レイヤを認識する
- ドメインレイヤ/ビジネスレイヤ
- レイヤ間の依存関係やデータフローを決める
- レイヤの表現方法
- 9.2 レイヤ構成のアイデア
- レイヤードアーキテクチャ (Layered Architecture)
- クリーンアーキテクチャ (Clean Architecture)
- ヒント: UIを扱うアーキテクチャ
- 9.3 機能に着目して分割する
- 機能間の関係を考える
- さらに細かく分類する
- ヒント: マイクロサービスアーキテクチャと境界の強度
- 9.4 アーキテクチャを考えるということ
- 9.1 レイヤを整理する
- Chapter10 壊さないための自動化テスト
- 10.1 手動テストの限界と自動化
- 問題の発見が遅れる
- テストケースの増加に追いつけない
- 人的ミスの発生
- 10.2 自動化テストの種類
- 単体テスト ――単一のクラスまたは関数をテストする
- 結合テスト ――複数のクラスや関数を組み合わせてテストする
- E2E テスト ――アプリケーション全体をテストする
- 自動化テストの使い分け
- 手動テストの必要性
- 10.3 単体テストを書く
- Kotlin解説(16) テストで使える関数名
- AAA: Arrange-Act-Assert
- 必要な十分なテストケースを作る
- ヒント: 境界値をテストする
- シンプルなコードでテストを書く
- 明確なテスト名をつける
- ヒント: プライベート関数をテストしないで
- ヒント 1 + 1はほんとに2?
- 10.4 依存しているコードを偽物に差し替える
- 依存しているクラスを差し替える
- ヒント: モックライブラリを使う
- 環境によって変化する値を差し替える
- テストにかかる時間を短くする
- 偽物の使いすぎには要注意
- 10.5 テストカバレッジを計測する
- 10.6 結合テスト/E2E テスト
- 10.1 手動テストの限界と自動化
- Chapter11 チームで書く良いコード
- 11.1 Gitでバージョン管理
- Gitを使った作業の基本フロー
- 分かりやすいコミットを作成する
- ヒント: 個人開発でもGitを活用する
- 11.2 コードレビューを行う
- コードレビューのゴールを決める
- コードレビューの依頼の仕方
- レビューの心構え
- 問題の重要度を見極める
- ヒント: 自転車置き場の屋根の色は何色にすべき?
- 11.3 コーディング規約を作る
- 11.4 自動でチェックする
- 11.5 設計書を作る
- Design Doc に含めること
- Design Doc を活用する
- 11.1 Gitでバージョン管理
- おわりに
- 参考文献一覧
- 索引