Вот проблема, с которой я сталкиваюсь:
У меня есть абстрактная черта Toggles
, у которой есть абстрактный метод isToggleEnabled(name: String)
.
То, что я хочу иметь, - это иметь возможность иметь черту производственной среды ProdToggles
с конкретной реализацией isToggleEnabled
и использовать ее в коде продукта, но иметь возможность предоставлять переопределяющую альтернативную черту TestToggles
с новойреализация isToggleEnabled
при тестировании.
Причина заключается в том, что реализация производственной среды использует свойства System для хранения имен переключателей и их состояний, однако при тестировании я хотел бы предоставить другую реализацию для хранения и чтения переключателей, чтобы несколько тестов могли выполняться параллельно безвлияют друг на друга (как через свойства системы они будут). То, что я придумал, используя шаблон торта:
trait Toggleable {
def isToggleEnabled(name: String): Boolean
}
trait ProdToggles extends Toggles with Toggleable {
override def isToggleEnabled(name: String): Boolean = System.getProperty("name").toBoolean
}
trait TestToggles extends Toggles with Toggleable {
val cache = scala.collection.mutable.HashMap.empty[String, Boolean]
override def isToggleEnabled(name: String): Boolean = cache.getOrElse(name, false)
}
trait Toggles {
this: Toggleable =>
def isEnabled(name: String): Boolean = {
isToggleEnabled(name)
}
}
//—————IN PROD code—————
class Prod() {
this: Toggles =>
def doSomething(): Unit ={
isEnabled("toggle.name")
}
}
object Prod {
def apply(): Prod = new Prod with ProdToggles
def apply(testing: Boolean) = new Prod with TestToggles
}
//——————IN TEST code———————————
class Tests {
val prod = Prod(true)
prod.doSomething()
}
Однако проблема с этим:
- Нарушает инкапсуляцию и экземпляр
Prod
может быть неправильно использован как экземпляр Toggle
как вымог бы сделать (new Prod with ProdToggles).{isEnabled, isToggleEnabled, doSomething}
- Каждому
Prod
классу mixin Toggles
потребуется object
с фабрикой apply
для возврата пользовательского экземпляра для тестирования и для prod - Cake-pattern isанти-паттерн
Есть ли у вас какие-либо другие подходы, чтобы обойти эту проблему? Спасибо!