アジリティを高めるための設計

この発言でもうすべてを語っているんだけど、たとえばDDDの流行(?)によりレイヤー化アーキテクチャ、そこにDIPによる依存関係の整理を加えたオニオンアーキテクチャやヘキサゴナルアーキテクチャ、それらを統括した概念としてのクリーンアーキテクチャなどへの関心はますます高まっているような気がする(要出典)。それ自体は喜ばしいことだとぼくは考えているのだけれど、一方で、初学者などがいきなり「ふんふん、これが"正解"か」と思って、その「構造だけ」を真似してみるという不幸な事故があとを絶たない、というような状況がいまあるような気がしている(要出典)。

そこに存在するのは、「こういう構造だよ」とか「こうやるんだよ」ということだけだ。重要なのは、そうではなくて「こういう構造にすることで、こういう場合に変更に強くなるでしょ。だから、その変更があることが予想できるときにはこうしたらいいよね」くらいまで理解をすることだと思う。

ぼくたちはプログラミングパズルを解いているわけではなくて、実際には「プログラミングを使って問題を解決しようとしている」はずだ(超絶技巧系の遊びだとまたちょっと話は違うんだけど、それはそれとしておく)。そのときに「良い設計」というのは、「新しい問題が出てきたときにすぐにそれに対応できるアジリティの高い構造になっていること」(この「アジリティ」という考え方については、moznion氏と話をしたことに多くを依っている)だと思う。

抽象的な話になったので、例を出したい。

ツイートにもある通りだけど、たとえば「なぜMVWhateverにするのか」というのは、簡単だ。「ViewとModelが密結合したコードだと、"見た目の変更"のときにデータやロジック、状態管理が邪魔をして簡単に見た目の変更ができない」とか、逆に「ロジックを変えようとしたら見た目が壊れちゃうから簡単にロジックの変更ができない」というような、「新しい問題にぶち当たったときにアジリティを落としてしまうような問題」を解決するために役立つパターンだからだからだ。

そして、この「UIとそれ以外を分けないでいるとアジリティ落ちる」問題は、どんな領域のアプリケーションでも「ありがち」なものだらか、「UIとそれ以外を分けるパターン」は広く使えるパターンとして「とりあえず選択しておいてもペイする」ようなパターンだったりする。けど、そうじゃないものもある。

たとえばDDDの戦術的設計(EntityとかValueオブジェクトとかあれね)とかは、本当にそれを選択しないとあとあとアジリティを落としてしまうような問題を引き起こすのかどうか、一旦考えてみてもいいと思う。単なるCRUDの簡単なTODOアプリケーションに対して、いちいちEntityやValueオブジェクトを考えることが、どれだけ後々のアジリティに影響するだろうか。むしろ、それは過度な分割を生み、後々のアジリティを落としてしまうのでは?

もちろん、「戦術的設計をいざやるぞ!ってときに、いきなりやってもできなそうだから、練習のためにやってみます」ならわかるし、そういうのをやってみることはとても価値のあることだと思う。一方で、それが後々もメンテするようなアプリケーションであるならば、「この構造を選択したのは、後々こういう変更があるときにすぐに変更できるアジリティを確保したいからです」を答えられないようなら、「XXアーキテクチャでいきます!」「XXパターンで行きます!」を選択するのはやめたほうがいい。

さて、「なぜその構造にしたの?」に対して「後々こういう変更があるときにすぐに変更できるアジリティを確保したいからです」を言えたとして、もうひとつ考えるべきことがある。それは「ほんとうにその変更って起こる可能性高いの?」ということだ。「起こらないはずの変更」に備えた部分は、「誤った構造化」となって、起こらなかった問題とは異なる「起こった問題」にぶち当たったときの負債となる(見に覚えがありませんか?ぼくは腐るほどあります)。

と、じつはぼくはサラッといまとても難しい話をしていて、これは要するに「未来を予測せよ」と言っているのと変わらない。未来を予測しなくては、「起こる問題」と「起こらない問題」はわからないからだ。しかし、そう簡単に未来が予測できればソフトウェア開発ってのはこんなに難しくないわけで、このあたりは本質的にソフトウェア開発の難しさであると思う。

少なくとも暫定的な話としては、「ある構造を選ぶときには、"こういう未来の問題に対してアジリティ高く反応するため"を言えるようにしよう」「予測できる未来(見た目は絶対かわるよね)(最初は予備校向けのサービスとして売出しますが、そのあと学校に攻め込んでいく予定となっています!)(このアプリやサービスが解決しようとしてる問題領域はめちゃめちゃでかいからそういうレベルのでかさに対応できないとだめだな)については、それに対応する構造にしておこう」「予測できない未来は予測せず、"それに備えた構造"は負債化する可能性が高いのでやめよう」というあたりに結論をおいておきたい。

で、最初に戻るわけです。「アジリティ高くすることが重要なわけで、UI変更のアジリティ高くするためにPDSを意識したり、モデルに関してもドメイン層とインフラ層を分離したりするわけで、"その分離によってどういう変更に対するアジリティを高めたいのか"を説明できないならやるな。」