I’m not sure who came up with the term ‘DDD-lite’ or if it even makes sense to ask the question, but I *think* I first saw it being used by Colin Jack. In any event, I’m going to describe what I mean by it, and how I’m using it in a way that I find comfortable along with a certain way of doing data access.
As I’m using it in this post (I don’t think there is an official definition), ‘DDD-lite’ refers to the use of certain patterns within your code. Full blown DDD requires an extensive collaboration between business users and developers and everyone in between (though there are many debates about this), and so DDD-lite is more of a programming technique (or set of them). As I use it (and I’m talking strictly about web forms here), it involves:
- MVP/C at the presentation layer (technically, only the ‘V’ is truly the presentation layer, but go with me here)
- V – the view. I always create views at the user control level, and the aspx page just combines them.
- M – the model. This gets the…stuff (I want to say ‘data’ but it doesn’t directly get data in a database sense) that the view needs to display, as well as act on the…stuff when it changes in the view.
- P – the presenter. This co-ordinates the interaction between the M and the V. I like my views to be a bit more robust than others (so the presenter may pass some stuff to the view and the view itself will do some formatting, etc.). I also tend to have the presenter constructed with the view passed in, and then wire up the presenter to the view’s events, then have the view fire off events, blah blah blah.
- C – the controller. In Asp.NET world, this could mean Monorail and other things, but I’m only considering Asp.NET MVC here. Since routing scares me (the combination of strings and order of precedence is something I will hork up massively the first twenty times I do it) and it isn’t officially released yet, I’m staying off it for now
- Facade/Services
- I’m actually inconsistent here. I think I prefer that the M call into a facade, which then calls into a service, but I sometimes shortcut this. What’s the difference? Not sure in terms of importance, but something like this: suppose the standard eCommerce site. I might have a facade layer for the shopping experience (adding to cart, applying discounts if I’m a logged in user with certain blah blah blah) and a different one for the ordering experience, for instance. And the facade is a cover/combiner of various services. Or, I might just call into the services directly. I go back and forth between the two, and am not sure if it is because of whimsy or if I can’t tell if one is really better than the other or laziness or stupidity or what.
- Repositories
- Here’s where the data stuff with the database happens. But there’s a ‘complication’ (it isn’t really complicated, but just how I do it).
- Domain Objects/DTO/Data Objects/Mapping
- Domain Objects: the objects that actually do all the stuff and have all (or most, or at least some) of the behavior. These objects are basically POCO, and these are heavily tested (when I don’t cheat) since these are the objects that do the stuff that matters.
- DTO: the objects that are used to populate the presentation layer, and pass data back from the presentation layer.
- Data Objects: the data access stuff, more below.
- Mapping: obviously, two types:
- DTO-Domain
- Domain-Data
- One way to think about this is a parallel between the other layers
- DTO: maps to the presentation layer
- Domain: maps to the facade/services layer
- Data: maps to the repository layer
Okay, so the data access stuff is pretty straightforward, and I’ll use LINQ to SQL as the example. Can you use L2S as your domain model? I don’t know. Someone smart enough could probably figure it out. But, I’m not that smart and I don’t want to worry about it. So, I create Data Objects the standard way. Drag and drop the fu&*er. Or use SqlMetal. But, in any case, I don’t worry (that much) about how L2S does what it does. I don’t want to TDD this area, unless I have edge-cases. If i’m using IRepository, I don’t want to test every instance of T here. It is akin to me of testing if int works in the CLR. You assume the framework does what it does properly. Similarly, I assume that once you get the basic case of IRepository working, it will work across the board.
I do want to test the mapping. Since I may refactor my domain objects, I need to know that the mapping between my domain objects and my data objects continues to work. This allows me to continually refactor my domain and then test the mappings to know they are in sync, without having to test *everything* down the stack.
An obvious question is whether or not this whole thing is a good idea. Could I improve the different layers and how they interact? Obviously there are times when I might say yes to this question, but I judge the ‘is it a good idea’ question by how easy it is for me to implement functionality. And because I have a comfort level with the way I’m doing it now, I go with it.
The bottom line is that the way I’m doing it now works efficiently for me. I’m used to it. The places or junction points where I am not so sure about, I build tests. The rest, I trust that the framework will test for me.