Tuesday, November 20, 2007

Using internal within the domain layer

There is a very nice trick you can do with the internal key word that I think is worth writing about. If you want to implement an Active Record class, such as customer.Save(), sometimes we might not want the presentation layer to have access to this method directly and pass via an application layer.

so the presentation layer code will call something like this:
customerService.SaveCustomer(customer) instead of customer.Save()


The reason is that within the application layer we might want to handle error handling and logging, work that normally does not belong in the domain. With internal it is very possible. First you have to place your Customer in its own assembly. Company.Domain.dll and your presentation would be in its own assembly as well Company.Presentation.dll

Now the methods and even properties you don't want the UI to access directly are marked as internal

// Customer class
internal Save()
{
// save the information within customer
}


The application layer needs to be within the same assembly as the domain, so its has access to internal members. Now our application layer can do something like this:

public CustomerService
{
public SaveCustomer(Customer cust)
{
try
{
//delegate the work to domain,
//the Save method is visible to the application layer
cust.Save();
}
catch(Exception e)
{
Logger.LogException(e); // perform logging
}
}
}

You can even take the idea further by marking certain properties as internal, so the presentation layer will not see them at all.

This is just one way of limiting the visibility of members and properties of a class, and I believe it is an elegant and nice solution when you want to control member visibility between the presentation layer and Active Record domain classes.

One last note...



I am not a big fan of active record and believe more in repositories, however active record has its place in DDD, it works well when the class maps well to the persistence layer.

So... remember, not everything should be public, some data should be kept "internal" to the domain.

No comments: