Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Question about Cake Pattern

Let there a few separate DAO classes OrderDAO, ProductDAO, and CustomerDAO that store/retrieve data in the database and share a single instance DataSource (the database connection factory).

In order to create a DataSource instance and plug it in DAOs we usually use Spring DI. Now I would like to do that in Scala without any DI framework.

I've read about the cake pattern, 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 pattern ?

What does it provide that DI frameworks like Spring do not ?

How can I create separate OrderDAOImpl and ProductDAOImpl objects sharing the same DataSource instance instead of one big DAOImpl?

like image 969
Michael Avatar asked Apr 15 '11 17:04

Michael


People also ask

How many questions are there in this cake quiz?

This quiz is 33 questions and answers long, so it’s perfect for those who love to test their knowledge (or learn something new). There’s also a cake picture round at the end, so you can see some of the most iconic cakes from around the world. Ready to get started with this cake quiz? Let’s go!

What kind of cakes are there?

From traditional Christmas cakes to French and Italian specialities, you will find a bit of everything. Please note that although there are a few baking questions, this is mainly a general knowledge quiz about cakes so you will need to know them, their history and where they come from rather than knowing how they are made.

Which Bake Off contestant ate the most cupcakes in 6 minutes?

Patrick Bertoletti holds the world record for eating the most cupcakes in six minutes. How many did he have? Are Jaffa Cakes biscuits or cakes? On which date does the USA celebrate National Cake Day? Which Great British Bake Off contestant threw their Baked Alaska in the bin after it had been left out of the freezer?

What is the origin of the word 'cake'?

Cake comes from the Old Norse word kaka. True or false? When making cakes, what did people use before whisks were invented? What kind of cake is this?


2 Answers

The advantages of the cake pattern are:

  • Unlike configuration-file-based DI solutions, matching contracts to implementations is done at compile time, which reduces class-finding and compatibility issues. However, many DI engines have an alternative in-code configuration feature
  • No third-party libraries are used. Self-type annotations which let you use the pattern are a native language feature. No special syntax is used to retrieve the implementation of the contract
  • Forgetting to specify an implementation for a component needed by another component results in a runtime error - just check this article http://jonasboner.com/2008/10/06/real-world-scala-dependency-injection-di.html and try not specifying one of the components or specifying a trait instead of a concrete class in any of the cake pattern examples or even forgetting to initialize a val corresponding to a component needed

However, to experience these advantages, you need to more strictly adhere to the architecture of the pattern - check the same article and note the wrapping traits that contain the actual contracts and implementations.

Your examples do not seem to be strictly the cake pattern. In your case you could've just used inheritance to create implementations for your traits and use separate classes for each DAO component. In the cake pattern the consuming code would be a component just like the DAO code, and the code assembling the dependencies together would stand alone from it.

To illustrate the cake pattern, you would have to add consuming classes (domain layer or UI layer) to your example. Or it the case your DAO components accessed each other's features you could illustrate the cake pattern on you DAO alone.

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 on your example. I think it could be more like 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.//
like image 53
kyrel Avatar answered Oct 06 '22 06:10

kyrel


Maybe:

  • Statically checked at compile time.
like image 24
Daniel C. Sobral Avatar answered Oct 06 '22 08:10

Daniel C. Sobral