2017-01-07 28 views
5

Próbuję poznać wzór tortu.wzór ciasta - dlaczego jest tak skomplikowany?

Czytam o tym blogu this.

Przykładowy kod z tego bloga jest:

case class User (name:String,email:String,supervisorId:Int,firstName:String,lastName:String) 

trait UserRepository { 
    def get(id: Int): User 
    def find(username: String): User 
} 
trait UserRepositoryComponent { 

    def userRepository: UserRepository 

    trait UserRepository { 
    def get(id: Int): User 
    def find(username: String): User 
    } 
} 
trait Users { 
    this: UserRepositoryComponent => 

    def getUser(id: Int): User = { 
    userRepository.get(id) 
    } 

    def findUser(username: String): User = { 
    userRepository.find(username) 
    } 
} 
trait UserInfo extends Users { 
    this: UserRepositoryComponent => 

    def userEmail(id: Int): String = { 
    getUser(id).email 
    } 

    def userInfo(username: String): Map[String, String] = { 
    val user = findUser(username) 
    val boss = getUser(user.supervisorId) 
    Map(
     "fullName" -> s"${user.firstName} ${user.lastName}", 
     "email" -> s"${user.email}", 
     "boss" -> s"${boss.firstName} ${boss.lastName}" 
    ) 
    } 
} 
trait UserRepositoryComponentImpl extends UserRepositoryComponent { 

    def userRepository = new UserRepositoryImpl 

    class UserRepositoryImpl extends UserRepository { 

    def get(id: Int) = { 
     ??? 
    } 

    def find(username: String) = { 
     ??? 
    } 
    } 
} 

object UserInfoImpl extends 
    UserInfo with 
    UserRepositoryComponentImpl 

mogę uprościć ten kod usuwając Users:

package simple { 

    case class User(name: String, email: String, supervisorId: Int, firstName: String, lastName: String) 

    trait UserRepository { 
    def get(id: Int): User 

    def find(username: String): User 
    } 

    trait UserRepositoryComponent { 

    def userRepository: UserRepository 

    trait UserRepository { 
     def get(id: Int): User 

     def find(username: String): User 
    } 

    } 

    trait UserInfo { 
    this: UserRepositoryComponent => 

    def userEmail(id: Int): String = { 
     userRepository.get(id).email 
    } 

    def userInfo(username: String): Map[String, String] = { 
     val user = userRepository.find(username) 
     val boss = userRepository.get(user.supervisorId) 
     Map(
     "fullName" -> s"${user.firstName} ${user.lastName}", 
     "email" -> s"${user.email}", 
     "boss" -> s"${boss.firstName} ${boss.lastName}" 
    ) 
    } 
    } 

    trait UserRepositoryComponentImpl extends UserRepositoryComponent { 

    def userRepository = new UserRepositoryImpl 

    class UserRepositoryImpl extends UserRepository { 

     def get(id: Int) = { 
     ??? 
     } 

     def find(username: String) = { 
     ??? 
     } 
    } 

    } 

    object UserInfoImpl extends 
    UserInfo with 
    UserRepositoryComponentImpl 

} 

i kompiluje dobrze.

1) Dlaczego kod na blogu jest tak skomplikowany?

2) Czy to jest idiomatyczny sposób użycia wzoru tortu?

3) Dlaczego w tym przykładzie wymagana jest klasa Users?

4) Czy to jest sposób, w jaki wzorzec ciasto ma wyglądać (z tego pozornie niepotrzebnych Users klasie?

5) lub jest uproszczoną wersją dobrze?

+1

blog zawiera sekcję komentarzy. dlaczego nie zaczniesz od zapytania autora? – pedrorijo91

+0

:) :) :) :) :) :) - jesteś zabawny – jhegedus

+0

Przepraszam, nie zauważyłem, właśnie zobaczyłem komentarz sprzed 3 lat .. ** Nie kopałem dużo w kodzie **, ale Myślę, że to tylko kolejny poziom pośredni.to może pomóc w testach, jeśli chcesz sfać/podkręcić to zachowanie, – pedrorijo91

Odpowiedz

8
  1. Początkowo może to wyglądać skomplikowanie, ale gdy już się go pozna, jest po prostu ... kotłowni i kłopotliwe. Dla każdej usługi należy utworzyć komponent, który będzie owijał tę usługę. Tak więc w podanym przykładzie masz UserRepository, który jest zawijany przez UserRepositoryComponent. A to tylko abstrakcja, więc musisz mieć konkretną implementację zarówno komponentu, jak i usługi (tj. UserRepositoryComponentImpl zawijania UserRepositoryImpl). Do tej pory masz tylko jedną usługę, która może być użyta w twoich modułach, wyobraź sobie wysiłek tworzenia dziesiątek usług;)

  2. Tak, to jest idiomatyczny sposób użycia tego wzoru. Istnieją jednak również inne odmiany tego wzoru, np. thin cake pattern lub parfait (termin ukuty przez Dicka muru)

  3. Prosisz o User jeszcze kod uproszczenie było usunięcie Users, więc opiszę oba z nich. User jest prostą klasą przypadku, która powinna uczynić ten przykład bardziej dostępnym/łatwiejszym do uchwycenia. Users jednak nie były tutaj potrzebne (to tylko kolejny pośredni poziom abstrakcji) i moim zdaniem przynoszą niepotrzebny hałas do tego przykładu.

  4. Powiedziałbym, że Twoja uproszczona wersja pokazuje dokładnie, jak powinien wyglądać wzór ciasta. Masz streszczenie UserRepository zapakowane wewnątrz UserRepositoryComponent, masz konkretną implementację obu tych cech i masz pewną usługę (UserInfo), która wymaga repozytorium użytkowników (które jest "wstrzyknięte" przy użyciu adnotacji typu self).

  5. Już odebrano.

+0

Dziękuję za szczegółowe wyjaśnienie, poprawiłem pytanie 3 i 4, rzeczywiście miałem na myśli "Użytkownicy", więc pisanie 'Użytkownik' wystąpił błąd literowy. – jhegedus

+1

Niestety, mogę dać tylko jeden głos na tę szczegółową odpowiedź. – ipoteka