Scala特性/蛋糕模式与案例类

Scala特性/蛋糕模式与案例类,scala,traits,case-class,Scala,Traits,Case Class,在我的web应用程序中,授权用户至少有4个“方面”:http会话相关数据、持久数据、facebook数据、运行时业务数据 我决定使用案例类作文而不是特征,至少有两个原因: 特征混合会导致名称冲突 我想要免费的案例类好东西,比如模式匹配和复制方法 我想知道有经验的专家对这个问题的看法。看起来特征和/或蛋糕模式应该适合这些任务,但正如我上面提到的,存在一些问题。。。很明显,我不仅希望快速、简单地实现它,而且希望深入理解它,以便将来使用 那么,我的决定是否有任何缺陷和误解,或者是正确的? 相关代码

在我的web应用程序中,授权用户至少有4个“方面”:http会话相关数据、持久数据、facebook数据、运行时业务数据

我决定使用案例类作文而不是特征,至少有两个原因:

  • 特征混合会导致名称冲突
  • 我想要免费的案例类好东西,比如模式匹配和复制方法
我想知道有经验的专家对这个问题的看法。看起来特征和/或蛋糕模式应该适合这些任务,但正如我上面提到的,存在一些问题。。。很明显,我不仅希望快速、简单地实现它,而且希望深入理解它,以便将来使用

那么,我的决定是否有任何缺陷和误解,或者是正确的? 相关代码如下所示:


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

我认为答案很简单:使用继承,只要所有东西都真正“属于”你的对象,只要所有东西都在同一个“问题域”

蛋糕模式的目的是将对象中某些部分从某种程度上说是必需的,但实际上并不是它的一部分,例如策略、装饰、配置、上下文等。日志记录就是一个典型的例子。一般来说,我们讨论的是你不想“硬线”的情况,比如在爪哇你会考虑使用DI框架(比如Guice或Spring)。请参阅以获取一个好的示例


通常有助于决定做什么的问题是:“我如何测试对象行为?”。如果您发现很难设置一个合适的测试环境,那么很有可能您应该将事情解耦,这意味着DI,这通常可以通过cake模式方便地实现。

第三种选择是使用隐式转换器,这可能是不必要的,因为您可以控制代码

这完全取决于你想对你的对象的某个方面有多不透明(或透明)。您可以向世界其他地方假装它是一个普通的旧case类,但在内部使用implicits使它做额外的工作。使用case类来保存数据是合适的,但我也觉得使用三个类来表示同一个对象很尴尬(
ConnectingUser
DisconnectedUser
AuthenticatedUser
),这取决于她的身份验证状态

对于
UserState
,您可以提供一个提取器,使其行为类似于case类:

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)
}

“蛋糕模式”一词通常用于服务的上下文,而不是数据,我之所以将其添加到我的问题中,主要是因为“名称冲突”问题,这是所有类型的特征混合中常见的问题。而且我也不完全理解你所说的“继承”是什么意思?问题是什么更好:特质混合(两级模型)还是组合。我不喜欢继承(多层次模型),因为它使事情变得沉重。轻量级的界面对我来说总是最好的,因为它们使所有的上下文都更简单(没有额外的数据需要注意)。谢谢你的回答。我目前正在处理case类(因为修改traits混合创建的对象也有问题,我的意思是case类的copy方法,因为您必须为每个traits组合使用反射或隐式定义构造方法)。因此,在我的例子中,匹配某些接口的隐式转换是有用的。