2017-01-07 14 views
5

私はケーキのパターンについて学びたいと思っています。ケーキのパターン - それはなぜとても複雑ですか

私はそれについてthisブログを読んでいます。

そのブログからのコード例は次のとおりです。

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 

私は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 

} 

、それがうまくコンパイルされます。

1)ブログのコードが複雑なのはなぜですか?

2)それはケーキパターンを使用する慣用方法ですか?

3)この例では、なぜUsersクラスが必要ですか?

4)は?ケーキのパターンは、その一見不要Usersクラスで(ように見えることになって仕方こと

5)であるか、簡易版だけで結構ですか?

+1

ブログにはコメントセクションがあります。なぜあなたは作者に尋ねることで始まらないのですか? – pedrorijo91

+0

:) :) :) :) :) :)あなたは面白いです – jhegedus

+0

申し訳ありませんが、気づかなかった、ちょうど3年前からのコメントを見ました.. **私はコード**で多くを掘り起こさなかった私はそれが単なる間接的なレベルだと思う。あなたがその行動を模倣したりスタブしたいのであればテストに役立つかもしれません – pedrorijo91

答えて

8
  1. 最初は複雑なように見えるかもしれませんが、一度このパターンに精通すれば、それはちょうどボイラープラタティーで面倒です。あなたのサービスごとに、そのサービスをラッピングする付属コンポーネントを作成する必要があります。したがって、提供された例では、UserRepositoryComponentで囲まれたUserRepositoryがあります。これは抽象化に過ぎないため、コンポーネントとサービスの両方を具体的に実装する必要があります(UserRepositoryComponentImplラッピングUserRepositoryImpl)。これまでにモジュールで使用できるサービスは1つだけですが、数十のサービスを作成しようと想像してください)

  2. はい、これはそのパターンを使用する慣習的な方法です。しかし、そのパターンには他のバリエーションもあります。 thin cake patternまたはparfait(ディック・ウォールによる造語)

  3. あなたはおよそUserを求めている、まだあなたのコードの簡素化がUsersを削除することでしたので、私はそれらの両方を説明します。 Userはシンプルなケースクラスであり、その例をより使いやすくする/理解しやすくする必要があります。 Usersしかし、ここでは必要ありませんでした(これは別の中間レベルの抽象化です)。

  4. 私はあなたの単純化されたバージョンが正確にどのようにケーキのパターンが見えるかを示していると思います。あなたは抽象的なUserRepositoryUserRepositoryComponentの中にラップされています。これらの特性の両方を具体的に実装しており、ユーザのリポジトリを必要とするサービス(UserInfo)を持っています(セルフタイプ注釈を使用して "注入"されます)。

  5. 既に回答済みです。

+0

詳細な説明をいただきありがとうございます。私は質問3と4を修正しました。 'User'に私が作ったタイプミスがありました。 – jhegedus

+1

残念なことに、私はこの詳細な回答に対して1つの投票しかできませんでした。 – ipoteka

関連する問題