6

この記事で提案されているように、一部のソフトウェアシステムの一部をコンポーネントに分割して完全にモジュール化するためにCakePatternを使用したいと思います。最も単純なケースでは、モック可能なコンポーネント、たとえば、相互に使用する可能性のあるロギング、構成、データベース、スクリプトなどが必要です。コードは次のようになります

trait AbstractConfig {
  def config: AbstractConfigInterface
  trait AbstractConfigInterface {
    def test: Unit
  }
}

trait SomeConfig extends AbstractConfig {
  this: Core =>  
  def config = SomeConfigImplementation
  object SomeConfigImplementation extends AbstractConfigInterface {
    def test = println("conf.test method called")
  }
}

trait AbstractDatabase {
  def database: AbstractDatabaseInterface
  trait AbstractDatabaseInterface {
    def connect: Unit
  }
}

trait SomeDatabase extends AbstractDatabase {
  this: Core =>
  def database = SomeDatabaseImplementation
  object SomeDatabaseImplementation extends AbstractDatabaseInterface {
    def connect = {
      println("connect method called")
      core.conf.test
    }
  }
}

trait Core {
  this: AbstractDatabase with AbstractConfig =>
  def core = CoreInterface
  object CoreInterface {
    def db = database
    def conf = config
  }
}

object app extends Core with SomeDatabase with SomeConfig

object Run {
  def main(args: Array[String]) = {
    app.core.db.connect
  }
}

ここで、データベースと構成コンポーネント(SomeConfigおよびSomeDatabaseトレイト)はプラグイン可能であり、必要に応じて他の実装に変更できます。それらの実装はcore、データベースと構成の両方を保持するオブジェクトにアクセスできるため、データベースは必要に応じて構成にアクセスでき、その逆も可能です。

したがって、問題は次のとおりです。のような特性SomeDatabaseが大きくなり、単一のファイルに収まらない場合、coreオブジェクトへのアクセスを保持する個別のクラスに分割する方法はありますか?具体的には、connectメソッドSomeDatabaseから別のファイルにコードを移動する必要があるとします。

// SomeDatabase.scala
trait SomeDatabase extends AbstractDatabase {
  this: Core =>
  def database = SomeDatabaseImplementation
  object SomeDatabaseImplementation extends AbstractDatabaseInterface {
    def connect = {
      val obj = new SomeClass()
    }
  }
}

// SomeClass.scala in the same package
class SomeClass {
    core.conf.test // Does not compile - how to make it work??
}

SomeClassはSomeDatabaseがどのように機能するかの実装の詳細なので、私は明らかにそれを特性にしてアプリケーションに混ぜたくありません。coreオブジェクトへのアクセスを提供する方法はありますSomeClassか?


いくつかの関連リンク:

  1. JanMachacekによる依存性注入とケーキパターン
  2. Real World Scala:JonasBonerによる依存性注入
  3. Scalaでの依存性注入:AdamWarskyによるケーキパターンの拡張
  4. Martin Odersky&MatthiasZengerによるスケーラブルなコンポーネントの抽象化
4

1 に答える 1

2

最も簡単な方法はCore、コンストラクターパラメーターとしてに渡すことSomeClassです。

// SomeDatabase.scala
trait SomeDatabase extends AbstractDatabase {
  this: Core =>
  def database = SomeDatabaseImplementation
  object SomeDatabaseImplementation extends AbstractDatabaseInterface {
    def connect = {
      val obj = new SomeClass(SomeDatabase.this) // pass it here
    }
  }
}

// SomeClass.scala in the same package
class SomeClass(coreComp: Core) { // use it here
    coreComp.core.conf.test
}

興味深いことに、私は本当に合格したかったのCoreInterfaceですAbstractConfigInterfaceが、それらが内部型であるという事実は本当にそれを困難にしました。

于 2012-04-20T20:11:46.177 に答える