半分愚痴です。
MVCやMVP、なんちゃらアーキテクチャなど、色々ありますが、あれらのコード全体の構成を決める所謂デザインパターンうち「どれを使うか」「使わないか」というのは大体4つの観点で決まると思います。いや、決めるべきだと思います。決められていないことが多々あります。というお話。
※もう少し上のレイヤーのアークテクチャーや、デザインパターン、フレームワーク、開発手法郡・ツールにも似たことが言えると思います
- 大前提、デザインパターンを適用するデメリット
- 1.テストを書くかどうか
- 2.完璧なプログラムか、スピードか
- 3.誰がプログラムを書くか、誰最適か
- 4.プロジェクトの規模や目的
- デザインパターンを決めるフロー
- 例外:部分的に使用する
- 例外:メリットが上回ると信じている場合
- デメリット・コストは誰に降りかかるのか理解する
- 普通に組んでも結構よくできるよ
- デザインパターンの思想だけ理解する
- デザインパターンを使うなら必ずやるべきこと
- まとめ・終わりに
大前提、デザインパターンを適用するデメリット
- 複雑性が上がる
- 学習コストが掛かる
- 慣れの問題
- 非公式の外部知識を使っている
- 変更リスク
- 低レイヤーの仕様変更リスク
- ニッチリスク
大体わかると思いますが、ざっと書きます。
複雑性
→大抵の場合、登場する概念が増えるので複雑さは増します
学習コスト
→複雑性が上がる、決まりやルールを覚える必要がある、思想の理解、ハマった時にどうするかの経験値が必要、チームメンバーと認識を一致させる必要などで学習コストが掛かります
慣れの問題
→学習コストが必要ということは、当然そのデザインパターンに慣れるのに時間がかかるということです。つまりある時点では誰しも誤ったコードを書きます。その誤った時点で指摘してくれるスーパーな人が居てくれればいいですが、そうではなく数人が議論の上進めなければならないならその分のリソースも必要になります。そこまでしてやる価値があるのか考えなければなりません。
非公式の外部知識
→ライブラリと似たような状況です。プログラムには、コードには存在しないお約束や決まりごと、理想形や書き方など、様々な情報が隠れています。
これは脳内に予めインプットしておかなければなりません。これらは大抵はドキュメントや個人が投稿したTIPSにまとまっていますが、非公式の場合、その情報がまとまっていないリスク、情報が不足しているリスク、そしてそれらをチームメンバーで一致させるコストが掛かります。
一致させられないと、リーディングすら手こずります。
変更リスク
→別のデザインパターンに変更するのが大変。やめるにも大変。
低レイヤーの仕様変更リスク
→例えばiOSだとSwiftとか、Cocoaとか、iOSのバージョンとか、そういう仕様が乗っかる低レイヤーの部分が変更された時、それまでの書き方がしっくり来なくなるリスク、新しい書き方に対応し辛いリスクなどが起こります。
ニッチリスク
→そのコードを上手く引き継げる人が少ない問題。
まず大前提として、これらを理解した上で、それでも何かを解決しうるメリットや状況が必要になります。
1.テストを書くかどうか
非常に多くのデザインパターンは「テストが書きやすい」と言っています。
逆に言えばテストを書かないならそれはメリットではありません。
これはつまり「テストを書くべきか」という難解な議論が上流に来てしまいます。これはデザインパターンより厄介なテーマです。
世のプログラマーが思ったよりも自分の近傍しか見えてなくて、自分の見えてる{バックエンド/エンドフロント/アプリ}×プロジェクト状況×事業状況でそれぞれ喋るのでまともな議論が成り立ってないんですよね。
雑に言えば、バックエンドはテスト書いて当たり前だし、フロントはあまり書かないし、アプリも大して書きません。理由は手動テストし易さと必要テスト量に依存しているからで、更にその理由は自動テストとは手動テストし辛い部分を担うべきだからにほかなりません。
昨今のテスト必要必要議論は、あれはTDDが良いか悪いかという議論が混ざってしまっています。両者は別物です。
とか言う話をし始めなければならないので、この時点で大抵の議論は詰むんですが。
その議論を脇においておくにしても
- 今書くのか
- 将来書きたいのか
- たぶん当分書かないのか
で、「たぶん当分書かない(書けない)」ならば、この「テストを書きやすい」メリットはメリットではありません。
2.完璧なプログラムか、スピードか
美しい完璧なものを数学的、とりあえず使えればいいやというものを工業的と言うと仮定します。
デザインパターンが目指しているのはおそらく数学的な美です。
単一責任の原則でも、疎結合でも何でも良いんですが、「しっくり来る」コードというのは時として事業の成否を見ていません。
もちろん完璧なコードの方が、超長期的に見て可変性に優れているかもしれません。
なのでもっと言えば「数年単位の品質と持続可能性」か「今この時点ですばやく仕上げたいか」です。
すばやく仕上げたいなら、よりオーソドックス・シンプルなデザインパターンを使うか、そもそも使わないかのどちらかです。
3.誰がプログラムを書くか、誰最適か
2は少しウソを書きました。
例えばあるデザインパターンに慣れている集団が居た場合、最も効率よく仕上げるにはそのデザインパターンを用いるべきでしょう。
これはチーム最適です。同じ会社内のチームではこれでいいと思います。
誰に引き継ぐかわからないし、どういう人が入ってくるかわからないなら、市場最適です。これは、学習コストのデメリットを上回らない限り、デザインパターンを使うべきではありません。
誰か1人だけ知ってるデザインパターンを使うというのは、それは個人最適です。その人がチームリーダーとして数年引っ張っていくのであれば使って良いと思います。逆に言えばその責任が生じます。
4.プロジェクトの規模や目的
ソースコードの行数が膨大になったり、人数が多くなったりすると話がガラッと変わってきます。
例えばマイクロサービスやiOSのMicroViewControllerという思想は、大規模な開発でもスケールするように考えられた思想です。
一般的な規模の開発では、むしろマイナスに働くこともあります。
このようにプロジェクトの性質や規模、目的によってデザインパターンがどのような効果をもたらすかは異なります。注意したいのは、最新の盛り上がっている、しかしニッチなデザインパターンはまだそういったナレッジが溜まっていないので、いずれにしてもリスクが存在するということです。
デザインパターンを決めるフロー
テストをめっちゃ書く? → テストを書きやすいデザインパターン
決まったチームで運用していく? → 慣れてるデザインパターン
誰が引き継ぐかわからない? → no デザインパターン
個人開発、チームリーダー? → 自分で決める
例外:部分的に使用する
どうしてもコードが複雑になって、書きづらいという時は部分的に使用すると良いと思います。ただし後任者が理解できるようにコメントを書くなど工夫すると良いでしょう。
例外:メリットが上回ると信じている場合
その場合でも、計測はしたほうが良いと思います。
デメリット・コストは誰に降りかかるのか理解する
プロジェクトのオーナーやステークホルダー全員に降りかかります。
学習コストは学習する人だけが困るわけではありません。
普通に組んでも結構よくできるよ
最近のWeb・アプリ界隈なんてそうじゃないですか?
銀の弾丸は無いですし、良さそうな思想は低レイヤーや公式が仕様に含めることが多いと思います。まあモノによりますけど。
デザインパターンの思想だけ理解する
個人的に、デザインパターンは丸っと使って型にはめるよりは、概念や思想だけ理解して、普通の書き方で上手く再現したほうが美味しいのではないかと思います。
もちろん縛らなければチームメンバーがその書き方をしてくれるかわかりませんが。例えば低レイヤーになら適用できるはずです。
デザインパターンを使うなら必ずやるべきこと
ドキュメントの整備です。
未知のデザインパターンでコードから仕様が読み取れない+ドキュメントがない、だと後任が本当に詰みます。
古代文明の遺跡を発掘したような感じになってしまいます。
もちろんコメントも必要です。
まとめ・終わりに
テスト原理主義者とデザインパターン原理主義者が多くてつらいです。
とか、あまり大きな声で言えないのでブログにしか書きませんが。
何かを使う・やる前提で話が進むことが多くて、それはイチ企業内の話であればひょっとしたら構わないかもしれませんが、もう少しカオス度が高い場面では「普通」にやるのも一考したいところです。
事業的な観点で「それやって誰が喜ぶのか」くらいで考えられると良いと思います。
こういうのって、一昔前だと独自フレームワークみたいな感じですよね。今だと有り得ないって言われますが、一時期独自フレームワークを誇ってた会社はありました。
ただ、痛し痒しなのは、デザインパターンが好きなエンジニアが特に優秀な層に一定数居る分、そういうデザインパターンは無くなりませんし、誰かが保守・改修しなければならないので、デザインパターンの知識は必要になるんですよね。
まあそれを保守してる頃には作った当人は別のデザインパターン使ってるんでしょうけどね。
あと、そういう経緯で「デザインパターンを使ったほうが優秀なエンジニアが採用できそう」みたいな話を数回聞いたんですが、厄介エンジニアの方が釣れませんかそれ?
普通に作って詰む確率と、こだわったデザインパターンで詰む確率、どっちの方が上でしょうね?
属人性についてもそうです。果たして属人性が高まるのはどちらでしょうか。プロジェクトの事をよく考えて、デザインパターンの効能や性質について理解し、ステークホルダーと相談の上決めたいものです。安易に実験場にしてはいけません。