漠然と、あるいは感覚的・直感的に、「こういう設計は良くない」と感じることは多いけど、具体的になぜそれだとダメなのかと問われると上手く言語化できないことも多い
それを上手く言語化して説明できるようになるために、ここで思考を整理してみようという試み
- 関心は一箇所にまとまっていた方がよい
- いろいろな場所に関心が散らばっているよりも、当然まとまっていた方が理解しやすいしメンテナンスも容易
- 「依存するものをまとめる」とも言える
- 例えば「ユーザー取得API」「投稿取得API」「ユーザーモデル」「投稿モデル」を「API」と「モデル」ディレクトリにまとめるのはよくない(ディレクトリ内のファイルにはそれぞれお互いに依存関係がないから)
- 「ユーザー」ディレクトリに「ユーザー取得API」「ユーザーモデル」を入れ、「投稿」ディレクトリに「投稿取得API」「投稿モデル」を入れるのが正解ではないか(APIはモデルに依存している)
- 例えば「ユーザー取得API」「投稿取得API」「ユーザーモデル」「投稿モデル」を「API」と「モデル」ディレクトリにまとめるのはよくない(ディレクトリ内のファイルにはそれぞれお互いに依存関係がないから)
- 共通化を行うと、分岐が増えて複雑になることがあるので、しない方がよい場合も多い
- (別の場所で)分岐が増えるということは、↑の関心の原則にも反することになる
- 例えばコードをAという環境とBという環境で動かしたいとする ただしAではXとYというAPIが使えるけど、BではYをセキュリティ上の理由で使ってはならないとする 一つのコードをAとB両方で動くようにすると、随所で「BであればYを呼ばない」という分岐を仕込む必要が出るし、コードを書いている時も常に「BではYを呼ばないように気をつけなきゃ」という意識を持っておく必要があり、心理的な負担になる さらに、人間は完璧ではないので、うっかりBでもYを呼んでしまうコードを書いてしまう可能性はもちろんある それならば、コードを無理に共通化せずに、最初からA専用コードとB専用コードを別々にしてしまえば、上記の問題は解決する
- 責任は自分で持つ
- 「この関数を呼んでも呼んではいけない場面では向こうでエラーもしくは無視してくれるから、こっち側で制御は不要」というのはよくない
- なるべく外部の挙動に依存しない実装にした方がよい
- バグ防止はもちろんのこと、コードを読む側にとっても、呼び出し側で明示的な制御がされているのとされていないのとでは理解が異なる
コードベースは時間と共に大きくなっていくけど、基本的に、その中でもいかに複雑さを減らせるかがとても重要
複雑さを減らせるなら、コードが冗長になったり、ボイラープレートが増えても構わないと思っている
冗長であるということは、ある意味明示的とも言える
それほどまでに、複雑さというのは忌避するべき対象だと思っている
複雑になったコードはバグを産み、メンテナンスを難しくし、コーディングのモチベーションを下げる
そのようになったソフトウェアはいずれ破綻する