修行の場

知人が言っていました。これは修行だと。

Code Complete Chapter 5のDesign Practices

Code Completeの5章に良い設計にたどり着くための"Heuristic"が書かれていて面白かったのでまとめます。

f:id:sam_yusuke:20190113060404p:plain

Practicesの絵

イテレーション

"Design is iterative process"と書かれていますが、
設計のプロセスは一方向で終わるものではなく、抽象度の低いところから高いところに戻り、また新たな設計をかんがえ…とイテレーティブにやるものだそうです。
クラスのルーチン設計あたりまで考えて、サブシステムに戻ってよりよい方法を探す。などと繰り返してもいいかもしれません。この方法がうまく行くちょっとした裏付けとして、コードを一度書くとかなりの知見が得られるため、その知識を使って似たコードを書きたくなる。という事実があげられていました。

似たような考えで、昔いたチームではかなり極端であまり設計せずにそれぞれのメンバーが数万業のコードを書いて、その実装時の知見を使って設計し直せばより良い設計ができるという考えでした。そこまで長いサイクルにしなくても設計レベルでサイクルを回して、実験的プロトタイピングと組み合わせればもう少し効率よく出来たのかなと思います。

分割統治法

サブシステムレベル、パッケージレベル、クラスレベル…と分割していき、行き詰まったら、上のレベルに戻って他の分割方法を試す。と行ったやり方です。

ボトムアップトップダウン

設計をする際には極端な方法として、トップダウンボトムアップなアプローチがあります。実際は組み合わせて使い、相補的な関係にあります。

トップダウンアプローチは、デザインの各レベルで人の脳の限界程度の複雑さに分割すればいいので容易というメリットがあります。また、実装の詳細について考えるのを遅らせられるため、情報の隠蔽などを早めに考えられるというメリットもあります。

ボトムアップアプローチは、実装時に利用するライブラリやシステムのインターフェースなど実装面の制約にあった設計にたどり着きやすいというメリットがあります。また、共通ユーティリティの抽出などにも役立ちます。(ライブラリの設計や選定に必要)ただ、複雑な実装をまとめて抽象化するのはトップダウンと比べると難しく設計のすべてのレベルに使えるわけではありません。また、ボトムアップに思いついたパーツで必要なものを作れるとも限りません。

昔いたチームでは一方向のトップダウンだったので、設計と実際のコードのズレが大きく、別のチームでは研究者が多く、ボトムアップアプローチが推奨されすぎており、後々コードの再利用のコストが大きくなるという問題がありました。
設計フェーズを双方のプロセスでやって、現実とのズレが少なく、複雑性の排除を実現できる設計を目指さなければならないと思います。

実験的プロトタイピング

設計段階で"十分に具体的な疑問"に答えるための実験をする"最小限"の"捨てコード"を書くことが設計において有益であることが述べられていました。
ソフトウェアエンジニアが設計すると、よく実施すると思います。

プロトタイピングにより、データベース、キューシステム、ライブラリなどの選択をすることで、それらにあった設計ができますし、データの読み込みであれば一括読み込みか、lazyな読み込みかなど決定できます。

疑問は具体的な問いとして落とし込まなければならないとのことでそうでないと、実験自体が意味の無いものになる可能性があるので納得です。例えば、
Xという条件下で1秒5000トランザクションをさばけるDBか?
Nレコードのテーブルに対する操作パフォーマンスが十分か?
といった問いが挙げられていました。

最小限の捨てコードでなければならない意味は、実験時間の最小化でしょう。productionで使われるかわからないコードを捨てコードとしなければ、実験コードが手の混んだものとなり、プロトタイピングの目的以上に時間を使ってしまいます。

今後、様々なシステムへの機械学習の導入が進むにつれて実験も必要となり、重要なPracticeとなりそうです。
例えば、既存の分類モデルをfinetuneしたもので正解率がX%以上になるか?といった性能の問に答えなければならないかもしれません。既存のモデルで無理なら学習データの収集や再学習の仕組みも設計に盛り込むという判断をするかもしれません。