Crap4J was mentioned in the ALT.NET forum, seems like another interesting code analysis idea but this time it does code complexity and add code coverage.
There is also an entertaining video that covers the thinking behind it, and it sounds like Crap4N is on the way too...
Thursday, November 29, 2007
Crap4J was mentioned in the ALT.NET forum, seems like another interesting code analysis idea but this time it does code complexity and add code coverage.
Wednesday, November 28, 2007
Whilst looking at PostSharp I found quite a few useful links and also managed to look at a few alternatives.
Aspect# seemed interesting but it only does virtual members (or interfaces I presume) and its certainly not transparent to the user of the classes as you have to go through an AspectEngine. Anyway no matter how useful it could have been it looks like Aspect# is a dead end and is on the way out.
Other than Aspect# there are a few other choices, Spring.NET has an AOP solution and Eric Bodden has a list of .NET AOP solutions and I'll definitely take a look at some of them, AspectDNG in particular sounds good.
I'll be interested to see if I can find any solution thats as simple as PostSharp Laos or that has such a nice way of supporting compile-time weaving.
Links - PostSharp
- Using AOP for validation
- PostSharp AOP reference
- AOP with PostSharp Part A
- AOP with PostSharp Part B
- Bitter Coder
- DotNetKicks - Not much yet...
Links - AOP
Tuesday, November 27, 2007
A new requirement has come in to our system, essentially we need to be able to tell external systems when (some) changes happen to our domain objects. How we notify the systems is one issue but how we actually track domain changes is another one.
Some of the changes are quite high level, such as a Customer state change, and some are just little changes to the data of an object, such as a change to a Customers first name.
We could handle the high level state changes by calling through Service classes, for example CustomerStateChangeService.Activate(customer). However we also need to think about how to track all the data changes, we've considered a few ways that we could do this and two of the most obvious are:
- Services - Instead of directly setting a Customers first name call through a Service which would then take care of ensuring that we give other systems a chance to track the change. We could look at something like the anticorruption layer example.
- Domain Events - The domain classes could raise events, to some extent this is nicely decoupled but it bothers us that our domain objects would be raising events simply because an external system needs to know about the change. It also means that pretty much every property setter in the domain could potentially be raising an event once its set the value, not very elegant.
- NHibernate - Maybe include an interceptor that can help us work out what has changed when NHibernate comes to persist. This sounds easy but in practice would be a mess and certainly isn't very intuitive.
Anyway these and other solutions didn't appeal so I started looking at PostSharp. Now I'm no fan of overly technical solutions to domain problems. However I'd heard good things about AOP and thought it might help us solve the problem, especially since logging is quite often given as an example of where AOP can help. I was thus hoping that it could give us a good, simple, solution to our problem.
However when I came to use PostSharp I couldn't believe how good it was. In particular it allows you to use attributes to specify code that you want PostSharp to inject in post-build...
To show how simple it is I've tried to come up with what I consider to be a useful example which you can get from google code. In order to run it you first need to install PostSharp, once you've done this you can open and run the project.
First off note that SimpleDomainClass is marked with AllPropertySetsNotificationAttribute. If you open AllPropertySetsNotificationAttribute you can see that it is using reflection to attach an extra attribute, PropertySetNotificationAttribute, to each property setters.
This may seem silly until you run the application and see that the code in PropertySetNotificationAttribute.OnSuccess is being automagically run.
This is happening because the post-build PostSharp process is ensuring that where it sees a method boundary aspect, such as PropertySetNotificationAttribute, it inserts the necessary IL to ensure the code in the attribute is run.
You can see this if you open Reflector and view the disassembly output for SimpleDomainClass, look at the property setters and note the extra code including the call to OnSuccess in the attribute.
In case you were wondering this is a simplified version of the binding sample that actually comes with PostSharp.
In our case you could easily imagine PropertySetNotificationAttribute calling out to a IDomainChangeNotificationService, the actual implementation could be retrieved from a Service Locator or injected in using IOC.
You will note that our domain assembly references the assembly that I've put the attributes into and also PostSharp.Laos and PostSharp.Public. This bothers me slightly but from what I can see they are quite lightweight assemblies so it doesn't seem to be a killer.
I'm still at the earlier stages of understanding PostSharp but I'm very impressed.
Like TypeMock and NHibernate it is very powerful and also seems to come with very good documentation.
I'm also stunned by how easy it was to do what I wanted to in this case, but then I guess I shouldnt be as the docs indicate that Laos has been designed to be simple rather than being fully featured.
Tuesday, November 20, 2007
I was just looking at a DDD example that had an interface on nearly every class in the system, including the domain classes. One reason for this is mocking (which I don't favor for the domain anyway) but the other seemed to be to improve the design. This second reason made me think I should disuss why I don't think the "everything needs an interface" approach is a good one for the domain.
First off I should say that the topic has already been discussed.:
I disagree slightly with the two viewpoints, to me you only need abstract classes or interfaces in a minority of cases. In the domain I believe you should only add an abstract class or an interface where you believe that the addition is improving the design, most commonly when it is a useful abstraction.
I do agree with the second view as even when you do have a useful abstraction an interface isn't always enough, you sometimes want to enforce the constraints (bake them in) and an abstract class is better for this.
Having said that I wouldn't take my Customer class and just create an ICustomer interface (or an abstract base class) on it, instead I'd look at the usage of the class and the coupling to it which might lead me to extract meaningful interfaces. In fact in many cases I'll just start out by referring to the concrete Customer domain class, only introducing abstractions where I know they are needed.
In summary only put in interfaces or abstract classes in the domain where they are helping, don't go for what Fowler refers to as "Interface Implementation Pair" approach.
Actually this post sums that up my view nicely.
Was just reading a blog entry from Ray Houston on his view classes. The scary thing is we have exactly the same approach, right down to the naming of the classes!
In our case if we had a Customer aggregate and we were displaying lists of Customers in a grid then loading each instance of the aggregate would be deeply inefficient. We'd be loading lots of data/rules that we didn't need and we'd also be missing information that we needed to display in the grid because that information would come from other aggregates. We might thus end up navigating associations from one aggregate to another just to get simple primitive data types to display in the grid, which is wildly inefficient.
What we really needed for these situations were fast loading read-only classes that have information from one or more aggregates but that only load the information/behavior needed for the display in the grid. Enter our Info objects.
We have Info objects (ClientInfo) and InfoLoaders (ClientInfoLoader). The loaders only have retrieval methods and are not repositories. The Info classes are then mapped to database views.
We actually have the Info objects in another assembly called Presentation, but we do have a reference from the Presentation to the domain assembly so that the Presentation classes can use things like Services/Rules/Specifications/Enums and so on. We could remove this dependency if we needed to, but it would be a little bit of effort and so far I don't see it as a major issue.
So far we only have a few Info objects, certainly not one per aggregate. We also don't create one Info object for each view (as in an MVP view) so its possible that when you load an Info object you get data that you don't need. If this became an issue we could deal with it.
Anyway I shouldn't have bothered explaining it as Ray has already done a good job. I also believe there is a discussion of this sort of thing on the DDD newsgroup (don't have link), but it is heartening to know we are not the only people using this approach.
Monday, November 19, 2007
Myself and two colleagues had a very interesting discussion about the structure of our domain projects. Originally we had this sort of folder structure within our domain projects:
This wasn't awful but it also wasn't perfect, after a bit of work we decided to restructure like this:
Its difficult not to prefer this folder structure as it keeps things that are related together in the folder structure and emphasizes key abstractions/classes (such as Customer here).
Sunday, November 18, 2007
Christian Bauer (Hibernate bod) has written a post about the repository pattern. I think the post is a little bit misinformed and concentrates too much on one possible way to implement the repository pattern, however it does show that people are still having trouble working out how to implement repositories so I thought I would explain how we do it.
I actually think the pattern is relatively simple, especially when used with NHibernate, so here goes...
1. Accessing From The Domain
I don't acces the repositories from the domain, with NHibernate I rarely see the need. I don't actually want to couple them because:
- Complexity - Having the domain classes call the repositories makes it harder to understand them.
- Testing - Most DDD practitioners seem to focus on state testing and thats certainly my preference, but if your calling repositories from the domain those tests become (as I see it) layer crossing tests and testing becomes more difficult.
I don't want to have to mock out repositories when testing the domain, for me thats reason enough to avoid the coupling. There isn't too much about this one the Web other than one forum post and bits and pieces on peoples blogs, but making your domain testable in isolation is (in my view) well worth the effort.
I tend to focus on modeling the most important associations in the domain.
Within an aggregate this is simple, you can always navigate from the root to the parts.
Where I want to associate one aggregate with another I'll put the most important association in the domain model and (optionally) handle the inverse using a repository e.g.:
Customer customer = customerRepository.GetForOrder(customer);
Ofcourse sometimes you might bidirectional association here, if it wasn't costing you too much complexity/coupling wise.
Note that in many cases people focus on modeling the association from the one to the many, e.g. Order to Customer. This sometimes works, sometimes it doesn't...do whatever makes sense. I try to do it without simply putting in the associations that make persistence simplest.
3. Implementation With NHibernate
NHibernate makes cascading and lazy loading simple. In the mapping files I don't lazy load within an aggregate though I do lazy load between aggregates, cascading only goes as far as aggregate boundaries.
The implementation becomes ridiculosly simple, for example for our key repository its basically this:
public class CustomerRepository : Repository
//..any custom queries
The base class is doing all the heavy lifting, for simple cases all I need to say is that the key to the Customer table is an int (using a generic generic parameter, which is missing from the code because blogger is cutting it out :)).
The base class is also very simple, it has methods for SaveOrUpdate/GetById/GetAll and we have extra an IDeletionRepository that we can add on which just has a Delete method. We also have a RetrievalRepository base class for completely readonly cases.
I am coupling the implementation of my repositories to NHibernate but that has so far not proved to be an issue. What we do strive to avoid is putting anything NHibernate specific on the interface of the repository, not just to follow the pattern but because its sensible as we may not always use NHibernate for all of the queries. So I avoid making the repository a leaky abstraction by, for example, passing in some ICriteria to one of the queries.
Testing the basic Save/Update/Concurrency also becomes mickey mouse as we have a base class called AggregateRootPersistenceTestBase that does the heavy lifting.
As an example this base class has a TestSaving method that delegates to a SaveTestHelper, this class does the following:
1) Create Repository - Create an instance of the repository under test.
2) Create Aggregate - Create an instance of the aggregate we are testing the persistence of.
3) Save - Save the aggregate to the database (save then flush).
4) Reload - Evict the saved aggregate from the session (or Clear the session) and reload it from the database. We could instead use a seperate ISession, either way we are ensuring that the reloaded object is fresh from the DB (not from the first level cache).
5) Compare - Compare the two objects, this works as I've written an ObjectHierarchyComparer that can be given two objects and will use reflection over their properties to ensure they match. In navigates right down the hierarchy until it gets to build in primitives to compare so can handle very complex object structures.
This is very simple, all you need to do to use SaveTestHelper is pass in two delegates, one that creates the repository and one that creates the aggregate. You can optionally pass in a string of property names that the ObjectHierarchyComparer should ignore (such as properties that get default values from the DB, because the reloaded object will have different values for them).
This is all very reusable. We then write tests for the aggregate roots in a few different scenarios:
- Unpopulated - Create an instance and save it.
- Populated - Move it into a non-default state (if it has lifecycle), populate the entire aggregate.
- FullyPopulated - Same but with associations to other aggregates populated.
3.2 Custom Queries
Any custom queries are written in the repositories, preferably in HQL/ICriteria so we can refactor the DB or code (made harder if you encode SQL). You could actually put the HQL into a named query in the mapping file if you wanted to.
3.3 Eager Fetching
We haven't really dealt with this issue fully yet but Udi Dahan has posted about it. I don't think I'd use his implementation but I do like the idea of fetching strategies and I'd probably choose the appropriate one in a coordination/application layer.
We probably underuse specifications, they can be useful if your getting lots of custom queries on the repositories that are all just for specific cases:
You could encapsulate these name queries in one or more specifications and pass them in:
The problem is converting your (domain) CustomerNameSpecification into a query. I don't want the class itself to be talking in terms of SQL/HQL/ICriteria so choices that we've though of are:
- Conditional - A single CustomerNameSpecification and the CustomerRepository picks it apart, for example the CustomerNameSpecification would have a FirstName property and if its not null the repository adds an appropriate ICriteria to the query.
- Switch - Subclasses of CustomerNameSpecification (such as CustomerFirstNameSpecification) and a switch in the repository that calls an appropriate method to create the query for each type of specification.
- Visitor : This one of the GOF patterns. Subclasses of CustomerNameSpecification (such as CustomerFirstNameSpecification) and each "accepts" a QueryVisitor, the power of double dispatch is then used to ensure the appropriate method is called on this class.
My hope is that in the future extension methods and LINQ should make this easier.
I've discussed eager queries but sometimes domain clases just aren't appropriate. For example we have cases where we display lists of objects in the GUI, for example we might have a grid displaying Orders that actually displays the Customer name.
Loading each Order domain object and the associated Customer is going to be deeply inefficient, for those cases we map seperate presentation (or as we call them info) objects.
We'd thus map an OrderInfo class to a database view that would bring in the information that is needed from whatever tables are involved. These classes are loaded using Loaders (not repositories) to emphasize that they are not domain classes. We also nly create these classes if we are sure that they are needed, so you only find them where we have proved that using the domain classes was going to cause performance issues.
It is worth emphasizing that this is not a presentation model, these are read-only classes that are not in any way associated to the aggregates in the domain.
Tuesday, November 13, 2007
Ayende has just blogged about the new features in NHibernate 2.0, the one that we are most interested in is the ability to map multiple tables to one class. This is very useful and we've been using it for a while.
Thursday, November 08, 2007
I listen to a few podcasts but my new favorites are:
- Software engineering radio - The "enterprise" episodes are great, but I'm yet to be sold on the ones that are on other topics (such as real time systems).
- Ask Udi - Good content but the topics are so interesting that the podcasts seem too short, I'm hoping for an extended version in the future.
I have to say both are very useful.
Posted by Colin Jack at 11/08/2007
Sunday, November 04, 2007
I've posted about this before but on my project we have a coordination layer that sits above the domain but I thought I'd add another post about it.
Since a coordination layer is quite closely linked to a domain assembly we have more than one of them, so if we had two domain models our projects would be:
- Create the Customer by calling into a CustomerFactory within the Customer domain assembly.
- Create a CustomerCreditCheckRequest and associate it with the new Customer before saving it. This logic obviously calls off to a repository and to the Finance domain and so cannot go into Company.Customers.Domain.
- Return the Customer.
When Is A Domain Service Enough?
There is another "issue", what do if we already have a coordination layer service and no domain service and want to decide where to put some code. For example lets say Order/Customer aggregates are in a single domain assembly but a rule is that for an Order to become active we must ensure the Customer has a valid Address. This is a cross aggregate rule but we could enforce it in a domain service, there is no specific need for the coordination layer to be involved. So we could have an OrderActivationService in the domain, however we already have an OrderService in the coordination layer...do we put the code in there instead?
Although I originally thought of just putting the cross aggregate logic in the domain I've been swayed by a colleague and of course even we could put a call to the OrderActivationService (domain) inside a suitably named method in the OrderService, keeping the logic in the domain but giving a simple single class interface to the GUI.
Compared To Service Layer
Evan Hoff did point out that this layer could be mistaken for a Service Layer, the links is here. As we discuss they are quite different as the coordination layer is not responsible for things like email/transactions/session management and is very closely linked to the domain itself. Not to say we might not also need a service layer at some stage, or that the coordination layer might not become one in time...