Pay your bills with DCI

Another “transfer money” implementation i’m afraid, but I think it is a good one. In this post I address two difficulties I encountered when coding up a DCI style use case in Scala. The first is nested contexts. It is not uncommon that during execution of a certain context, one or more other contexts are instantiated and executed. We’ll have a glance at what this looks like in my approach. Second is the problem of injecting roles in objects that already exist. This issue arises when doing DCI in a statically typed language like Scala. I reckon it isn’t that much of a problem in Ruby, for instance. I remember James Coplien mentioning Scala in one of his talks, saying that Scala looks as it was made for DCI. I’m not sure, I found myself struggling quite a lot with injecting roles in existent objects. Scala does not allow to mix in traits in existing objects at runtime, only statically or at object instantiation. Fortunately Scala has a trick up its sleeve that approximates dynamic mixins, we’ll get to that in a moment.

As I mentioned in my previous post on DCI, the key technique I use to glue the different parts of the code together is the Cake Pattern, a technique for doing dependency injection in Scala. Although it is suitable for that, I think it is capable of more. Having a Java background, I regard dependency injection as a way to piece together object graphs, where the different components are objects instances. The result of this is usually a static object graph where the different objects are some sort of stateless containers for logically related methods. I am maybe stereotyping here, but this is what a lot of Spring applications look like. The Cake Pattern is actually a lot more powerful than traditional dependency injection. Instead of piecing together object graphs, you can actually weld a pile of traits together into very precisely synthesized objects. Or in other words, it is not an object graph that is built from object instances, it is a single object that is built from traits. When learning about that, it struck me that the Cake Pattern could potentially be a very suitable technique for doing DCI in scala. DCI is all about putting together exactly the needed functionality into a small object graph, launching an interaction, and then letting the created objects be garbage collected again. I think DCI is an excellent theory for guiding developers in deciding which components to create. The Cake Pattern can then be used to piece those components together into a working software system.

A scenario

Before diving into the code, let’s briefly have a look at the scenario we’re going to implement. Image being the user of a banking application. The system has a button which allows you to pay all your unpaid bills with only one click. However, the entire transaction fails if you don’t have enough money in your bank account to pay them all. We’ll translate this to DCI artifacts. The user of the system plays a role in our case. He is a person that has bills to pay, which makes him a debtor. Or in other words, a user is represented by the Person class, and Debtor is the role that is mixed in into the Person object, in the PayBillsContext. Let’s clarify with a not-so-UML-compliant graphical representation.

Notice the blue balloons, these are the nested contexts I mentioned earlier. It is the methodful role implementation TransactionalDebtor of the methodless role Debtor that instantiates and executes TransferMoneyContext objects. Conceptually this is easy to grasp, but don’t forget that the TransferMoneyContext object is a configured “business” component that is capable of working with a transactional resource like a database. So how can the methodful role instantiate such an object? Doesn’t this remind of the anemic domain model debate? Or the question whether it is a good idea to inject business objects into domain entities? Now we’re cooking. Enter the almighty Cake Pattern.

Salt, pepper, Scala… check!

The Cake Pattern is something very particular of Scala. Based on Martin Odersky and Matthias Zenger’s paper called Scalable Component Abstractions, it was later baptised under its common name by Jon Pretty in a discussion thread. Quoting Jon:

(…) beyond my appreciation of cake, [a] cake is made of a number of layers (separated by jam), and can be sliced. The layers represent the different levels of inner class nesting. It is conceivable that you would reach the bottom layer by working your way down from the top.

It is a very weird pattern, I’ll happily admit that. The best way to get your head around it is to code up something yourself. It honestly took me quite a while before my penny really dropped. Anyhow, the beauty of this pattern is that because of its nested traits, the line between entities and business components becomes very blurred. An entity instantiated in a Cake Pattern-y business component al of a sudden has access to the dependencies of that business component, defined by self-type annotations. It becomes even weirder when, in a certain business component, you implicitly convert an existing entity into a role, where the implicit conversion is defined in a trait on which that business component depends, where that trait has dependencies of its own, also defined by self-type annotations. The modest domain entity all of a sudden gains business component superpowers! Yikes! Everybody still with me? Let me illustrate with some code, starting with the Debtor role and the PayBillsContext.

trait Debtor {
  def payBills
}

trait Context {
  def execute
}

trait PayBillsContextFactory {
  this: DebtorProvider =>

  class PayBillsContext(val person: Person) extends Context {
    def execute = person.payBills  // implicit conversion from Person to Debtor
  }

}

The Debtor trait, a methodless role, is pretty straightforward, it has only one method. (Rereading this sentence it struck me how contradictory that sounds, a “methodless role with one method”. With methodless roles DCI refers to methods without implementations, just to clarify) The PayBillsContext class is also very simple, it has a Person variable and an execute method. But look, in that execute method, we call the payBills method on a Person instance! Somehow that Person must have secretly been turned into a Debtor, otherwise this wouldn’t compile. How can this be?

I know kung fu

Notice that the PayBillsContext class is an inner class defined in an outer trait PayBillsContextFactory. The outer trait is pretty empty, apart from its self-type annotation DebtorProvider.

trait DebtorProvider {
  implicit def asDebtor(person: Person): Debtor
}

An abstract implicit conversion method. How does this work? When the Scala compiler sees some method being called on something that doesn’t have that method, it looks for implicit conversions in scope that could solve this conflict. In this case, the compiler finds that abstract implicit conversion method in the self-type of the PayBillsContextFactory trait, namely the DebtorProvider trait. This is a compatible conversion, so the compiler is happy and doesn’t complain. This is wicked! In the context of paying bills, the Person object is provided with all the intelligence he needs in his role as Debtor. Doesn’t that remind you of something?

Indeed Mr. Anderson, you know kung fu. Let’s have a look at what kind of kung-fu you know.

trait TransactionalDebtorProvider extends DebtorProvider {
  this: Transactional with PayBillsQueries with TransferMoneyContextFactory =>

  implicit def asDebtor(person: Person): Debtor = new TransactionalDebtor(person)

  class TransactionalDebtor(self: Person) extends Debtor {

    def payBills = inTransaction {
      findUnpaidBills(self.id) foreach {case (bill, creditor) =>
        new TransferMoneyContext(self.accountId, creditor.accountId, bill.amount).execute
        markAsPaid(bill.id)
      }
    }

  }

}

In the TransactionalDebtorProvider trait, the abstract implicit conversion method is implemented. It returns an instance of the TransactionalDebtor class, which wraps a Person instance and implements the Debtor trait. You all know what this is called right? It’s an adapter. Actually I would have liked to implement the TransactionalDebtor as a trait, with Person as a self-type annotation, but I haven’t found a way to glue such a trait onto an existing object. I don’t think it is possible at all in Scala (if it is, please tell me how). You can only mix in such a trait at object instantiation, that’s as close to dynamic traits as you get, i’m afraid. Still, the implementation is quite clean. The fact that the DCI methodful role is implemented as a class instead of a trait is only a minor aesthetical flaw.

Let’s zoom in on what is going on in the payBills implementation. In a transaction, a query is launched to retrieve the Person’s unpaid Bills, and each bill is paid by executing a TransferMoneyContext. Lastly, the Bill is marked as paid. The implicit conversion from Person to Debtor provides that Person with this functionality. The TransactionalDebtor is able to launch transactions, execute queries and create TransferMoneyContext instances because its outer trait, the TransactionalDebtorProvider, has the necessary dependencies, defined as self-types: Transactional, PayBillsQueries and TransferMoneyContextFactory. Remember me saying that the Cake Pattern somehow blurs the line between domain entities and business components? No need for implementing hooks in an ORM framework so that it interacts with a dependency injection container in order to inject business components into entities. (For more information about the TransferMoneyContext, see my previous post)

In summary, every outer trait sits on top of its self-types, which in turn sit on top of their self-types. The only thing we still need to do is do the actual welding together of all the traits.

trait LayerCake
  extends PayBillsContextFactory
     with TransactionalDebtorProvider
     with PayBillsQueriesSqueryl
     with TransferMoneyContextFactory
     with TransactionalMoneySourceProvider
     with TransactionalMoneySinkProvider
     with UpdatableAccountAspect
     with CalculatedBalanceAspect
     with MoneyTransferQueriesSqueryl
     with TransactionalWithSqueryl
     with Tables
     with MyDataSource

What does this look like to you? It’s a layer cake! A stack of traits, summarized in a trait, which can then be mixed into other traits or objects.

Conclusion

Using the Cake Pattern, working with nested DCI Contexts is absolutely trivial. As is injection of all kinds of logic that is untypical of domain entities. Injecting roles into existing objects can be done rather elegantly with implicit conversions. The beauty of it all is that I don’t need any frameworks to do all this. It’s just Scala.

That’s it! I hope that I’ve somehow been able to convey the train of thought that led to this implementation. Don’t be shy and comment away!

The code is available on Google Code.

It compiles with the final Scala 2.8 release and has a few dependencies:

Peace.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s