Code should be obvious
-
不明瞭さは複雑性の2大原因のうちひとつ
-
重要な情報が新参の開発者にとって明らかでないとおこる
- 【補】「数週間後の自分」も含まれると思う
-
- 本章ではコードの理解しやすさを左右する要因について述べる
-
理解しやすいコード
- あまり考えずにすばやく読める
- 推測が正しい
-
理解しづらいコード
- 理解するのに時間と労力がかかる
- 誤解のおそれも多い
- 理解しやすいコードはコメントが少なくて済む
-
「理解しやすさ」は読み手の心理
- 自分のコードよりも他人のコードに対して気づきやすい
- コードレビューで判定するが最善
- コードを理解しづらくする因子を理解し、よいコードを書く方法を学ぶ
Things that make code more obvious
-
最重要テクニックは既出
-
良い命名
- コードの振る舞いの明確化
- ドキュメンテーションの必要性を減らす
-
一貫性
- 読み手はコードからパターンを認識し、詳細を読み込むことなく推測できる(それは合っている)
-
-
スペースを賢く使う
- Docコメントのインデント
-
処理のフェーズ間の空行
- 実装コメントの上に空行を置くと、コメントを読みやすくなり特に有用
-
コメント
-
どうしても理解しづらいコードになることもある
- 【補】例: 区間端を含むのか含まないのか、とか
- このような場合、コメントで情報を補うのが重要
- 読み手の立場に立って、何が混乱の元となりそうか考えて書く
-
Things that make code less obvious
- コードを理解しづらくするものは数多くある
-
有用さゆえ、理解しづらくとも使うものもあるだろう
- 例: イベント駆動プログラミング
- ドキュメンテーションを添えることで、読み手の混乱を最小化できうる
-
イベント駆動プログラミング
-
制御フローを追いづらくなる
-
ハンドラは直接実行されない
- 関数ポインタやinterfaceを通じて、間接的に呼び出される
- 何が実行されるかは実行時までわからない
- 正しく動作するという根拠・確信を得づらい
-
- こういった不明瞭さは、各ハンドラのインタフェースコメントに「いつ実行されるか」を記述して補うと良い
-
/**
* This method is invoked in the dispatch thread by a transport if a
* transport-level error prevents an RPC from completing
*/
void
Transport::RpcNotifier::failed() {
...
}
-
ジェネリクスコンテナ
- C++の
std::pair<T,U>
等 -
メンバ名が汎用なので意味を汲み取りづらい
- 【補】
std::pair
ならfirst
,second
- 【補】
-
ジェネリクスコンテナを使わず、用途特化のコンテナクラスを作るが吉
- インタフェースコメントも書ける
-
一般論として、ソフトウェアは書き手の便利ではなく読み手の便利のために設計されるべき
- ジェネリクスコンテナは書き手の便利のためのもの
- 代わりに読み手に混乱をもたらす
- 読み手にとって理解しやすくするために、書き手は何分か余計に費やしてでも、用途特化のコンテナクラスを作るべき
- C++の
-
宣言と割り当てで異なる型
-
例: メンバ宣言は
List<T>
、コンストラクタでの割り当てはArrayList<T>
ArrayList<T> --|> List<T>
-
非機能的な特性が異なり、「実際の型が何であるか」が利用側に影響する
-
非機能特性の例
- パフォーマンス
- スレッドセーフティ
- 【補】LSP違反
-
- 宣言の型を割り当ての型に合わせるべき
-
-
読み手の想定に反する
-
例: mainがreturnするがアプリケーションがexitしない
- メインスレッドは終了するが別スレッドが動き続ける
- コメントで明示すべき
-
Conclusion
- コードが理解しづらいということは、読み手が重要な情報を知らないということ
- コードを理解しやすくするには、必要な情報が読み手に必ず伝わるようにしなければならない
-
方法は3つ
-
必要な情報そのものを減らす
- 抽象化
- 特殊ケースを減らす
-
新たな情報なしにコードを読めるようにする
-
読み手が他のコンテキストで得ているであろう情報を活用する
- 規約に従う
- 読み手の想定に従う
- 【補】一貫性
-
-
コード中に情報をこめる
- よい命名
- コメント
-
英語
-
judicious
- 賢明な