私は OO のバックグラウンド (C#、javascript) から来ており、Scala は FP への最初の進出です。
私のバックグラウンドのために、ドメインの問題にうまく適合し、コードの最小限の可変性などの FP の優れたプラクティスにも準拠するドメイン モデルを実現するのに苦労しています。
最初に、現在の私のドメインの問題について簡単に説明します。
- 主なドメイン オブジェクトは次のとおりです。
Event, Tournament, User, and Team
Teams
で構成されていますUsers
- との両方
Teams
にUsers
参加できますTournaments
。Event
Events
Users
とからなるTournaments
- とのスコア、統計、およびランキングは
Teams
、主要な機能になりUsers
ます。Tournaments
Events
この問題の説明を考えると、ドメインに関する私の最初のアイデアは、双方向の循環関係が標準であるオブジェクトを作成することです。これは、グラフに似たものです。私の考えでは、特定のオブジェクトに関連付けられているすべてのオブジェクトにアクセスできると、データのビューをプログラミングしたり操作したりするための最も簡単な方法が提供されるということです。
case class User(
email: String,
teams: List[TeamUser],
events: List[EventUser],
tournaments: List[TournamentUser]) {
}
case class TournamentUser(
tournament: Tournament,
user: User,
isPresent: Boolean){
}
case class Tournament(
game: Game,
event: Event,
users: List[TournamentUser],
teams: List[TournamentTeam]) {
}
しかし、FP のベスト プラクティスをさらに掘り下げていくうちに、私の思考プロセスが FP の原則と相容れないことがわかりました。循環参照は嫌われており、不変オブジェクトではほとんど不可能のようです。
これを考えると、ドメイン内の「現実世界のオブジェクト」の常識的な組織を維持しながら、適切な FP の要件を満たすようにドメインをリファクタリングする方法に苦労しています。
私が検討したいくつかのオプション
- lazy val と by-name 参照を使用してください-- これに関する私の不満は、ドメインが自明ではなくなると、管理不能になるように思われることです
- 代わりに一方向の関係を使用してください-- この方法では、一部のドメイン オブジェクトを、他のオブジェクトを介してのみアクセスできる 2 番目のクラス オブジェクトとして強制的に格下げする必要があります。どのように選択しますか?それらはすべて私にとって等しく重要に思えます。さらに、これには、2 番目のクラス オブジェクトの単純なリストを取得するためだけに、「粒度に反して」クエリを作成する必要があります。
- インダイレクションを使用し、リレーションシップの識別子のリストを保存します。これにより、循環的な依存関係が削除されますが、リレーションシップの更新をエミュレートするために追加のビジネス ロジックを記述し、関係を取得するために DB に余分なトリップを行う必要があるため、複雑さが増します。
そのため、実装または元のモデルのいずれかを変更して、必要と思われる結合を達成する方法に苦労していますが、Scala の「正しい方法」で。どうすればこの問題にアプローチできますか?
TL;DR -- ドメインがそのコアで双方向アクセスと可変性を要求しているように見える場合、適切な FP プラクティスを使用してドメインをモデル化するにはどうすればよいですか?