www.goodreads.com
General-Purpose Modules Are Deeper
- モジュールを汎用にするか用途特化にするか
- 汎用サイドの言い分
- 広範な問題に対応できる
- 将来の工数短縮
- ch3. Working Code Isn't Enough にも沿っているように見える
- 用途特化サイドの言い分
- 機能を汎用的に作ったはいいが、一度も使われないかも
- 汎用的すぎると、今現在挙がっている問題にうまく対処できない
- 都度リファクタリングして汎用にしていく
- インクリメンタルアプローチに沿っているように見える
Make classes somewhat general-purpose
- 著者の経験上、「やや汎用」がスイートスポット
- 実装には今現在のニーズを反映する
- インタフェースは汎用にする
- 複数用途に利用できる程度には汎用
- それでいて今現在のニーズにも簡単に利用できる
- 汎用の利点
- 他用途に流用できれば、将来の工数短縮
- 他用途に流用できても、単純になる(意外な利点)
- インタフェースが単純で、実装をよく隠蔽した「深い」モジュールになる
Example: storing text for an editor
class Text...
void backspace(Cursor cursor);
void delete(Cursor cursor);
- UI側で範囲削除が欲しくなったらTextクラスに↓を生やしますか?
class Text...
void deleteSelection(Selection selection)
- UIに関する知識の漏出
- 「選択」や「バックスペース」がTextに反映されてしまっている
- ので、UIを開発する者はTextクラスも開発しなければならなくなる
- モジュール設計の目的「個々のモジュールを独立して開発できる」に反する
A more general-purpose API
class Text...
void insert(Position position, String newText);
void delete(Position start, Position end);
text.delete(cursor, text.changePosition(cursor, +1));
text.delete(text.changePosition(cursor, -1), cursor);
- 用途特化モジュールとの比較
- 呼び出しのコードはいくぶん長くなるが…
- 明瞭である
- コード量減る
- Textクラスに生えている大量の用途特化メソッドを消すことができる
- UIの知識が漏出していない
- 知識の隠蔽
- 認知の負荷が低い
- 開発者が知る必要があるのは、少数の単純なメソッドのみ
void backspace()
はfalse abstraction
- 抽象化とは「重要でない詳細を削ぎ落とす」こと
- 利用側にとって重要な詳細は抽象化・隠蔽してはいけない
- 「どの文字が消えるか」という知識が隠蔽されている
- が、UIは「どの文字が消えるか」知らなければならない
- 「不明瞭」となり、複雑性をもたらす
- 【補】認知の負荷、もしくは「わからないことがわからない」につながる
- ソフトウェア設計上、誰が・何を・いつ知る必要があるかは最重要
Questions to ask yourself
- 行うは難し
- 汎用と用途特化との間のよい落とし所を探るために、次のことを自問自答せよ:
What is the simplest interface that will cover all my current needs?
- 機能を保ったままメソッドの数を減らすことができれば、汎用のメソッドを作ったことになる
- メソッドの数を減らすべきなのは、個々のメソッドを単純なままに保てる場合のみ
- 「メソッドを減らすために大量の引数を追加する」というのは、単純化になっていない可能性がある
In how many situations will this method be used?
- 特定の1用途向けのメソッドは危険信号
Text
クラスのbackspace()
メソッドみたいなやつ
- 汎用メソッドにまとめられないか検討する
Is this api easy to use for my current needs?
class Text...
void insertChar(Position position, Char newChar);
void deleteChar(Position position);
- 汎用メソッドの別解
- 「文字列を挿入したい」「範囲削除したい」というニーズには使いづらい
Conclusion
- 汎用インタフェースは用途特化インタフェースより優れた点多数
- 「深いモジュール」になる傾向
- クラス間をきれいに分離
- 「やや汎用」のモジュールを作ることが、システム全体の複雑性を減らす最良の方法