2

私のWebアプリケーションでは、許可されたユーザーには少なくとも4つの「ファセット」があります。httpセッション関連データ、永続データ、Facebookデータ、ランタイムビジネスデータです。

少なくとも2つの理由から、トレイトではなくケースクラスの構成を使用することにしました。

  • 特性の混合は名前の衝突を引き起こす可能性があります
  • パターンマッチングやコピーメソッドなどのフリーケースクラスのグッズが欲しい

このテーマに関する経験豊富なスカラリストの意見を知りたいです。特性やケーキのパターンはそのようなタスクに適しているように見えますが、前述のように問題があります...迅速かつ簡単に実装するだけでなく、使用するために深く理解したいことは明らかです将来は。

それで、私の決定には欠陥や誤解がありますか、それとも正しいですか?関連するコードは次のようになります。


case class FacebookUserInfo(name: String, friends: List[Long])
case class HttpUserInfo(sessionId: String, lastInteractionTime: Long, reconnect: Boolean)
case class RuntimeQuizUserInfo(recentScore: Int)
trait UserState {
  def db: User
  def http: HttpUserInfo
}

case class ConnectingUser(db: User, http: HttpUserInfo) extends UserState
case class DisconnectedUser(db: User, http: HttpUserInfo, facebook: Option[FacebookUserInfo]) extends UserState
case class AuthorizedUser(db: User, http: HttpUserInfo, facebook: FacebookUserInfo,
                          quiz: RuntimeQuizUserInfo) extends UserState
4

2 に答える 2

3

答えは簡単だと思います。すべてが同じ「問題ドメイン」にある限り、すべてが実際にオブジェクトに「属している」限り、継承を使用します。

ケーキパターンの目的は、何らかの形で必要とされるが実際にはその一部ではないオブジェクトの部分、たとえば戦略、装飾、構成、コンテキストなどを除外することです。ロギングは典型的な例です。一般的に、JavaでDIフレームワーク(GuiceやSpringなど)を使用することを検討する場合など、「ハードワイヤード」にしたくない状況について話します。良い例については、http://jonasboner.com/2008/10/06/real-world-scala-dependency-injection-di.htmlを参照してください。

何をすべきかを決定するのに役立つことが多い質問は、「オブジェクトの動作をどのようにテストできますか?」です。適切なテスト環境を設定するのが難しい場合は、物事を切り離す必要がある可能性があります。これは、ケーキパターンで便利に実現できるDIを意味します。

于 2010-10-07T07:40:18.873 に答える
1

3番目のオプションは、暗黙のコンバーター、別名「pimp my library 」を使用することです。これは、コードを制御できるため、おそらく必要ありません。

それはすべて、オブジェクトの特定の側面についてどの程度不透明(または透明)にしたいかによって異なります。昔ながらのケースクラスを他の世界に見せかけることはできますが、暗黙的に使用することで、内部的に余分な作業を行うことができます。データを保持するためにcaseクラスを使用することは適切ですが、認証の状態によっては、3つのクラス(、、)をConnectingUser使用して同じオブジェクトを表すのも厄介だと感じています。DisconnectedUserAuthenticatedUser

UserState場合、ケースクラスのように動作するようにエクストラクタを提供できます。

object UserState {
  def unapply(state: UserState) = Some(state.db, state.http)
}

これは、次のように一致状態で使用できます。

val user = ConnectingUser(User(), HttpUserInfo("foo", 0, false))
user match {
  case UserState(db, http) => println(http)
}
于 2010-10-08T16:22:35.377 に答える