Packagingについて考える
packagingと普通のディレクトリの間の抽象度の仕組みが必要?
理想的には、プログラム内の全てをライブラリを切るぐらいの感じで作りたい
monorepoみたいな
しかし、そうすると個別にpackage.jsonとか用意するのが面倒(?)
そのへんの手間を省くために、一緒くたに扱っているようなイメージ
一方で、一緒くたに扱っていると、どこからでもimportできてしまう(?)
この中間となるようなpackagingの仕組みがあると良い(?)
そもそもディレクトリを分ける意義
かなりいろいろあるはずmrsekut.icon
一緒に使うものであるということを明示する
異なる抽象度であることを明示する
単に抽象度の異なる内容のものが2つのファイルに分かれているだけでもわかる
グルーピングによる抽象の明治
フクスのファイルを1つのディレクトリにいれることで、1つとして認識できる
f1,f2,f3の3つの機能に、2つのレイヤーusecse, repositoryとある時
こういうわけかたと
u1,r1
u2,r2
u3,r3
こういうわけかたとできる
u1,u2,u3
r1,r2,r3
両方できるべき
どちらか1つに固定しないといけないことじたいがおかいしい
file treeでノイズを消す
file treeのviewを自由にいじれる
高い抽象度での関係の可視化
ディレクトリ構造の表現として最も優先順位が高いのは、
どういう風にmoduleが構成されているか、というのができるだけ短い時間で理解できること
だと思う
そう考えた時、
(これが適していることもある)
この辺がわかることが本当はもっとも要件としての優先順位が高い
どういうmoduleがあるのか、登場人物の列挙
そのmoduleはどのmoduleに依存しているのか、module同士の関係
そのmoduleのinterfaceは何なのか
interfaceだけが大事で、moduleの内容・詳細は本当にどうでもいい
寧ろノイズなので、どっか知らない宇宙に飛んで行ってて欲しい
いわば、tsの型定義ファイルみたいなやつ1枚あればそれでいい
似た概念で括ることと、モジュールの線引はずれる事がある
似た概念で括るということは、その概念が消えたときにその括り(ディレクトリ)を消せば、半自動的にそれに関するものが消えるということを意味している
しかし、モジュールの線引は必ずしもそうはならない
例が大事だが、例をあげるのが難しい
Curtain moduleの中に frill moduleのようなものがあった時、
frillのatomはどこに置くべきかみたいな感じで
pbf的にはfrill moduleないだけど、
module的に考えると、frill module外でしょ、みたいな
それを具体的なドメインと結びつけるmain関数的なものは、
全く別の仕方で切ることになるから、それらがフラットに並んでるのはおかしい
PBFを批判したところで、単にmrsekut.iconのPBFの理解がおかしいだけ、という可能性がある
同じものを近くに置くという発想はかなり良いのだけど、それを「feature」とかいう謎の用語で命名してるのがかなり良くないのでは
コーディングしてるとき、何らかのmoduleについて実装している時、
「そのmoduleが参照してはダメなもの」はエディタ上からどこかへ行ってほしい
候補にも検索にも出てくる必要がない
ファイルツリーにめちゃくちゃファイルが並んでいるのが邪魔
https://gyazo.com/cab31f8cf083352111babb27c7a3e45a
汎用的な機能と、ドメインに特化したデータ構造のようなものがあり、これらは直交する
個別のEntityは、横断した機能を選択して使う
こう考えた時に、E1,E2,E3,...とfa,fb,fc,...は全く別の抽象度にそんざいする
これらは同じディレクトリにフラットに存在するのはおかしい
あとから見た人が識別不能なので
縦軸の方の呼び方がわからん
図ではEntityと書いてるけど、別にEntityに限らんし
ただ、謎の分類を施して、後にどちらに配属するか悩むと良くない
分けるなら、それぐらい定義を明確にすべき
内部の構造?内部の機能(インターフェース)?
サーバ側を考えてみよう
zennのようなpostを返すようなサービスを作る時に
機能で言えば
postsを取得する
ランキング上位のpostsを取得する
検索ワードをもとにpostsを取得する
と言ったものがある
一方で、内部のデータの構造を考えるならば
posts
ユーザ
コメント
のように分かれるわけである
サービスの利用者から見れば前者の方が重要で、コードの書き手からすると後者のほうが重要なようにも思える
で、後者の分け方は別にfeatureではない
この分け方の内部に前者の分け方があると読みやすい
例えばHogeSize、PiyoSizeというものがあったとき
height, widthは個別で色々な計算過程をたどる
このとき、ディレクトリはSize単位で作るが、実際の計算過程はディレクトリで表現不可能である
monorepoとかもわざわざそんな大仰な仕組みがなくても自然に実現できるべきである
実はgitなどのVCSによる制限を食らっている可能性はないだろうか
packageの管理としてもショボい
ファイル内の任意の場所から、任意のものをimportできてしまう
featureとしてのグループと、packageとしてのグループが対応しない
なんかもっと関数とかの見た目と近くなるはず
そのpackageというまとまり
に依存しているもの、
から公開しているもの
をもっと明示的に見えるようにする
関数を作るときにその抽象、つまり引数と返り値が重要となるように、
moduleに対しても同じことが言えるはず
moduleが、どの外部moduleに依存しているのかを型やプログラマブルなツールで取り扱えるべきではないのか
これは1つの親しか規定できない
2つの親から参照されるときに、publicにするしかなくなる
実際、npm package同士の関係などはそんな感じになってる
package同士がネットワーク的に依存している
誰に依存されているかはどうでも良い
何を公開しているかは重要
何に依存しているかも重要
packageもいわばちょい大きめの関数みたいなものとして表現できるはず
依存するものと、公開するものとある
依存関係を可視化しようとする毛玉問題になりがちがだが、それは可視化の仕方が悪いと言えるはず 本当にネットワークになってはいけない
そこの関係も含めて、設計しないといけない
毛玉になるのはいらん線が全部表示されているから
package時に閉じてるものは出てこなくて良い
そのpackageの抽象度毎に調節できるばだいぶマシになる気がするんだけど
その抽象度に沿った依存関係が見たいだけなんだよな
わかり易い例で言えば、ReactでかつCAぽいレイヤー構造をしてる時に、
jotaiのatomの依存関係だけを見る、とか
そうすれば内部の具体的なロジックは捨象しつつ、
Component同士の関係といった表層部分も捨象できる
例えばViewだけ、Entityだけの関係、みたいな
あるいは、このfeature内の、view, entity, repositoryの関係、みたいな
理想的には、CAぽいやつのレイヤーごとになにか印があるとよい
ComponentとかJotaiのatomとか、hooksとかみたいに機能の制限として元からある制約を利用すると良さそう
もしかしたらUnisonとかそういう知見があるかも(知らない) 同様にファイルの上部に書いてるimport文もviewに過ぎないんだよな
importしてないのにReact型とかjestのtest()とか入ってっしゃろみたいなのもある
https://gyazo.com/f863a0957f6bf253e7f898fca70f81a8
GUIで、Aとa,b,cは同じmoduleやぞ、というのを囲ったら1つのまとまりになるみたいな
そういうインタラクションがあれば割と自在に抽象と捨象ができそう
プロジェクト内の全moduleに対し、ライブラリを使う感じで互いに参照する必要がある
これが実践できないのは、恐らく人間の問題ではなくツールがないせいだと思う
誰でもライブラリを使うことはできるし、ライブラリを設計するなら同じ発想になるはずなので
同じモジュール、同じものとみなすならスタンプ結合でもいい
その関数の抽象度によってかわるということになる
何か概念を追加する系の修正が入った時に、
段階を踏むmoduleの境界部分を先に修正して、
あとでそれ以外の部分を修正すれば良い、という感じにしたい
そうするためには、段階的なmoduleの協会ってどこやねん、というのをパッと確認できる必要がある
エディタのモジュールに対するサポートも弱い
privateなものは候補に出てこなくていい
今注力しているpackageだけのファイルツリーを表示したい
外部のpackageが出てるだけノイズ