OCamlでClean Architectureもどき
このところOCamlでアプリケーションをほそぼそと作っているのですが、その過程でClean Architectureっぽいものを採用してみました。 <!–more–> 作っているアプリケーション自体は、完全に趣味の領域のものなのでまだ公開していません。ただ、OCamlであってもなんであっても、ある程度の規模になったらなんらかの方法論は必要かな、と思い始めました。 packageそのものがいっぱいある moduleもいっぱいある どことどこが関連してるかよくわからなくなってくる これはもしかしたらmodule/packageの分割方法自体が問題か・・・? ある程度Clean Architectureっぽいことも出来るようになってきたので、自分の知識を整理する上でも書いてみます。 Clean Architectureとは? ググってもらうのが一番早いのですが、それは流石に不親切すぎるので・・・。 Clean Architectureは、 http://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html が原典とされ、 Robert C. Martin によって提唱されたアーキテクチャです。 Onion Architecture/Hexagonal Architectureなど、過去のアーキテクチャも参考にしながら作成されたものになり、それらの特徴も一部受け継いでいます。 Clean Architectureは、以下のような制約を導入します。 ある層は、それより外側の層に依存してはならない ある層は、それより内側の層にのみ依存する これがClean Architectureにおける唯一の制約です。層としては、基本形として以下を提唱しています。 Entities いわゆるドメインモデルです Use Cases アプリケーションロジックです。Domain Logicよりは特殊化されていますが、サブシステムとかがないアプリケーションだと、大体がここにロジックがある感じになるそうです Interface Adapter/Gateway/Presenter UIやData Storeなど、外部との連携を行うための層です。 APIをGatewayとして実装する、UIの情報をPresenterから返す、とかいろいろあります Frameworks and Drivers Framework specificな処理とかです APIをFrameworkの機能を利用して作成する、とかであればここになります ただ、これ以外にも 層を 追加することは可能です。唯一の制約である、層の間にある依存方向を守る限り、層の増減は自由です。 OCamlでの課題(自分的に) OCamlである程度の規模のアプリケーションを作成する場合、恐らくある程度の単位でパッケージを作成する場合が多いと思います。最近は dune を利用すると思いますが、使わない場合であったり、一パッケージに全ファイルを置くのは色々問題があります。 module名がめっちゃ長くなる 1ファイル1moduleとかやると、ファイル名もめちゃくちゃ長いですが、そのmoduleを利用するときにすごく面倒になります 一般的なモジュール名がかぶる 特に被るのが Types とかの名前です 1ファイルに複数のmoduleを書くと見通しが悪い 1データ型1module主義とかやると、単純にファイルの中身がかなり長くなります OCamlerはあまりその辺は恐れないようですが。 この辺はfoldとかをうまく使えばいいのかもしれません 特に、頻繁に使うmodule名が長いと色々だれますし、毎回aliasを書くのもしんどいです。以前よりもmoduleを明示しなければならないケースは少なくなりましたが、一級moduleを利用しているとやっぱりきついです。 パッケージを分ける上での基準も厄介です。大抵は機能とか役割別だと思いますが、結構分けづらい感じになっていったりで・・・。 そこで、パッケージを分ける基準として Clean Architecture を使ってみました。 OCaml on Clean Architecture とはいっても、基本的には各層ごとになるようにパッケージを分割するだけです。そうすると、dependenciesの方向制御も簡単になります。私は、 domain, usecase, gateway, binary と分けています。こうすると、OCamlの制約とduneの機能で、以下のような利点を自動的に得られます。 ...