Question about the pie template

Suppose there are several separate classes DAO OrderDAO , ProductDAO and CustomerDAO that store / retrieve data in a database and share a single instance of DataSource (connection to factory database).

To create an instance of a DataSource and connect it to DAOs , we usually use Spring DI. Now I would like to do this in Scala without a DI framework.

I read about the cake template , and it looks like I should do the following:

 trait DatabaseContext { val dataSource:Datasource } trait OrderDAO {this:DatabaseContext => ... // use dataSource of DatabaseContext } trait ProductDAO {this:DatabaseContext => ... // use dataSource of DatabaseContext } object DAOImpl extends OrderDAO with ProductDAO with DatabaseContext { val dataSource = ... // init the data source } 

Do I understand the cake pattern correctly?

Can I implement these DAOs differently using the cake template?

What ensures that DI frameworks such as Spring are not?

How to create separate OrderDAOImpl and ProductDAOImpl objects that use the same DataSource instance instead of one large DAOImpl ?

+6
source share
2 answers

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 { ... // use dataSource of DatabaseContext } } trait ProductDAOComponent {this:DatabaseContext => trait ProductDAOImpl { ... // use dataSource of DatabaseContext } } object Registry extends OrderDAOComponent with ProductDAOComponent with DatabaseContextImpl { val dataSource = new DatasourceImpl //if Datasource is a custom trait, otherwise wrapping needed val orderDAO = new OrderDAOImpl val productDAO = new ProductDAOImpl } //now you may use them separately Registry.orderDAO.// 
+5
source

May be:

  • Statically checked at compile time.
+2
source

Source: https://habr.com/ru/post/886008/


All Articles