継続的デリバリーのソフトウェア工学 もっと早く、もっと良いソフトウェアを作るための秘訣 (David Farley)
書籍情報
- 著者:David Farley(著), 長尾高弘(訳), 榊原 彰(解説)
- 発行日:2022-12-18
- ISBN:9784296070367
- URL:https://bookplus.nikkei.com/atcl/catalog/22/12/01/00531/
書籍目次
- 序文
- はじめに
- 第1部 ソフトウェア工学とは何か
- 第1章 イントロダクション
- 1.1 工学 ――科学の実用的な応用
- 1.2 ソフトウェア工学とは何か
- 1.3 「ソフトウェア工学」の再生
- 1.4 ソフトウェア工学の誕生
- 1.5 パラダイムシフト
- 1.6 まとめ
- 第2章 工学とは何か
- 2.1 私達にとって製造は問題ではない
- 2.2 製造工学ではなく設計工学
- 2.3 工学の実践的な定義
- 2.4 工学 != コード
- 2.5 工学はなぜ大切なのか
- 2.6 「工芸」の限界
- 2.7 精度とスケーラビリティ
- 2.8 複雑さ管理
- 2.9 反復性と計測精度
- 2.10 工学、創造力、職人技
- 2.11 私たちがソフトウェア工学をしていない理由
- 2.12 トレードオフ
- 2.13 進歩の幻想
- 2.14 工芸から工学へ
- 2.15 工芸では不十分
- 2.16 考え直すべきときが来たのか
- 2.17 まとめ
- Column: 数学としての工学
- Column: 最初のソフトウェアエンジニア
- Column: プログラミング言語の進化
- 第3章 工学的アプローチの基礎
- 3.1 変化の産業?
- 3.2 計測の重要性
- 3.3 安定性とスループットの活用
- 3.4 ソフトウェア工学という研究分野の基礎
- 3.5 学びのエキスパート
- 3.6 複雑さ管理のエキスパート
- 3.7 まとめ
- 第1章 イントロダクション
- 第2部 学びの最適化
- 第4章 反復的な作業
- 4.1 反復的な作業の実践的な利点
- 4.2 守り重視の設計戦略としてのイテレーション
- 4.3 計画の誘惑
- 4.4 反復的な作業の現実
- 4.5 まとめ
- Column: アジャイル革命
- Column: プロセス戦争
- Column: 無限の始まり
- 第5章 フィードバック
- 5.1 フィードバックの重要性を示す具体例
- 5.2 コーディングに対するフィードバック
- 5.3 インテグレーションに対するフィードバック
- 5.4 設計に対するフィードバック
- 5.5 アーキテクチャに対するフィードバック
- 5.6 フィードバックは早く
- 5.7 製品設計に対するフィードバック
- 5.8 組織と文化に対するフィードバック
- 5.9 まとめ
- Column: NATOの会議
- Column: テストの根本的な役割
- 第6章 漸進主義
- 6.1 モジュラー性の重要性
- 6.2 組織上の漸進主義
- 6.3 漸進主義のためのツール
- 6.4 コード変更が与える影響の最小化
- 6.5 漸進的な設計
- 6.6 まとめ
- 第7章 経験主義
- 7.1 現実に根ざすということ
- 7.2 経験主義と実験主義の境界線
- 7.3 「そのバグはわかってる!」
- 7.4 自己欺瞞を避ける
- 7.5 自分の理論に合う事実の偽造
- 7.6 事実に指針を求める
- 7.7 まとめ
- Column: 神話と事実の分離:例
- 第8章 実験主義的であること
- 8.1 「実験主義的であること」とはどういう意味か
- 8.2 フィードバック
- 8.3 仮説
- 8.4 計測
- 8.5 変数の管理
- 8.6 実験としての自動テスト
- 8.7 実験としてのテストの結果が持つ意味
- 8.8 実験のスコープ
- 8.9 まとめ
- Column: スピードの必要性
- 第4章 反復的な作業
- 第3部 複雑さ管理の最適化
- 第9章 モジュラー性
- 9.1 モジュラー性の目安
- 9.2 設計の重要性の過小評価
- 9.3 テスト可能性の重要性
- 9.4 テスト可能性を意識した設計によるモジュラー性の向上
- 9.5 サービスとモジュラー性
- 9.6 デプロイ可能性とモジュラー性
- 9.7 さまざまな規模におけるモジュラー性
- 9.8 人間システムのモジュラー性
- 9.9 まとめ
- Column: 複雑さと決定論的動作
- 第10章 凝集度
- 10.1 モジュラー性と凝集度: 設計の基礎
- 10.2 凝集度の理解が未熟な例
- 10.3 コンテキストが大切
- 10.4 パフォーマンスの高いソフトウェア
- 10.5 カップリングとの関係
- 10.6 TDDによる凝集度の向上
- 10.7 凝集度の高いソフトウェアの実現方法
- 10.8 低凝集度のコスト
- 10.9 人間システムの凝集度
- 10.10 まとめ
- Column: ドメイン駆動設計
- 第11章 関心の分離
- 11.1 依存性注入
- 11.2 本質的な複雑さと付随的な複雑さの分離
- 11.3 DDDの重要性
- 11.4 テスト可能性
- 11.5 ポートアンドアダプター
- 11.6 ポートアンドアダプターを使うべきなのはいつか
- 11.7 APIとは何か
- 11.8 関心の分離を進めるためのTDDの利用
- 11.9 まとめ
- Column: データベースのスワップアウト
- 第12章 情報隠蔽と抽象化
- 12.1 抽象化か情報隠蔽か
- 12.2 「大きな泥だんご」ができる理由
- 12.3 組織的、文化的な理由
- 12.4 技術的な問題と設計の問題
- 12.5 オーバーエンジニアリングの懸念
- 12.6 テストによる抽象化の推進
- 12.7 抽象化の力
- 12.8 漏れのある抽象化
- 12.9 適切な抽象の選択
- 12.10 問題ドメインからの抽象
- 12.11 付随的な複雑さの抽象化
- 12.12 サードパーティーのシステムやコードの分離
- 12.13 常に情報隠蔽を指向せよ
- 12.14 まとめ
- Column: 抽象化レベルの引き上げ
- Column: 抽象化か実理性か
- Column: ドメイン固有言語
- 第13章 カップリングの管理
- 13.1 カップリングのコスト
- 13.2 スケールアップ
- 13.3 マイクロサービス
- 13.4 デカップリングはコード量を増やす
- 13.5 カップリングのさまざまなタイプ
- 13.6 どちらかと言えば粗結合を目指す
- 13.7 粗結合と関心の分離の違い
- 13.8 DRYは単純化しすぎ
- 13.9 粗結合のツールとしての非同期処理
- 13.10 粗結合のための設計
- 13.11 人間システムの粗結合
- 13.12 まとめ
- Column: 粗結合のしすぎ
- 第9章 モジュラー性
- 第4部 ソフトウェア工学を支えるツール
- 第14章 工学分野のためのツール
- 14.1 ソフトウェア開発とは何か
- 14.2 ツールとしてのテスト可能性
- 14.3 計測点
- 14.4 テスト可能性を実現する上での問題点
- 14.5 テスト可能性の引き上げ方
- 14.6 デプロイ可能性
- 14.7 スピード
- 14.8 変数の管理
- 14.9 継続的デリバリー
- 14.10 工学を支える汎用性の高いツール
- 14.11 まとめ
- Column: 周縁部でのテスト
- Column: 管理の甘さが生み出すコスト
- 第15章 現代のソフトウェアエンジニア
- 15.1 ヒューマンプロセスとしての工学
- 15.2 デジタルによる破壊的企業
- 15.3 結果かメカニズムか
- 15.4 長く有効で汎用性の高い原則
- 15.5 ソフトウェアを対象とする工学の基礎
- 15.6 まとめ
- 第14章 工学分野のためのツール
- 謝辞
- 解説
第1章 イントロダクション
ソフトウェア工学とは何か
- ソフトウェアの現実的な問題に対する効果的、経済的な解を見つける為の経験的、科学的なアプローチの応用
学びのエキスパートに必要な5つのテクニック
- (1) 反復的な作業
- (2) フィードバック
- (3) 漸進主義
- (4) 実験主義
- (5) 経験主義
複雑さ管理のエキスパートに必要な5つの
- (1) モジュラー性
- (2) 凝集度
- (3) 関心の分離
- (4) 抽象化
- (5) 粗結合
5つの要素
- (1) テスト可能性
- (2) デプロイ可能性
- (3) スピード
- (4) 変数の管理
- (5) 継続的デリバリー
第2章 工学とは何か
ソフトウェア開発は製造業ではない
- 物理的な製品を製造するのはコストがかかり、複雑な工程やプロセスが必要
- 故に製造業には生産工学などが発展した
- ソフトウェア開発における「製造」は最終的な成果物を生成するひとつのタスク(実行ファイルやコンテナイメージのビルド)でしかない
- ソフトウェア開発における「製造」のコストは全体から見ると極わずかでしかない
- ソフトウェア開発における「製造」は重要な問題ではない
- ソフトウェア開発は設計工学である
- [NOTE]
- マーティン・ファウラーも同じことを言っている
- The New Methodology
- ソフトウエア開発のどこまでを設計と呼ぶか? | 日経クロステック(xTECH)
誤解 → 工学とはアウトプット(コードや設計)のことである
- 工学とはアウトプット(コード、設計)のことだけではない
- ソフトウェア開発に関する全てが対象である(プロセス、ツール、文化、etc...)
第9章 モジュラー性
モジュラー性の定義
- システムのコンポーネントが分割、再結合されている度合い
- 柔軟性の高さ、用途の多さといった利点がある
ソフトウェア開発の本質
- ソフトウェア開発の本質は、モジュラーな設計を行えるスキル
モジュラー性とテスト可能性
- テスト可能性を高めるとモジュラー性の高さにつながる
- モジュラー性の高いコンポーネントはモジュール単体のテストが容易となりバグを検出しやすくなる
- モジュラー性に欠けるシステムは全てを結合した状態でテストする必要があるので、テストが複雑になり、テストのヌケモレが多くなりがち(=品質が低くなる)
サービスとモジュラー性
- サービスは境界を表すもの
- 他のコードに対して、サービス内の詳細を隠蔽して、操作インターフェイスを提供するもの
第11章 関心の分離
関心の分離の定義
- それぞれ別々の関心(小さな問題)を持つように分離されたセクションからプログラムを組み立てるという設計
関心の分離の効果
- システムのモジュラー性、凝集度、抽象化を向上させる重要なテクニック
依存性の注入
- コードが依存するもの(ロジック)をコード内で作らず、引数で渡すプログラミングテクニック
- プログラミングテクニックなので、ツールやフレームワークの機能ではない
- [NOTE]
- DIコンテナと依存性の注入がセットで語られることが多いため、DIコンテナ=依存性の注入であると認識している人は多い
第12章 情報隠蔽と抽象化
情報隠蔽と抽象化とは
- オブジェクトやシステムについて考えるに当たって、より重要な部分の細部に注意を集中させるために物理的、空間的、時間的な細部または属性を取り除くプロセス
抽象化か情報隠蔽か
- 両者に大きな違いは無い
- 本書では情報の隠蔽とはコードの振る舞いの隠蔽を指す
大きな泥団子
- ある部分を書き換えると、コードの他の部分に影響が出るような書き換え困難なコード
- システムの殆ど全ての仕組みを理解できる頭脳がないと変更できないコード
マインドセット
- 既存コードを書き換えるのは良いことであり、合理的なことである
- しかし、多くの企業では既存のコードへの変更を恐れている
- 設計は凍結と同時に陳腐化する
チームのソフトウェアの半分の寿命
- チームが作るソフトウェアの品質は、その半分の寿命から計算できる
- ソフトウェアの半分の寿命とは、チームが担当するソフトウェアの半分が書き換えられるまでにかかった時間
- [NOTE]
- いまいちよくわからなかった
オーバーエンジニアリングの懸念
- 技術的に輝かしいアイデアを追い掛けたがるエンジニアの性質
オーバーエンジニアリングとの付き合い方
- 最新の技術的アイデアへの憧憬
- 同時に一定の実利主義、懐疑主義も身に付ける
- 解決すべき問題のコンテキストでどれだけ役立つかは公平な目で評価する必要がある
- いきなりクリティカルな領域への投入は避ける慎み深さが必要
フューチャープルーフ
- 「今は必要無いかもしれないけど、将来必要になる(かもしれない)」と考えたがるエンジニアの性質
- 時間と共に劣化しないシステムを作りたいというエンジニアの欲望
- YAGNI原則
抽象化
- 抽象化すれば、システムのある部分の複雑さを他の部分から隠すことができる
- そうすると、システムのある部分のコードをより安全に変更できるようになる
テスト
- リグレッションテスト重要
漏れのある抽象化
- 抽象化したはずの細部が抽象化レイヤーに漏れ出てきている状態、そのような抽象化の失敗
- 抽象化のプロセスは複雑なプロセスなので、取り扱いに注意が必要
漏れのある抽象化、漏れのタイプ
- (1) 本質的に避けられないもの
- 例えば、ハードウェアの性能を限界まで引き出したい場合、ハードウェアに対する抽象化を壊す必要が出てくる
- (2) 失敗した抽象化
- 考慮漏れなど設計の不備により生じるもの
イベントストーミング
- 注目すべき概念を形成する振る舞いの塊を見つけ出すのに役立つモデリング手法
- 境界付けられたコンテキストやドメインの境界線を浮かび上がらせることができる
付随的な複雑さの抽象化
- コードにはそのコードが果たすべき本質的な責務と、本質的ではないが必要な責務(付随的な複雑さ)が存在する
- 本書では付随的な複雑さはコード内に直接書くのではなく、Listenerという概念を導入して隠蔽している
サードパーティのシステムやコードの分離
- プロダクトコード内でサードパーティーコードを直接使わない(ラップして使う)という話
抽象化はソフトウェアの核心
- ソフトウェアエンジニアにとって、抽象化のスキルは必須
第13章 カップリングの管理
カップリングの定義
- ソフトウェアモジュール間の相互依存の度合い
- 2つのルーチン、モジュールがどの程度密接に繋がっているかの尺度
- モジュール間の関係の強さ
カップリングにおける留意事項
- より疎結合である方が良い
- しかし、コンポーネントが完全に疎結合であることはコンポーネント同士がやりとりできないという事でもある
- カップリングは常に完全に取り除けるわけでもないし、そうするべきでもない
密結合と疎結合
- 一般論として密結合より疎結合を目指す
- ただし、密結合=悪、疎結合=善というほど単純ではない
- トレードオフの問題
スケールアップ
- 疎結合なサービスは担当チーム同士の調整が(理論的には)不要になるので、開発のスケールアップが期待できる
マイクロサービス
- マイクロサービス化することで結合度を避けることができる
- ただし、設計難易度は高い
コードの文字数について
- コードは入力量を減らす為ではなく、思考を深めることを目的に最適化するべし
- [MEMO]
- 至言
カップリングのナイガードモデル
- (1) 運用 → プロデューサが実行されていないのでコンシューマが実行できない
- (2) 開発 → コード変更の為にプロデューサとコンシューマの間に調整が必要に成る
- (3) セマンティック → 共有する概念があるため、両方を同時に書き換える必要がある
- (4) 機能的 → 協力して行う仕事があるため、両方を同時に書き換える必要がある
- (5) 偶発的 → あまりよくない理由の為に両方を同時に書き換える必要がある
DRY原則の問題点
- スコープを広げすぎる
- モジュールやサービスレベルでは正しい
- ソースコードリポジトリやデプロイパイプラインなどインフラまでスコープを広げると厄介な事になる
- システム全体でDRYを維持するのはコストと手間が掛かるorコストに見合わない
DRYのメリット/デメリット
- メリット:
- 1箇所変更するだけでよい
- デメリット:
- その1箇所に全ての利用者が依存してしまう(影響度、メンテナンス性に影響)
マイクロサービス間で同じコードを共有しない
- コードの変更が復数のサービスに影響するので、マイクロサービス間でのコード共有はしない
- マイクロサービスの独立性が失われる
- [MEMO]
- とはいえ、どうしようも無い時はありそう