doc.dev1x.org

A Philosophy of Software Design (John Ousterhout)

書籍情報

書籍目次

Preface

ソフトウェア設計の現状

問題分解の重要性と教育の欠如

プログラマの能力差と設計スキルの性質

スタンフォード大学 CS 190 の授業スタイル

著者の背景と経験

本書の位置付けと読者への要請

1 Introduction

ソフトウェア開発と複雑性の本質

複雑性に対処する2つのアプローチ

ウォーターフォールモデルとその問題点

インクリメンタル開発(アジャイル開発)

ソフトウェア設計の継続的プロセス

本書の目的と活用方法

2 The Nature of Complexity

章の目的と概要

複雑性の定義

複雑性の症状

複雑性の原因

複雑性の漸進的な蓄積

結論

3 Working Code Isn't Enough

戦術的プログラミングの問題点

戦略的プログラミングの原則

適切な投資量

スタートアップにおける設計投資

結論

4 Modules Should Be Deep

モジュラー設計の基本原則

インターフェースの構成要素

抽象化の概念と誤り

深いモジュール

浅いモジュール

private void addNullValueForAttribute(String attribute) {
    data.put(attribute, null);
}

クラシティス(Classitis)

JavaとUnix I/Oの比較例

結論

5 Information Hiding (and Leakage)

情報隠蔽の基本概念

情報漏洩とその危険性

時系列分解による情報漏洩

HTTPサーバを用いた実例

クラス内部での情報隠蔽

情報隠蔽の過剰適用への注意

結論

6 General-Purpose Modules are Deeper

汎用設計と特化設計のトレードオフ

事例: テキストエディタのテキストクラス設計

汎用性が情報隠蔽を向上させる

汎用インタフェース設計のための自己確認

結論

7 Different Layer, Different Abstraction

階層ごとに異なる抽象化の原則

パススルーメソッド

public class TextDocument ... {
    private TextArea textArea;
    private TextDocumentListener listener;
    ...
    public Character getLastTypedCharacter() {
        return textArea.getLastTypedCharacter();
    }
    public int getCursorOffset() {
        return textArea.getCursorOffset();
    }
    public void insertString(String textToInsert, int offset) {
        textArea.insertString(textToInsert, offset);
    }
    public void willInsertString(String stringToInsert, int offset) {
        if (listener != null) {
            listener.willInsertString(this, stringToInsert, offset);
        }
    }
    ...
}

インターフェースの重複が許容されるケース

デコレーターパターン

インターフェースと実装の違い

パススルー変数

結論

8 Pull Complexity Downwards

基本原則: 複雑さを下方に引き込む

例1: テキストエディタのテキストクラス

例2: 設定パラメータ

過剰適用への注意

結論

9 Better Together Or Better Apart?

基本的な問い: まとめるか分けるか

分割のコスト

コードをまとめるべき判断基準

まとめるべき具体的なケース

汎用コードと専用コードの分離

例1: 挿入カーソルと選択範囲

例2: ログ記録用の別クラス化(分離が不適切な例)

例3: エディタのUndo機構(汎用部分の分離)

メソッドの分割と統合

結論

10 Define Errors Out Of Existence

例外処理が生む複雑性

過剰な例外定義の問題

例外を定義によって排除する手法

例外マスキング

例外の集約

クラッシュ戦略

特殊ケースの設計による排除

限界と結論

Chapter 11 Design it Twice

基本原則

設計代替案の検討プロセス

代替案の評価基準

設計の統合と改善

多層的な適用

時間的コスト

優秀な人材とこの原則の関係

設計スキルへの効果

12 Why Write Comments? The Four Excuses

コメントの重要性

開発者がコメントを避ける4つの言い訳

言い訳1: 良いコードは自己文書化されている

言い訳2: コメントを書く時間がない

言い訳3: コメントは古くなり誤解を招く

言い訳4: 見てきたコメントはすべて無価値だった

良いコメントがもたらす恩恵

13 Comments Should Describe Things that Aren't Obvious from the Code

コメントの基本原則

コメントの種類と慣習

コードの繰り返しを避ける

低レベルコメントによる精度の向上

高レベルコメントによる直感の強化

インターフェースドキュメント

実装コメント

クロスモジュール設計の決定事項

結論

14 Choosing Names

命名の重要性

不適切な命名がバグを引き起こした事例

良い名前の条件: イメージを生み出すこと

名前の精確性

一貫した命名

Go言語スタイルガイドとの見解の相違

結論

15 Write The Comments First

概要

コメントを後回しにすることの問題点

コメントを先に書くアプローチ

コメントが設計ツールとなる理由

早期コメント記述の楽しさ

早期コメント記述のコスト

結論

16 Modifying Existing Code

既存コード修正の前提

戦略的姿勢の維持

コメントの維持: コードの近くに置く

コメントはコードに置きコミットログに置かない

コメントの維持: 重複を避ける

コメントの維持: 差分を確認する

高レベルのコメントは維持しやすい

17 Consistency

一貫性の意義

一貫性の例

一貫性の確保

度を超すこと

結論

18 Code Should be Obvious

不明瞭さと明白なコードの定義

コードを明白にする要素

コードを明白でなくする要素

結論

19 Software Trends

本章の目的

オブジェクト指向プログラミングと継承

アジャイル開発

ユニットテスト

テスト駆動開発

デザインパターン

ゲッターとセッター

結論

20 Designing for Performance

性能設計の基本姿勢

性能をどう考えるか

変更前に測定する

クリティカルパスを中心に設計する

事例: RAMCloud Buffer

結論

21 Conclusion

本書の主題

設計を重視することの欠点

設計を重視することの利点

良い設計への投資の効果

良い設計者が得る報酬

Summary of Design Principles

Summary of Red Flags