Pie template benefits:
- Unlike DI solutions based on configuration files, contract negotiation with implementation is performed at compile time, which reduces search and compatibility issues. However, many DI engines have an alternative configuration in code.
- No third-party libraries are used. Annotations that allow you to use the template are native language. Special syntax is not used to retrieve contract execution
- Forgetting to specify the implementation for the component required by another component leads to a runtime error - just check this article http://jonasboner.com/2008/10/06/real-world-scala-dependency-injection-di.html and do not try specify one of the components or indicate a trait instead of a specific class in any pie template examples or even forget to initialize the val value corresponding to the required component
However, in order to experience these advantages, you need to adhere more strictly to the architecture of the template - check the same article and pay attention to the wrapping features that contain the actual contracts and implementations.
Your examples do not seem strictly a cake sample. In your case, you could simply use inheritance to create implementations for your properties and use separate classes for each component of the DAO. In the pie template, the consumption code will be a component similar to the DAO code, and the code that collects the dependencies will be separate from it.
To illustrate the cake template, you must add consumption classes (domain level or user interface layer) to your example. Or is it the case when your DAO components are referring to each other, you could illustrate the cake template on you only DAO.
to make it short
trait OrderDAOComponent { val dao: OrderDAO trait OrderDAO { def create: Order def delete(id: Int): Unit //etc } } trait OrderDAOComponentImpl extends OrderDAOComponent { class OrderDAOJDBCImpl extends OrderDAO { def create: Order = {/*JDBC-related code here*/} def delete(id: Int) {/*JDBC-related code here*/} //etc } } //This one has a dependency trait OrderWebUIComponentImpl { this: OrderDAOComponent => class OrderWebUI { def ajaxDelete(request:HttpRequest) = { val id = request.params("id").toInt try { dao.delete(id) 200 } catch { case _ => 500 } } } } //This matches contracts to implementations object ComponentRegistry extends OrderDAOComponentImpl with OrderWebUIComponentImpl { val dao = new OrderDAOJDBCImpl val ui = new OrderWebUI } //from some front-end code val status = ComponentRegistry.ui.ajaxDelete(request)
More details about your example. I think it might be more like a cake if:
trait DatabaseContext { val dataSource:Datasource } trait OrderDAOComponent {this:DatabaseContext => trait OrderDAOImpl { ...
source share