私は次のライブラリを実装しています:
parsing
パッケージに入れます)storage
パッケージに入れました)chart
パッケージ)別のデータ表現(たとえば、table
パッケージ)を追加する場合は、parsing
およびstorage
パッケージを再利用できるため、コードをこのように分割しました。
私は循環依存関係が心配ですが:
Parser
は入力データを専用のデータ構造クラスRecord
に保存する必要があります。これは、DataStorage
がデータを取得する方法を知り、Parserがデータの方法を知る必要があることを意味します挿入はDataStorage
クラスで実行されます。chart
-そして最終的にはtable
-パッケージがDataStorage
クラスからデータを取得する方法についてもう少し知っておく必要があることも心配しています。私の懸念は有効ですか?はいの場合、どうすれば問題を解決できますか? contracts
やinterfaces
などの特定のクラスがそれらを実装するような方法で、Record
/DataStorage
パッケージ内のいくつかのインターフェイスを公開することを考えていました循環依存ではなくなります。
この解決策は良い方法と考えられますか、それとももっと良い代替案がありますか?
Record
やDataStorage
などの特定のクラスがそれらを実装し、循環依存関係がなくなるような方法で、コントラクト/インターフェースパッケージの一部のインターフェースを公開することを考えていました。
これで結構です。各パッケージは(可能な限り抽象的な方法で)定義します1)入力と出力なので、これらのパッケージへの依存関係はdependency inversionによって実装されます。これは、パッケージとコンシューマの間のクリーンな依存関係です。どちらも、相互にかなり分離されているためです。
つまり、package-by-featureは、境界(パッケージ、モジュール、レイヤーなど)。その場合、別の組織になる可能性があります。 package-by-componentのようなもの2。
1:これに沿って、興味があるかもしれません依存関係ルール:どのデータが境界を越えるか
2:ライブラリや小さな事業単位などの小さな境界の場合、package-by-featureは問題なく機能しますが、モジュール式アーキテクチャの場合package-by-componentは重要です。小さな組み込み機能とアドオンまたはプラグインを比較してください。
インターフェイスでサイクルをマスキングする場合は注意が必要だと思います。
パーサーについてストレージに知らせることをお勧めしますが、その逆はお勧めしません。パーサーはドメイン/ビジネスロジックのようです。他のすべてはそれを中心に展開します。 The Onion Architecture も参照してください。
すべてをオーケストレーションする新しいパッケージ(アプリなど)を作成できます。しかし、「パーサー」から「ストレージ」への変換は、おそらくストレージシステムに大きく依存しています。したがって、「ストレージ」パッケージまたは「parserstorage」パッケージのいずれかに属していると思います。
パーサーが非常に多くのデータを生成するので、それをストレージと絡み合わせるのに必要なパフォーマンスの観点からは、パーサーパッケージにストレージのインターフェイスを定義し、それらを「ストレージフレーバー」パッケージに実装できます。
循環依存関係は、アーキテクチャのwhich-class-is-responsible-forが正しくないことを示す指標になる可能性があります。
通常あなたは持っています
このアーキテクチャは、循環依存を回避します。
この例はパッケージ化されます