2017-06-16 14 views
0

インターネット上で見つけたCakeのパターンに関するすべての記事で、単一レベルの依存関係がわかりました。実装とcakeパターンの混在の重複を回避する方法

しかし、私がそれを使い始めたとき、私は高レベルのクラスでしかサービスを使用できないという問題に直面し、複数の場所でそれを混在させる必要がありました。

例えば、私がサービスを持っていて、このサービスが他のサービスのセットで動作し、このセットの各サービスがデータベースを使用している場合、私はこの低レベルサービスのセットからデータベースに直接アクセスしませんでした。私は高レベルのサービスでのみすべてのデータベースクエリを作った。 しかし、場合によっては困難です。

は質問が例とより明確になることがある:

trait DatabaseServiceComponent{ 
     val databaseService: DatabaseService 
     trait DatabaseService{ 
     def getSomeData(id: Int, tableName: String): List[String] 
     def getFriends(id: Int): List[Int] 

    } 
} 

trait DatabaseServiceComponentImpl extends DatabaseServiceComponent{ 
    val databaseService: DatabaseService = new DatabaseServiceImpl 
    class DatabaseServiceImpl extends DatabaseService{ 
    def getSomeData(id: Int, tableName: String): List[String] = ??? 
    def getFriends(id: Int): List[Int] = ??? 
    } 
} 

trait Scoring { this: DatabaseServiceComponent => 
    def importantValues: Set[String] 
    val tableName: String 
    def getScore(id: Int): Double = databaseService.getSomeData(id, tableName).count(importantValues) 
} 

class Scoring1 extends Scoring{this: DatabaseServiceComponent => 
    val tableName: String = "s1" 
    override def importantValues: Set[String] = Set("a", "b") 
} 

class Scoring2 extends Scoring{this: DatabaseServiceComponent => 
    val tableName: String = "s2" 
    override def importantValues: Set[String] = Set("foo", "bar") 
} 

class Scoring3 extends Scoring{this: DatabaseServiceComponent => 
    val tableName: String = "s3" 
    override def importantValues: Set[String] = Set("1", "2") 
} 

// How to implement this correctly? 
trait Scoring2FriendsAverage {this: DatabaseServiceComponent => 
    val scoring2: Scoring2 
    def getScore(id: Int):Double ={ 
    val scores = databaseService.getFriends(id).map(scoring2.getScore) 
    scores.size/scores.sum 
    } 
} 


object FriendsScoringProcessor{ 

    val scoring2Friends = new Scoring2FriendsAverage with DatabaseServiceComponentImpl{ 
    val scoring2 = new Scoring2 with DatabaseServiceComponentImpl // I don't like that I have to mix the implementation of a service again 
    } 

    def printScores(id: Int): Unit = { 
    val score = scoring2Friends.getScore(id) 
    println(score) 
    } 

} 

私はScoringsのセットを持っており、それらのそれぞれは、データベースを使用しています。私は、データベースを使用するスコアリングの1つを使用するFriendsScoringを持っています。私は、FriendsScoringにのみデータベース実装を混在させたいと思っており、下位レベルのサービスでそれを複製しません。

低レベルサービスへの暗黙的なコンストラクタ引数を使用して実装を提供することをお勧めします。

答えて

2

ケーキパターンのコンポーネントとサービスのレベルが混ざっているように見えます。

サービスレイヤでScoringを使用すると、ケーキパターンレベルでは存在しないはずです。

あなたは、データベースのために行ったように、各レベルでネストされた2つの特色にScoringを分割したい場合があります:

trait ScoringComponent {this: DatabaseServiceComponent => 

    trait ScoringService { 
    def getScore(id: Int): Double = 
     databaseService.getSomeData(id, tableName). 
     count(importantValues) 
    } 
} 

次にあなたが必要な依存関係を混合した後ScoringServiceを使用することができます。