/<role>/<domain>/DomainNameRoleみたいなディレクトリ階層よりも/<domain>/<role>/DomainNameRoleみたいな階層の方が素直だと思う

こんなの探せば10年とか20年前にも似た議論があって結論出てそうだし、ドメイン駆動設計系の人が実践論として言ってそうなものだけど。

アプリケーションフレームワークとかボイラープレートみたいなものをいくつか眺めていると、/Controller/SignIn/SignControllerみたいなディレクトリの組み方を薦めてるものが結構あるけれど、これは素直じゃないなと思った。

だいたいこんな階層になるやつ。

  • /
    • Action/
      • Signin/
      • Report/
      • Editor/
    • View/
      • Signin/
      • Report/
      • Editor/
    • Repository/
      • Signin/
      • Report/
      • Editor/
    • UseCase/
      • Signin/
      • Report/
      • Editor/

何が素直ではないと思ったかというと、

  1. 具体的な問題領域よりも先に教条主義的なコードの役割分担が優先されている
    • 問題領域に応じてHelper増えたりとか色々あるのが本当だよね
    • 例えばバージョン情報みたいな画面だと View だけに色々ベタに書いていいはずで(バージョン情報の他問題領域から再利用とか、普通そんなに起きねえよ)
  2. 結果, 同一の問題領域のコードなのに木構造的に再従兄弟みたいな位置にいるコードが多くて見通しが悪い
    • 凝集度悪くね?
  3. 問題領域に応じたコードの組み方がやりにくい
    • 例えば「ReportドメインのViewはReactじゃなくてVue使いたい!(そちらの方が技術的に向いている)」みたいな需要に合わない。この構成だと、例えばView/の下の一箇所を変えると、隣接するディレクトリに配置されたコード全てを同じように変えたくなってしまう。それが人情ってもんです。

な辺り。

あとで移行とかリファクタをしようと思った場合に一番面倒なのは 3 だし、普段コードをいじるときは 2 がストレスになるけど、何れにしても「問題領域に応じて最適な道具を用いる」という思想とは噛み合わせが悪いし、私はそういう思想なので、息苦しさとかデメリットばかりなように思う。なので、自分がゼロから組む場合はもっぱら:

  • /
    • Signin/
      • Action/
      • View/
      • Repository/
      • UseCase/
    • Report/
      • Action/
      • View/
      • Repository/
      • UseCase/
    • Editor/
      • Action/
      • View/
      • Repository/
      • UseCase/
      • Helper/

みたいに, 問題領域の方を階層の上に置くようになった。 こっちの方が問題に合わせてコードを書く、という場合は素直だと思う。

/<コードの役割>/<問題領域>/問題領域_コードの役割.拡張子 みたいなディレクトリ構成を採用してるフレームワークは、そのフレームワークが想定する・楽にできる問題領域が1つ〜2つ程度なんじゃないか、それ以上を単一のアプリケーションに入れ込むことを想定してないんじゃないかと思うし、用途としてはそんなに向かないだろう。

だからと言って「マイクロサービス最高!時代はマイクロサービス!マイクロサービスしない奴は何をやってもダメ!」とか言うつもりはないんだけど、そこらへんの射程の距離感は常に意識しておくべきで、それを忘れるとコードが無秩序に増え続けるのをウッカリ見過ごしてしまいそう。