2010-10-07 6 views
2

В моем веб-приложении у авторизованного пользователя есть как минимум 4 "грани": связанные с http-данными данные, постоянные данные, данные facebook, рабочие данные во время выполнения.Scala traits/cake pattern vs case classes

Я решил пойти с классом случая составом вместо признаков, по крайней мере по двум причинам:

  • черты смешения может привести к конфликтам имен
  • я хочу свободное лакомство случая класса как сопоставления с образцом и скопировать метод

Хотелось бы узнать мнение опытных экспертов по данной теме. Похоже, что черты и/или шаблон торта должны быть подходящими для таких задач, но, как я уже упоминал выше, есть проблемы ... Очевидно, что не только я хочу быстро и легко реализовать его, но и понять его в глубину для использования в будущем.

У моего решения есть недостатки и недоразумения, или это правильно? Связанные код выглядит следующим образом:


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

ответ

1

Третий вариант заключается в использовании неявных преобразователей aka «pimp my library», что, вероятно, не является необходимым, поскольку у вас есть контроль над кодом.

Все зависит от того, насколько непрозрачным (или прозрачным) вы хотите быть с определенным аспектом вашего объекта. Вы можете притворяться, что это простой класс старого случая для всего остального мира, но внутренне делайте это, делая дополнительную работу, используя implicits. Использование класса case для хранения данных является подходящим, но я также считаю, что неудобно представлять один и тот же объект с использованием трех классов (ConnectingUser, DisconnectedUser, AuthenticatedUser) в зависимости от состояния аутентификации.

Для 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) 
} 
+0

Благодарим вас за ответ. В настоящее время я занимаюсь классами case (так как существует проблема с модификацией объектов, созданных с перемешиванием признаков, я имею в виду способ копирования методов классов case, так как вы должны использовать отражение или неявно определять метод построения для каждой комбинации признаков). Поэтому в моем случае может быть полезно неявное преобразование в соответствие с определенными интерфейсами. –

3

Я думаю, ответ прост: Берите с наследованием, до тех пор, как все на самом деле «принадлежит» к объекту, пока все в том же «проблемной области».

Намерение шаблона пирога состоит в том, чтобы разделить части объекта, которые каким-то образом необходимы, но на самом деле не являются его частью, например. стратегию, оформление, конфигурацию, контекст и т. д. Регистрация будет типичным примером. Обычно мы говорим о ситуациях, которые вы не хотите «жестко прокладывать», например. случаях, которые вы рассмотрели бы на основе Java-среды (например, Guice или Spring) на Java. Для хорошего примера см. http://jonasboner.com/2008/10/06/real-world-scala-dependency-injection-di.html.

Вопрос, который часто помогает решить, что делать: «Как я могу проверить поведение объекта?». Если вам сложно создать подходящую тестовую среду, есть вероятность, что вы должны разделить вещи, а это означает, что DI, который часто можно легко реализовать с помощью шаблона пирога.

+0

В «шаблон Cake» термин обычно используется в контексте сервисов, а не данных, я добавил его к моему вопросу в основном из-за проблемы с названием «столкновение имен», которая является общей для всех видов смешения признаков. –

+0

А также я не совсем понимаю, что вы подразумеваете под «идти с наследованием»? Вопрос в том, что лучше: смешивание признаков (двухуровневая модель) или состав. Мне не нравится наследование (многоуровневая модель), потому что это делает вещи тяжелыми.Легкие интерфейсы всегда предпочтительнее для меня, поскольку они упрощают все контексты (никаких дополнительных данных для просмотра). –