TDD, DDD, Distrubuted N-Tier apps, and a little time travel

Warning: incoming wall of text!

This post is about test driven development, domain driven design, and distributed n-tier apps. But before I can really get into things, I need to take a few moments and give you an idea of where I came from.

I started developing in 1991 with Borland’s Object Windows Library and the C++ compiler with a copy of Appleman’s WinAPI bible at my side. Later, I incorporated Paradox tables into small db apps.

Later, I migrated to Visual Basic 3, and it’s successors. During this time, I learned how to write basic SqlServer procedures and used that instead of Paradox. It was at this time, circa Visual InterDev and VB6 that the company I worked for wrote distributed n-tier apps.

These apps typically had a data access layer (considered the bottom of the stack), several DCOM-MTS components, which provided the business logic and user state mechanics, and either a thin-client desktop app, or web app.

Then I retired.

In 2002 I got hold of Visual Studio 2002 Enterprise on my own and started dabbling again. It was fun. There was a lot of things I got excited about, but things still weren’t really robust enough, so I waited while toying with it.

In the meantime, I came up with an idea for a project (my forum application), and while it would not come close to competing with major releases already out there, I wanted to see it through if for no other reason than to say I did it.

Forward to 2008.

I picked up VS2008Pro, and things had gotten much better. I started writing my forum app in vb. Had some minor issues, but nothing major. I was moving along great, then MVC 1.0 was released. Back to square one. After a year or so, I still hadn’t duplicated what I already had, but I trudged on, trying different things, and eventually migrating to C#.

Forward to 2010.

I picked up VS2010Pro. Love it, but in the past couple weeks, my project has devolved even further. I am at a place now where, out of everything I had before, only one table is in the db, and only one view is in the project.

So what exactly is the problem? Am I too old for this now? No. Of course not. Is it too complex? No. Of course not.

I think the main problem is, and it is one shared by a lot of people, is there are no real solid examples of how modern applications are developed. This is something most of us have to stumble though on our own, and it can be greatly hindered by our past experiences and notions of how things work.

I am going to try and explain what TDD and DDD are, and are not, and provide some small concrete examples of each.

First, let me state that TDD and DDD are not the same thing, although if you use one, you will probably use the other, but neither requires the other.

Second, they are not patterns in the traditional sense. They aren’t even code-based, and this is why examples are rare, or hard to understand.

Let’s start with TDD, and assume I want to design a car. I get out some paper and start making notes:

Do I have a frame? No.
creates frame and asks again
Do I have a frame? Yes.

[COLOR=#000000]Do I have an eninge? No.
creates engine and asks again
[COLOR=#000000]Do I have a engine? Yes.

Does the engine work in the frame? No.
adjusts engine and asks again
Does the engine work in the frame? Yes.

This is test driven development. The concept is that you only create what you need, as you find that you need it. If I had started out by piling a bunch of parts together, we may have ended up with the Etsel as opposed to a Ferrari.

Developers approach things the same way, using unit tests. I should probably comment here simply using unit tests, by themselves, does not mean you are using TDD. One can use a unit test to do other things as well, including performing stress test, validation tests, and other things, post-development.

Like TDD, DDD is a way of thinking about your application, and there is bleed between these two. Let’s say I am writing a pick-pack-ship program for some plant. Instead of going in and piling a bunch of properties and methods into a class that way may not even need, we carefully craft the component, one element at a time, based on need. But it’s more than just simply adding properties and methods to a class also. To understand this, let’s back up a bit.

If you recall, in the old days (8-10 years ago), when things were done via MTS, our business layer operated as DCOM objects which used an external DAL to read and write to the db. The classes that moved back and forth between the DCOM objects and the DAL were nothing but simple DTO classes (and if you were a purist, sometimes even arrays or structs). The objects that moved between the client and the DCOM objects were similar except they were exposed only the fields required by a particular request.

Ok, now if you’ve paid attention, you’ll see that all the responsibility for validating values, and applying business logic was in the DCOM objects. Data simply HAD to go through them in order to get to the database. There was no other way. This worked, but there were problems. Namely, the MTS role system was designed for users who were logged in as part of a corporate domain. This didn’t work so well for publically accessible websites.

We now have a web environment that is managed, and all the “layers” of your application reside in the same bin folder. This means that a coder could concievably push data into the database via the dal, bypassing the service layer. This is not good. We needed a way to ensure that the data is always intact and valid. The solution was to move as much of the logic as we could from external classes and put it into the data classes themselves.

As I mentioned a moment ago, DDD is a way of thinking about your application more-so than coding, so simply taking a data class, and adding simple accessor methods around the properties isn’t enough. For example:

public class Car
{
public Engine Engine { get; protected set; }
public void SetEngine(Engine engine) { Engine = engine; }
}

Well, this class is certainly more secure than before, but it still isn’t domain driven. Why? It’s code based. Try going to a mechanic and asking him to “SetEngine”. He’ll probably just go grab a beer.

Now, consider the next example:

public class V4Engine : Engine { }
public class V6Engine : Engine { }

public class Car
{
private engineIsUpgradable = false;
private Engine engine = new V4Egine();
public void UpgradeEngineToV6()
{
if (!engineIsUpgradable) throw new Exception(“Sorry, can’t do that!”);
engine = new V6Engine();
}
}

Now this is domain driven. Why? Because it reads like a request:

car.UpgradeEngineToV6();

However, it is a poor domain. Cars cannot upgrade thier own engines. You need to get a mechanic to do it.

mechanic.UpgradeEngineToV6(owner, car);

The above would test the following:

Does the owner have the funds?
Does the mechanic have a v6 engine on hand?
Will the car accept a v6?
Finally the transaction get’s done.

So really, after all this typing:

TDD is simply designing objects, piece by piece, when, and only when, a proven need exists.

DDD is simply design objects, and their methods, as if they were living things (hence the term entity), and need to be asked to do something, or asked if they can do something.

With such things in place, you can now be assured that, even if you send such objects right to the persistence layer, they are valid.

That’s it folks. Hope this was helpful.
[/COLOR][/COLOR]