Refining the Domain Model Through Simple TDD Experimentation


Do you remember the very early sketch we had when we left Chapter 4, "A New Default Architecture"? You'll find it again in Figure 5-1.

Figure 5-1. Early sketch from Chapter 4


I went a bit overboard, providing too many details in the sketch which I normally wouldn't have. Anyway, it's better now than never to really learn some of the details of the requirements. Let's start implementing this now in a TDD-ish manner and see what issues we need to address and resolve, and by doing so we'll evolve the model as we go.

I typically attack feature by feature, but considering that we talked about some UI sketches in the last chapter, I think I'll start by trying to make it possible to support those UI sketches and later on summarize what features we covered.

Starting with the Creation of Order and OrderFactory

We'll start out by creating the Order class and the OrderFactory. I'll skip thinking about everything at first except for what is shown in Figure 5-2.

Figure 5-2. First part to implement, parts of Order and OrderFactory


Note

The first few steps are necessary to properly create the domain objects. We must complete these steps before we can get to the interesting and crucial part, namely testing and implementing the logic that our model facilitates.


I'll get started on writing a first test for this. I'll test so as to make sure that I don't get null back when I ask the factory to create a new order. Here goes:

[Test] public void CanCreateOrder() {     Order o = OrderFactory.CreateOrder(new Customer());     Assert.IsNotNull(o); }


Note

You might wonder why I name my tests the way I do? The early convention for naming xUnit tests was to prefix them with "Test," but that's not necessary with NUnit, for example, because it will understand the attribute Test instead. This means we are free to name the tests the way we want. This also means we get the tech-talk out of the way and can focus the discussion on domain concepts and design.

I like naming the tests as statements of what the tests intend to verify. That way, the collection of test names becomes a list of what should be possible and what should not.


At first, the test looks extremely simple. To make the test compile, I need to create an empty Order class. That's fine for now. Next, I need to create an OrderFactory class with a single method, but our problems start cropping up already when writing that method. One of the rules defined in Chapter 4 was that an Order always has to have a certain Customer, and this is solved by giving that responsibility to the OrderFactory, giving the Order a Customer at creation time. Therefore, the CreateOrder() method of the OrderFactory needs to receive a Customer instance as a parameter (which you can see in the test code). No rocket science there, but we have just started working on the Order Aggregate and we would like to forget about everything else right now.

The first solution that springs to mind (which is also visible in the test I wrote previously) would be to also just create an empty Customer class. After all, I will need it really soon, and I'm not going to interact with it in this test, so there isn't a lot of coupling added between the building bricksat least not yet. On the other hand, it feels like we are touching on too many things in this first little test. That's a typical smell, so let's try to avoid that if possible.

The second solution I thought about would be to mock the Customer and thereby create looser coupling between the Aggregates, at least in this test. I certainly do like the idea of mocks, but it feels a little bit like overkill here. After all, I'm not going to interact with the Customer at all; I just need the Customer more or less as a placeholder.

The third solution could be to create an interface called ICustomer (or something similar, or let Customer be an interface) and then create a stub implementation of the interface. Again, that feels like overkill right now, and what would the purpose be when moving forward? To be able to swap ICustomer implementations? Is that really something I expect? No, I don't, so until proven wrong, I decide that this isn't the solution I am going to start with.

The fourth solution could be to skip the Customer parameter. I could do that temporarily in order to get going and then change the test when I add the Customer parameter later on. I could also decide that I probably don't want gluing the Order and the Customer together to be a responsibility of the factory. Could it have been a premature design decision that TDD revealed in a few seconds?

Not binding the Order and Customer together in the factory would actually add flexibility to the UI design so that I don't first have to start with choosing the customer. Instead, I could start by letting the user fill in other information about the new order and then ask the user who the customer is. On the other hand, flexibility somewhere usually means complexity somewhere else. For example, assume prices are customer dependent; what price should be used when I add OrderLines to the Order without a defined Customer? What should happen later? It's certainly not impossible to solve, but we shouldn't introduce complexity if we can avoid it.

Another drawback with the fourth solution is that the Order I get back from the factory isn't really in a valid state. The rule was that every Order should have a Customer. Sure, the order isn't persisted in the factory, but it's still not in a valid state. The consumer must do something to transform the order to a valid state after the factory has executed.

A fifth solution could be to use object as the type for the parameter to CreateOrder(), but that's not very purposeful, and it adds to the casting needs. The same goes if you invent some generic interface that all your Domain Model classes should implement, like IEntity, and then use that as a parameter. What we are discussing now is using a sledgehammer to crack a nut.

You probably think that I'm violating the principles of TDD here by thinking too much instead of trying it out with tests, code, and refactoring. On the other hand, during the time it takes you to write the name of the test, lots of ideas and thoughts (and decisions) will flee through your mind very fast and semi-consciously. (This, of course, depends on your experience with the problem at hand.)

Anyway, let's not think too much and instead decide on one solution to try out. I'll grab the first one. Adding an empty Customer class with a public default constructor is actually very quick and easy to do, so let's do that. Now the test compiles, and I get a red bar because I only wrote the signature and only returned null from the CreateOrder() method in OrderFactory.

It's time to implement CreateOrder(). The first try could look like this:

//OrderFactory public static Order CreateOrder(Customer customer) {     return new Order(); }


For that to compile, I must have an accessible default constructor of the Order. It could be public, but instead I decide to let it be internal in order to hinder the consumer of the Order class instantiating it except via the OrderFactory. Sure, this isn't the perfect protection, but at least direct instantiation by mistake will only happen inside the Domain Model, and that's a step in the right direction in my opinion.

Refactoring time? Well, what value does the factory really add? Not anything yet. It just adds a bit of complexity. I really should have at least started without the factory, because it shouldn't be around if it doesn't add value. Now I still think there are quite a lot of things it will deal with, such as snapshotting the customer, adding null objects, creating different kinds of orders, and a few other things.

But the code so far just feels silly now with a factory, don't you think? It might add value later on, but now it's less simple than it could be. Let's change it directly to use the simplest possible construction for this: direct use of a constructor.

Note

It feels strange to refactor away from a factory. But it's just a sign that I got carried away and started out with a too detailed design from the beginning.

Also worth pointing out is that I had a CreateOrderLine() method in the sketch in Chapter 4, but life is simpler without it.


[Test] public void CanCreateOrder() {     Order o = new Order(new Customer());     Assert.IsNotNull(o); }


Any other tests to write? Sure, what we have been discussing all along is how to deal with the customer parameter. So in my opinion an interesting test would be to check that a newly created order has a customer. I currently don't have verification of that. Let's add a test for doing so.

[Test] public void CanCreateOrderWithCustomer() {     Order o = new Order(new Customer());     Assert.IsNotNull(o.Customer); }


This test tells me that I need to add a Customer field or property on the Order. (I think it will be needed not only for my test, but also for some of the requirements.)

In order to cut down the complexity, I decide on a read-only property like this in the Order class:

//Order public readonly Customer Customer;


If there is no way to change the Customer of the Order, we can expect it to be ever-present (and never-changing), and that will simplify the other rules. If you don't need the flexibility...

Now everything compiles and life is good, and we do get a red bar. That's easily fixed by modifying the constructor so it uses the customer parameter. The constructor now looks like this, and we get a green bar:

//Order public Order (Customer customer) {     Customer = customer; }


Some Domain Logic

In Figure 5-2, I mentioned that I should also add OrderDate to the Order. What could the semantics around that one be? The order should probably get an initial OrderDate when first created and then a final OrderDate when the order gets the status of Ordered (or something like that). Let's express that in a test:

[Test] public void OrderDateIsCurrentAfterCreation() {     DateTime theTimeBefore = DateTime.Now.AddMilliseconds(-1);     Order o = new Order(new Customer());     Assert.IsTrue(o.OrderDate > theTimeBefore);     Assert.IsTrue(o.OrderDate         < DateTime.Now.AddMilliseconds(1)); }


The idea with the test is to set up an interval of spots in time and then check that the OrderDate is within this interval.

As usual, this won't compile. I need to add a public OrderDate property. This time, I'm using a private field + a public getter since I'm going to change the OrderDate value later on in the lifecycle. And this time, I let the constructor of the Order set the OrderDate field without adding another parameter to the constructor. For clarity, here's the piece:

//Order private DateTime _orderDate; public Order (Customer customer) {     Customer = customer;     _orderDate = DateTime.Now; } public DateTime OrderDate {     get {return _orderDate;} }


We get a green bar.

I started this section with a diagram describing a subset of the model in Figure 5-2. The model has evolved slightly, as shown in Figure 5-3 where I visualize the code.

Figure 5-3. First part to implement, Order, revised


Note

You might wonder why I draw figures by hand sometimes and with a UML tool sometimes. The reason is that I wanted to illustrate that upfront, I just sketch quickly as a help with the thought and communication process. When I have implemented the thing, then I may visualize the implementation with a UML tool.


When you compare Figure 5-3 with Figure 5-2, the visible differences aren't that big. It's actually just that I had to implement a first version of the Customer class and the relationship from Order to Customer. That's not a real change to the model; only to the subset diagram.

Note

I also show the constructor in Figure 5-3 to give a more detailed view of how the classes work.


It's time for refactoring before moving on to the next step. First, I wanted the call to the constructor of the Order to be moved out to the [SetUp], but then I would have to change the last test slightly regarding the time interval, and that would make it a little less to the point. Moreover, the three tests shown so far are just about the creation, so I like having the calls in the test methods themselves. Let's leave refactoring for the time being and move on with refining the Domain Model.

Second Task: The OrderRepository + OrderNumber

In the previous section, we talked about what the OrderFactory could look like in order to serve our need to create new Order instances from scratch, but then decided to skip the factory for now. In my opinion, the next problem naturally is how the OrderRepository should work out.

In Chapter 4, I discussed GetOrders() of the OrderRepository. Right now, I think the most important, typical method is GetOrder(), and therefore I'd like to start with that one and the identifier of the Entity Order.

While we're talking about it, what is OrderNumber? Well, typically an order has some form of unique identification that could be used by humans for identifying one particular order. One common solution is to just assign a new number to each order from an ever-increasing sequence of numbers. In Figure 5-4, I show the Order class again after modification and the newly added method in the OrderRepository class.

Figure 5-4. Order and OrderRepository


I know, I was supposed to talk about the OrderRepository, but I think it is important to do something about the OrderNumber first. Do we have to give the Order its identity when it is created? I think it's correct to say that the OrderNumber is 0 until the order is saved (meaning that the status is Ordered) for the first time. Until it is, we don't want to waste an OrderNumber on something that just might become a real order.

Note

This depends very much on the requirements (whether it's good or bad), but I get a growing feeling that we are mixing two different things here the business identification and the persistence identification. We'll come back to that in a later chapter.

I also strongly dislike the coupling between persistence and business rules. I mean that the moment the order is persisted, it's also "Ordered." We'll leave that for now and come back to it in Chapter 7, "Let the Rules Rule," when we focus on business rules.


So as usual we can then write a very simple test like this:

[Test] public void OrderNumberIsZeroAfterCreation() {     Order o = new Order(new Customer());     Assert.AreEqual(0, o.OrderNumber); }


Guess what? This won't compile, so I add a new read-only property called OrderNumber to the Order class and let it use a private _orderNumber field.

This way we dealt with OrderNumber from the constructor perspective. If the OrderNumber property is read-only, however, how can we give it the value when using the OrderRepository for finding and reconstituting an old Order? To make the whole issue clear, let's take a step back and write a test and a [Setup] method (after having declared OrderRepository with the name _repository):

[SetUp] public void SetUp() {     _repository = new OrderRepository(); } [Test] public void OrderNumberCantBeZeroAfterReconstitution() {     int theOrderNumber = 42;     _FakeAnOrder(theOrderNumber);     Order o =     _repository.GetOrder(theOrderNumber));     Assert.AreEqual(theOrderNumber, o.OrderNumber); }


As usual, the whole thing won't compile. I don't have an OrderRepository class, so I write one with just a signature for the GetOrder() method and no code. The test code still won't compile, so I have to stub the _FakeAnOrder() in the test class. I get a red bar.

I'm just getting further and further away from the problem I thought I wanted to focus on. To be able to write the _FakeAnOrder() method, I need to make it possible for the Repository to know about an Order. I could go ahead and implement a new method in the OrderRepository that is only there for supporting other tests, but I think this is a good sign of my needing to write another test instead. I need to test saving Orders, or at least make the Repository aware of Orders.

Note

I have to admit that I have quite a lot of ideas about how the saving should really happen, but I'll move on slowly here and write simple code that I will refactor a lot now. Please don't get upset about this; it's not the final solution.


So, I add the Ignore attribute to the OrderNumberCantBeZeroAfterReconstitution() test so that it won't give me a red bar right now. Then I write another test that looks like this:

[Test] public void CanAddOrder() {     _repository.AddOrder(new Order(new Customer())); }


As usual, it won't compile. I need to add the AddOrder() method to the OrderRepository. And as usual, I just add the signature, but this is not enough to get a red bar. As a matter of fact, there is no test code at all in the CanAddOrder() method. The reason is that I'm not keen on the idea of letting the Repository publish any methods for the sole purpose of an external test class for checking the inner state of the Repository. Sure, I could use the GetOrder() method, but then it's the chicken or the egg scenario. The implementation of this method is far from even being started yet.

Instead, I take a step back and add a private IList to the Repository for holding on to the orders. I don't publish anything about the IList to the outside; it's very much an implementation detail, and I already think I will have to get rid of it really soon. Instead I use another assertion, not a xUnit one, but an assertion from the Diagnostics namespace for checking what I think should be checked. What the Assert() does is check that the statement is true. If not, the developer will be notified. The AddOrder() method could look like this:

//OrderRepository public void AddOrder(Order order) {     int theNumberOfOrdersBefore = _theOrders.Count;     //TODO Add here...     Trace.Assert(theNumberOfOrdersBefore         == _theOrders.Count - 1); }


Need for Another Assert Lib?

You should think twice before using the ordinary Diagnostics assertions. One problem with that is that it won't integrate well with NUnit. Another problem is that I can't customize it for how it should act in different situations like development, continuous integration, beta testing, and during production. I discussed this some more in my earlier book [Nilsson NED].

You might also wonder why I didn't make sure that the test could be expressed somehow in a NUnit test. I could expose the necessary state that the test needs, but I prefer not to if I don't have to. If I did, it would make it harder to refactor the Repository class, andagainI'm sure I need to do that.

The technique I used earlier is to some extent inspired by Design By Contract by Bertrand Meyer [Meyer OOSC]. Even though it's not formalized at all, the assertion expresses what the AddOrder() ensures, that is its assurances for post-conditions.

What could be the pre-conditions that the AddOrder() requires? Perhaps that the order isn't known to the Repository before? No, I dislike seeing that as an error. That _theOrders isn't null? But the method would throw an exception if it is. It's also the case that the whole thing about _theOrders is a very temporary solution, as you will soon see. Let's leave this alone for now.


So let's create Mytrace.Assert(), which will just throw an exception if it receives false as the parameter. That way, it at least integrates well with NUnit/Testdriven.net.

Compile, test, and red bar. Good. So let's swap the TODO-comment for the add call:

//OrderRepository public void AddOrder(Order order) {     int theNumberOfOrdersBefore +1 = _theOrders.Count;     _theOrders.Add(order);     MyTrace.Assert(theNumberOfOrdersBefore         == _theOrders.Count); }


And we now have a green bar. We are writing some strange code here and there, but we are moving forward, and we are creating tests that aren't weird at all along the way, so let's continue.

Note

I could have also worked with a mock to verify that the System Under Test (SUT) worked as expected, but you can probably envision how from Chapter 3, "TDD and Refactoring," so let's move forward.


Now it's time to go back to the OrderNumberCantBeZeroAfterReconstitution(), and what I stumbled on the last time was the help method for the test that I called _FakeAnOrder(). It could look like this:

//A test class public void _FakeAnOrder(int orderNumber) {     Order o = new Order(new Customer());     _repository.AddOrder(o); }


Ouch, we are now experiencing another problem. Do you see it? Yep, how can we get the faked OrderNumber into the order instance? The OrderNumber property was read-only (which makes sense), so using that one won't work.

As a matter of fact, this is a generic problem. It can be expressed like this: How can we from the outside (such as in a Repository) set values in instances that are being reconstituted from persistence?

Reconstituting an Entity from Persistence: How to Set Values from the Outside

I mentioned the generic problem of setting values in an instance that is being recreated by reading it back from the database. In the case of OrderNumber it's obviously a problem because the OrderNumber will never change by letting the consumer interact with the property directly, but it's more or less the same with other attributes. Let's for the moment assume that OrderDate is read/write. If the consumer sets a new OrderDate, there might need to be some checks kicking in. It's probably not interesting to execute these checks when the OrderDate is getting a value at the time an order is being read from the database and reconstituted as an instance.

There are several possible ways in which to deal with this problem. Let's see what we can come up with.

Use a Specific Constructor

We could have a specific constructor that could be used just for this reconstitution. It could look like this:

//Order public Order(int orderNumber, DateTime orderDate,     Customer customer)


It works, but it's not very clear to consumers of the Order that they aren't supposed to use that constructor. Well, I could let it be internal, of course, to lessen the problem quite a lot!

The intention of the constructor could become slightly clearer if you use a static named method as a factory like this:

//Order public static Order ReconstituteFromPersistence(int orderNumber     , DateTime orderDate, Customer customer)


This not only makes the purpose of the method slightly clearer, but also the fact that the consumer should not mess with this method. Still, it's possible for the consumer to use the method by mistake, butagainthat could be dealt with by using an internal method instead. It's also problematic when the class gets more real world-ish, when instead there are perhaps 50 properties that should be set at reconstitution. If this is the case, the parameter list became unwieldy a long time ago.

Use a Specific Method, Typically in a Specific Interface

Another option is to decide on a method that the Order class has to implement, and typically this method should just be reachable via a specific interface. Consequently, there is much less of a risk that the consumer will mess with the method by mistake. If the consumer wants to do evil things, he can, but that's more or less always a problem. If it's possible to set values in the instance from the outside, the consumer can do it too. That is actually not necessarily a bad thing. Instead you should take a reactive approach and decide that the possible usage didn't create a problem.

So what could this look like? One approach could be to have a method like this on the Order:

//Order public void SetFieldWhenReconstitutingFromPersistence     (int fieldKey, object value)


It's definitely a bit messy. Now we have to set up a map of field keys, which must be maintained from now on, both as the map and as regards the SetFieldWhenReconstitutingFromPersistence() code itself.

A similar solution (still without a nice maintainability story) would be to swap the fieldKey parameter for a fieldName parameter instead.

Use Reflection Against the Private Fields

I could use reflection, but there are pros and cons to this, as usual. The drawbacks are that reflection is slow (at least compared to ordinary access, but is it too slow?), we can't close down privileges for the user, and we must know about the internal structure such as field names from the outside. (The last thing could be dealt with in part by adding private properties that are only there to be used for the reflection or by setting up naming rules so that if the property is called Name, there should be a private field called _name. It might become slightly more robust, but the basic problem is still there.)

The most important advantage is that it's not intrusive. You can create your Domain Model just the way you want it, without having to add infrastructure-specific and obscure constructions.

Note

Well, there are small details, such as that Customer can't be readonly. We'll get back to this in depth in later chapters.


A Totally Different Solution...

We could go for a completely different solution: for example, keeping the values outside the instance all the time in a "safe place" so that the instance is just like a Proxy [GoF Design Patterns]. It really is a totally different solution, along with its ups and downs. However, I really don't like making such a big, specific decision right now. It would also mess up the Domain Model classes with stuff that has nothing to do with the domain. Let's continue as simply as possible.

All this has quite a lot of infrastructure flavor, hasn't it? I'd like to postpone the decision regarding how to set values from the outside until later, when I start thinking about what infrastructure to use for supporting my Domain Model. On the other hand, I need to make some sort of decision now in order to move on with the tests. What's the simplest mechanism that could possibly work for now? Unfortunately, there is no really simple solution that I can come up with now. That's a good sign that I should probably go back and rethink the whole thing.

Note

It's pretty ironic that we ended up in this long discussion just because I started to work with the semantics around OrderNumber. But we are here now, so let's end the discussion.


For now, I decide to use reflection against the private fields. I write a helper method in the OrderRepository (which probably should be factored out later) that looks like this:

//OrderRepository public static void SetFieldWhenReconstitutingFromPersistence     (object instance, string fieldName, object newValue) {       Type t = instance.GetType();       System.Reflection.FieldInfo f = t.GetField(fieldName           , BindingFlags.Instance | BindingFlags.Public           | BindingFlags.NonPublic);       f.SetValue(instance, newValue); }


At last, we can move on again. What a long discussion just because OrderNumber was read-only. Remember, however, that this was actually a generic discussion about how to let the Repositories set values when reconstituting instances from persistence without running into problems with read-only properties and code in setters.

Do you remember the test called OrderNumberCantBeZeroAfterReconstitution()? It's repeated here:

[Test] public void OrderNumberCantBeZeroAfterReconstitution() {     int theOrderNumber = 42;     _FakeAnOrder(theOrderNumber);     Order o =     _repository.GetOrder(theOrderNumber);     Assert.IsTrue(o.OrderNumber != 0); }


I added the Ignore attribute before so that the test wouldn't be executed. Now I take away the Ignore attribute, and I get a red bar.

Time to change the _FakeAnOrder(). I make sure that the new order gets the OrderNumber of 42, like this:

//A test class public void _FakeAnOrder(int orderNumber) {     Order o = new Order(new Customer());     OrderRepository.SetFieldWhenReconstitutingFromPersistence         (o, "_orderNumber", orderNumber);     _repository.AddOrder(o); }


Still a red bar, but it's due to something else this time. I'm afraid that I created a situation for myself when there were several reasons for red bars, which is not recommended. I took too big a leap in my TDD approach.

Anyway, the problem is that I haven't implemented OrderRepository.GetOrder(). It's just an empty method (returning null). For the moment, we have the orders in an IList so we can just iterate over the items in the list, checking them one by one. It could look like this:

//OrderRepository public Order GetOrder(int orderNumber) {     foreach (Order o in _theOrders)     {         if (o.OrderNumber == orderNumber)             return o;     }     return null; }


I know, it's a naïve implementation, but that's just what I want right now. And guess what? Green bars.

So we are back on dry ground, but my whole being is screaming for refactoring the SetFieldWhenReconstitutingFromPersistence() method. The SetFieldWhenReconstitutingFrom-Persistence() method just doesn't belong in the OrderRepository. I create a RepositoryHelper class for now and move the SetFieldWhenReconstitutingFromPersistence() method there. Still a green bar after I changed the call to SetFieldWhenReconstitutingFromPersistence().

Let's have a look at how the Domain Model diagram looks now. You'll find the revised diagram in Figure 5-5.

Figure 5-5. Order and OrderRepository, revised


I have the growing feeling that the whole thing isn't as good as I want it, but I can't put my finger on why. I'm sure it will appear more clearly when I move on, so that's what I'd like to do now. What's next on the list? Perhaps fetching the list of orders for a certain customer.

Fetching a List of Orders

So what we are talking about is another method in the OrderRepository called GetOrders(), which takes a customer as parameter for a start. When we have found some Orders, the second part of the problem is to show some values such as OrderNumber and OrderDate. In Figure 5-6, you find a diagram showing what I think

Figure 5-6. Order, Customer, and OrderRepository for listing orders


we will be creating in this section.

Note

Did you notice how different the multiplicity in the UML diagram in Figure 5-6 is compared to how it would be expressed in a database diagram? If you come from a database background, I think differences such as no navigable relationship from Customer to Order might surprise you, and the multiplicity is one to one for the relationship that is there because it is from Order to Customer.


It's time for another test. Again, I need to fake Orders in the OrderRepository for the test to run. Here goes:

[Test] public void CanFindOrdersViaCustomer() {     Customer c = new Customer();     _FakeAnOrder(42, c, _repository);     _FakeAnOrder(12, new Customer(), _repository);     _FakeAnOrder(3, c, _repository);     _FakeAnOrder(21, c, _repository);     _FakeAnOrder(1, new Customer(), _repository);     Assert.AreEqual(3, _repository.GetOrders(c).Count); }


As you saw, I changed _FakeAnOrder() so it now also takes Customer and OrderRepository as parameters. That's a simple change, of course. Another pretty simple thing is needed for making the solution compile and that is adding the GetOrders() method. It could look like this (after you first took that mandatory tour of red, of course):

//OrderRepository public IList GetOrders(Customer customer) {     IList theResult = new ArrayList();     foreach (Order o in _theOrders)     {         if (o.Customer.Equals(customer))             theResult.Add(o);     }     return theResult; }


I'm not sure I really like the previous code. I'm thinking about the check for equality. Assume that I have two Customer instances (not two variables pointing to the same instance, but two separate instances), both with the same CustomerNumber. Will the call to Equals() then return true or false? It depends on whether Equals() has been overridden or not and whether or not the overridden implementation uses the CustomerNumber for deciding on equality.

Note

Readers that are familiar with the concept of the Identity Map pattern [Fowler PoEAA] and who see it as a must will probably wonder why we are having this discussion at all. The idea with Identity Map is that you will not have two separate instances for a single customer. The Identity Map will take care of that for you.

The language itself, C# for example, won't take care of this for you. But when we discuss persistence solutions in Chapter 8, "Infrastructure for Persistence," and Chapter 9, "Putting NHibernate into Action," we'll cover this. Until then, we are on our own.


It's Time to Talk About Entities

Well, we have already touched on this subject several times in this chapter since Order and Customer are examples of Entities, but let's take a step back and focus on the concept.

It is important for us to keep track of some things in the domain over time. No matter whether a customer changes name or address, it's still the same customer, and it's something we are interested in keeping track of. On the other hand, if a customer's reference person changes, it is probably not anything we care to keep track of. A customer is a typical example of an Entity [Evans DDD]. Again, an Entity is something we keep track of by identity rather than all its values.

To take an extreme example of something that isn't an Entity, let's think about the integer 42. I don't care about the identity of 42 at all; I only care about the value. And when the value changes, I no longer think it's the 42 that has changedit's a totally new value with no connection to the old one. Forty-two is a Value Object [Evans DDD] and not an Entity.

If we take that extreme example over to our domain, we might be able to say that it isn't interesting for us to track ReferencePerson of a Customer by identity. It's only interesting for us to track it by value. We'll get back to Value Objects later on in this chapter.

Note

Of course, what should be tracked by identity and what should just be thought of as values is highly dependent on the domain. Let's take an example. As I said above, I believe that ReferencePerson in this application can be dealt with as a Value Object, but if the application is for, let's say, a sales support application for salesmen, perhaps they see ReferencePerson as an Entity instead.


Back to the Flow Again

Unfortunately, the test CanFindOrdersViaCustomer() won't execute successfully after I override Equals. The reason is that all customers used in the test have the same CustomerNumber, that being zero, and therefore I find five Orders that have the right Customer, not three. We need to change the test a little bit. I create another little helper method called _FakeACustomer() like this:

//A test class private Customer _FakeACustomer(int customerNumber) {     Customer c = new Customer();     RepositoryHelper.SetFieldWhenReconstitutingFromPersistence         (c, "_customerNumber", customerNumber);     return c; }


Note

_FakeACustomer() should associate the customer with the CustomerRepository (or rather the Unit of Work, when that comes in to play). Let's skip this for now because it won't affect the flow now.


Then I change the test CanFindOrdersViaCustomer(), so I use _FakeACustomer() instead of just calling the constructor of the Customer directly. The code looks like this after the change.

[Test] public void CanFindOrdersViaCustomer() {     Customer c = _FakeACustomer(7);     _FakeAnOrder(42, c, _repository);     _FakeAnOrder(12, _FakeACustomer(1), _repository);     _FakeAnOrder(3, c, _repository);     _FakeAnOrder(21, c, _repository);     _FakeAnOrder(1, _FakeACustomer(2), _repository);     Assert.AreEqual(3, _repository.GetOrders(c).Count); }


We are back to green bar again.

I think it is time to sum up where we are with a figure. Since Figure 5-6, we have also added CustomerNumber to the Customer class, as you can see here in Figure 5-7.

Figure 5-7. Order, Customer, and OrderRepository for listing orders, revised


The Bird's-Eye View

What is it that we have tried to accomplish so far? To a guy like me who has spent over a decade working with databases and database-focused applications, the code looks pretty strange when you think about it. For instance, there are no jumps to a database at all. Sure, it feels nice to leave that for now when focusing on the Domain Model and writing tests, but I also want to have the possibility of writing tests without touching the database later on.

What have the tests bought us thus far? Well for starters, we've used the tests as a means to discover and nail down the behavior and specification that we want the Domain Model to implement. By starting out with Fake/naïve implementation, we've been able to concentrate our energy on inventing the API. We are also trying hard to come up with, and playing with, the Ubiquitous Language. Finally, our tests have now given us a solid foundation in which we can transition the code from our naïve implementation to the "real thing."

I also believe we have respected the eventual target with the design choices. We have also created an abstraction layer in the form of repositories so we can defer dealing with the database (which is worth deferring).

So, specifically what we have done was write a first fake version of the OrderRepository...! We have also given the OrderRepository several different responsibilities. That might be the reason for my uneasiness with the design. I don't want to focus on infrastructure at all right nowI want to postpone it until later on. However, because I noticed that what I'm currently working on is infrastructure within the Domain Model, let's wait with the feature list for a while and consider some refactoring to get a nicer solution with the faking of the OrderRepository.

Note

I'm trying to use "stub," "fake" and "mock" with specific, explicit meanings. Here's a quote from Astels [Astels TDD]:

"Stubs: A class with methods that do nothing. They are simply there to allow the system to compile and run.

Fakes: A class with methods that return a fixed value or values that can either be hardcoded or set programmatically.

Mocks: A class in which you can set expectations regarding what methods are called, with which parameters, how often, etc. You can also set return values for various calling situations. A mock will also provide a way to verify that the expectations were met."

But that's not the only definition. It's discussed a little differently by Meszaros [Meszaros XUnit]:

"A Test Stub is an object that is used by a test to replace a real component on which the SUT depends so that the test can control the indirect inputs of the SUT. This allows the test to force the SUT down paths it might not otherwise exercise.

"A Fake Objectis an object that replaces the functionality of the real depended-on component in a test for reasons other than verification of indirect inputs and outputs. Typically, it will implement the same or a subset of the functionality of the real depended-on component but in a much simpler way.

"A Mock Object is an object that is used by a test to replace a real component on which the SUT depends so that the test can observe its indirect outputs. Typically, the Mock Object fakes the implementation by either returning hard-coded results or results that were pre-loaded by the test."


Faking the OrderRepository

My first thought was that I should fake some of the inner parts of OrderRepository so that the same OrderRepository could be used in different cases and get an instance like a DataFetcher in the constructor, which will do the right thing. When I think about it more, it feels a bit like overkill. More or less the whole OrderRepository will have to be swapped if I decide to let the OrderRepository talk to a relational database instead of just being a fake. The whole class will have to be swapped.

Perhaps an interface like the one shown in Figure 5-8 is what I need for now.

Figure 5-8. IOrderRepository, first proposal


Instinctively, I like this a lot. It might be because of my COM heritage or because many authors (such as [Szyperski Component Software], [Johnson J2EE Development without EJB] and [Löwy Programming .NET Components]) clearly state that programming against interfaces is preferable to programming against concrete classes.

Stilland I have already touched on thisI do have concrete classes (Customer and Order) within the signatures of the interface. Again, I leave it like this for now because I don't currently see any value in creating interfaces for those classes.

Another thing that comes to mind is that it might be nice to create a more generic Repository interface. It could look like what is shown in Figure 5-9.

Figure 5-9. IOrderRepository (or rather IRepository), second proposal


This might grow on me, but right now I prefer the more specific interface in Figure 5-8, as it clearly states exactly what is needed. The generic IRepository requires more casts when being used and might be incorrectly trying to gather all upcoming Repositories in one and the same shape.

Another solution might be to use generics in the IRepository-interface + a base class and thereby at least get the type safety (and avoid code duplication) and avoid extra type casts. One problem then is that I might add a Delete() method to the Repository, even though not all Repositories will need it. And even with generics, the GetListByParent(parent) is troublesome because what if an Entity has several parents? Well, it's an early sketch and that can be solved of course. But I can't help thinking that it's better to let the code "speak as clearly as possible for now" and skip generalizations like that. It's just not feeling important yet. As usual, no decisions are carved in stone. I can challenge the decisions again later on when I can more easily see what pieces can be generalized, but for now, I'll stay with IOrderRepository.

Because of that, I rename the OrderRepository class to OrderRepositoryFake and let the class implement the IOrderRepository. I also need to change the [SetUp] code in my test class. It currently looks like this:

//A test class, the [SetUp] _repository = new OrderRepository();


It could now look like this:

//A test class, the [SetUp] _repository = new OrderRepositoryFake();


The declaration of _repository must use IOrderRepository as the type.

And the tests still work.

I guess pure XPers would groan a little bit at the refactoring I just did. I actually didn't have to make that change now; it was a change for preparing for the future, when I need a real Repository instead of the faked one. OK, I can agree with that, but I can't help thinking a little bit about the future (read: later chapters) when I will be hooking in infrastructure.

I cross my fingers that this preparation will prove to be good. I fell back into old habits of early guessing.... On the other hand, we are of course free to choose our own balance and don't have to stick to XP dogma!

A Few Words About Saving

I mentioned saving data previously. AddOrder() isn't really saving; it just adds the Order to the Repository. Or should it mean saving also? No, I don't think I want that behavior. What I want from AddOrder() is that the Repository (and the underlying infrastructure) from that point should know about the instance and deal with it when I ask for a PersistAll().

I need to ask the infrastructure to deal with the save functionality. The question for now is if I want to state the PersistAll() to the Repository instance or to something at a higher level that monitors instances for all the Repositories. Again, I think I'm drifting away from the Domain Model and into the infrastructure part. I'm glad the question was raised, but parts of the discussion will have to wait until the next chapter. There is a great deal that we need to discuss as far as that is concerned. For now, I'm happy with AddOrder() as a way of letting the Repository know about the instance. As far as the tests that have been written so far are concerned, it doesn't really matter that the instance is transient (but prepared for being persisted) and not persistent at that point in time.

OK, I'm as eager as you are to get writing some more tests. What's on the list? Well, I have dealt with most of it in feature 2, "List the orders when looking at a specific customer." What I haven't dealt with there is showing the total amount for each order, type of order, and reference person.

Let's take them one by one, starting with total amount for each order.

Total Amount for Each Order

At first this seems like a trivial task. I need to create an OrderLine class that I hook into the Order class as a list. Then I can just iterate over the OrderLine collection and calculate the total amount. I could actually do that from the consumer code, of course, but I don't want to. That would reveal the algorithm to the consumer, and it's not all that clear or purposeful either. In reality, the algorithm will become much harder when we move further, adding discounts of many different kinds, for example. Instead, I want a read-only property called TotalAmount on the Order class. Again, it could internally iterate over the OrderLine collection and calculate the value.

But this is getting to be too much for me, the "premature optimizer guy" that I am (even though I'm trying hard not to be). Instantiating all orderLines for each order for a customer just to be able to show the TotalAmount of the orders sets off the alarm bells. This might not be a problem depending upon the execution environment and chosen infrastructure. On the other hand, in the case of a distributed system, it is a problem, and potentially a big one that can hurt the database server, the network, and the garbage collector.

I must admit I have to force myself not to deal with this optimization right away. It's simple to fix it directly, but it's not really important right now when I'm crunching what the Domain Model should look like. It's much more important right now to design for simplicity and clarity, and get back later with a profiler to see if it's a real performance problem. So I start with the simplest solution and can then refactor the TotalAmount property later on if the performance characteristics aren't good enough.

Ah, I made it! I skipped an optimization now. And it feels so good for the moment.

Let's take a step back now that we have thought a bit about the TotalAmount. It's time to write a test (better late than never). I start with the simplest possible one I can come up with.

[Test] public void EmptyOrderHasZeroForTotalAmount() {     Order o = new Order(new Customer());     Assert.AreEqual(0, o.TotalAmount); }


It's simple to make that test compile. I just add a public read-only property called TotalAmount to the Order class and let it return -1. It compiles and I get red. I change it so that the property returns 0 and I have a green bar.

I could leave that for now, but because I have the context set up for me now, I continue a little bit. Here's another test:

[Test] public void OrderWithLinesHasTotalAmount() {     Order o = new Order(new Customer());     OrderLine ol = new OrderLine(new Product("Chair", 52.00));     ol.NoOfUnits = 2;     o.AddOrderLine(ol);     Assert.AreEqual(104.00, o.TotalAmount); }


Ouch, there was a lot of design done in that single test, and I now need to create two classes and new methods at old classes to just make it compile. I think I'd better comment out that test for the moment and start a little more simply, focusing on the OrderLine class.

First of all, I want the OrderLine to get the price from the chosen product as a default. Let's write a test.

[Test] public void OrderLineGetsDefaultPrice() {     Product p = new Product("Chair", 52.00);     OrderLine ol = new OrderLine(p);     Assert.AreEqual(52.00, ol.Price); }


Even that is a pretty large jump that requires some code to be written, but I'm feeling confident right now, so let's write a Product class. The second argument in the constructor should be the unit price. The Product class should also have two read-only properties: Description and UnitPrice.

I also wrote an OrderLine class with two members: Product and Price. It looks like this:

public class OrderLine {     public decimal Price = 0;     private Product _product;     public OrderLine(Product product)     {         _product = product;     }     public Product Product     {         get {return _product;}     } }


The test now compiles, but it's red. I need to change the constructor so that I grab the price from the Product and put it into the OrderLine itself. The constructor now looks like this:

//OrderLine public OrderLine(Product product) {     _product = product;     Price = product.UnitPrice; }


We are back to green again. I write a test proving that I can override the default price in the OrderLine, but it's not very interesting, so let's leave it out here.

The next test I'd like to write is a calculation of the TotalAmount of one orderLine. The test could be like this:

[Test] public void OrderLineHasTotalAmount() {     OrderLine ol = new OrderLine(new Product("Chair", 52.00));     ol.NumberOfUnits = 2;     Assert.AreEqual(104.00, ol.TotalAmount); }


Two more design decisions there. I need a NumberOfUnits field and a TotalAmount on the OrderLine. I let the NumberOfUnits be a public field, and I write the TotalAmount as a read only property returning 0. It compiles, but is red. I then change the TotalAmount into this:

//OrderLine public decimal TotalAmount {     get {return Price * NumberOfUnits;} }


Green again.

Let's have a look at what we just did. In Figure 5-10, you find a diagram with OrderLine and Product.

Figure 5-10. OrderLine and Product


It's time to go back to the test I commented out before. You'll find it again here, but I made it a little bit "bigger" this time, dealing with two OrderLines.

[Test] public void OrderWithLinesHasTotalAmount() {     Order o = new Order(new Customer());     OrderLine ol = new OrderLine(new Product("Chair", 52.00));     ol.NoOfUnits = 2;     o.AddOrderLine(ol);     OrderLine ol2 = new OrderLine(new Product("Desk", 115.00));     ol2.NoOfUnits = 3;     o.AddOrderLine(ol2);     Assert.AreEqual(104.00 + 345.00, o.TotalAmount); }


In order to get this to compile, I need to add AddOrderLine() and TotalAmount to Order. I let the read-only property TotalAmount just return 0 for the moment. And I set [Ignore] on OrderWithLinesHasTotalAmount() test. Instead, I write another test to focus on AddOrderLine(). That test could look like this:

[Test] public void CanAddOrderLine() {     Order o = new Order(new Customer());     OrderLine ol = new OrderLine(new Product("Chair", 52.00));     o.AddOrderLine(ol);     Assert.AreEqual(1, o.OrderLines.Count); }


For this to compile, I need to add both AddOrderLine() and an OrderLines property to the Order. Because the test will fail meaningfully if either of them isn't working, I get started by writing OrderLines the way I think I want it, but don't finish AddOrderLine(). You can find the code here:

//Order private IList _orderLines = new ArrayList(); public IList OrderLines {     get {return ArrayList.ReadOnly(_orderLines);} } public void AddOrderLine(OrderLine orderLine) { }


It compiles and is red. I add a line to the AddOrderLine() method like this:

//Order public void AddOrderLine(OrderLine orderLine) {     _orderLines.Add(orderLine); }


It compiles and is green.

It's time to delete the Ignore attribute from the test called OrderWithLinesHasTotal-Amount(). The test is red because TotalAmount of the Order just returns 0.

I rewrite the TotalAmount property like this:

//Order public decimal TotalAmount {     get     {         decimal theSum = 0;         foreach (OrderLine ol in _orderLines)             theSum += ol.TotalAmount;         return theSum;   } }


Simple, straightforward, and green. And did you notice that I resisted the urge to optimize it? I just wrote it the simplest way I could think of, and I even almost did it without groaning. After all, I currently see the Order and its OrderLines as the Aggregate and therefore as the default load unit as well.

Historic Customer Information

I think it's time for some refactoring. Any smells? One thing I didn't like much was that Order has a relationship with Customer. Sure, an Order has a Customer, that's fine, but if I look at an Order one year later, I probably want to see the Customer information as it was when the Order was created, not as it is now.

The other problem is that the constructor takes a Customer as a parameter. That means that the Order might get into the persistent object graph directly, without a call to IOrderRepository.AddOrder(), and this might not be such a good idea. (Well, it depends on your infrastructure as well, but it's not obvious that there is a boundary.) AddOrder() is the way of saying that this order should get persisted when it's time for saving.

None of these problems are at all hard to deal with, but how do I communicate this clearly? I write a test, to try out a proposal:

[Test] public void OrderHasSnapshotOfRealCustomer() {     Customer c = new Customer();     c.Name = "Volvo";     Customer aHistoricCustomer = c.TakeSnapshot();     Order o = new Order(aHistoricCustomer);     c.Name = "Saab";     Assert.AreEqual("Saab", c.Name);     Assert.AreEqual("Volvo", o.Customer.Name); }


But I'm not so sure about this solution... Currently, the Customer is a pretty small type, but it will probably grow a lot. Even though it's small now, is it really interesting to keep track of what reference people the Customer had at that point in time?

I think creating another type with only the properties that are interesting might be a good solution here because it will also create an explicit boundary between the Aggregates, but especially because that's what the underlying model indicates. Let's create a CustomerSnapshot (somewhat inspired by [Fowler Snapshot] regarding the purpose, but different in implementation) that only has the minimum amount of properties, and let it be a value object. The test only has to be transformed very slightly (after I have corrected two compile errors: the type for the Customer property and the parameter to the constructor):

[Test] public void OrderHasSnapshotOfRealCustomer() {     Customer c = new Customer();     c.Name = "Volvo";     CustomerSnapshot aHistoricCustomer = c.TakeSnapshot();     Order o = new Order(aHistoricCustomer);     c.Name = "Saab";     Assert.AreEqual("Saab", c.Name);     Assert.AreEqual("Volvo", o.Customer.Name); }


Another thing to consider is whether the consumer or the Order constructor is responsible for creating the snapshot. Previously, I let the consumer be responsible. Let's change that so that the constructor again takes a Customer instance as the parameter, as follows:

[Test] public void OrderHasSnapshotOfRealCustomer() {     Customer c = new Customer();     c.Name = "Volvo";     Order o = new Order(c);     c.Name = "Saab";     Assert.AreEqual("Saab", c.Name);     Assert.AreEqual("Volvo", o.Customer.Name); }


And the constructor of the Order looks like this:

//Order public Order(Customer customer) {     Customer = customer.TakeSnapshot(); }


Another thing to consider is if it's the correct place in time to take the snapshot when the customer instance is created. Isn't that too early? What if the customer changes? Perhaps we should take the snapshot at a transition for when the customer accepts the order? Lots of interesting and important questions, but I start like this now.

Let's just conclude this section with an update of the Customer. See Figure 5-11.

Figure 5-11. An added method for taking a snapshot of Customer


It's refactoring time again, I think. Hmmm...I'm not totally happy with the fact that I send a Customer instance to GetOrders() when finding Orders. It's actually just the ID of the customer that is important for the functionality, and it feels a bit strange to use a current customer for fetching orders with historic customer information. Anyway, I'd like to think about it some more.

Another question is what we should call the property of the Order for seeing the historic customer information of that order. Right now it's called Order. Customer, but that says nothing about the time aspect of the Customer information. Perhaps Order.CustomerSnapshot is better. I think it is, I make that change, and you can see the new Order-class in Figure 5-12.

Figure 5-12. Changed name of Customer property


Yet another thing is that Customers are instantiated directly and not with a CustomerFactory. It's absolutely OK for now, I think. We add factories when needed, not before!

Perhaps I should add that OrderFactory back again, add a method to it for CreateOrderLine(), and let it take both a Product and an Order as parameter (or at least an Order). On the other hand, it feels good to be able to work with an OrderLine without making it persistent (which will happen when I add the order line to a persistent order). Let's see if this might need to be changed later on, but this has raised another concern. I think I need to discuss the life cycle of an instance right here.

The Life Cycle of an Instance

In the previous section, I said that an order line becomes persistent when I add it to a persistent order, and this needs explaining. What I mean is that an instance starts its life as transient when you do the following, for example:

Product p = new Product();


Then the Product is transient. It is not fetched from the database as it has never become persistent. If we want it to become persistent (and stored to the database at next call to PersistAll()), we need to ask a Repository for help by calling AddProduct(). Depending upon the infrastructure that is used, the Repository makes the infrastructure aware of the product.

Then again, when I ask the Repository for help with reconstituting an instance from the database, that fetched instance is persistent when I get it. All changes I make to it will be stored at next PersistAll().

But what about OrderLine? I didn't ask the Repository to AddOrderLine(), but I did ask the Aggregate root Order to AddOrderLine(), and because of that the order line is made persistent, too. Within Aggregates, I think the persistence aspect should be cascaded.

Let's summarize what I think the semantics are for the life cycle that I need in my Domain Model. They are shown in Table 5-1.

Table 5-1. Summary of the semantics for the life cycle of the Domain Model instances

Operation

 

Result Regarding Transient/Persistent

Call to new

Transient

Repository.Add(instance) or persistentInstance.Add(instance)

Persistent in Domain Model

x.PersistAll()

Persistent in Database

Repository.Get()

Persistent in Domain Model (and Database)

Repository.Delete(instance)

Transient (and instance will get deleted from database at x.PersistAll)


In Figure 5-13, you'll find the life cycle described as a state diagram.

Figure 5-13. The life cycle of an instance


Note

Evans talks a lot about this too... [Evans DDD]. There is a splendid explanation for this, so be sure to read it. The same goes for Jordan/Russell [Jordan/Russell JDO]. JDO has more complex (and flexible) semantics, but of course I might discover later that the simple semantics I sketched previously are not enough.


Don't mix this up with how the infrastructure (for example NHibernate) sees the transient/persistent. What I talk about here is the way I want the life cycle semantics for my Domain Model instances. It's then up to the infrastructure to help me with the wanted semantics behind the scenes. This will be discussed a lot more in later chapters.

Talking about the infrastructure, the hawk-eyed reader might wonder what I meant with x.PersistAll() in Table 5-1. I tried to symbolize that unknown infrastructure with x. Again, we can forget about that for now.

Back to feature 2, listing orders for a customer. The next sub-feature was that an order must have an ordertype.

Type of Order

A simple solution here would be to add an OrderType instance to each Order, as shown in Figure 5-14.

Figure 5-14. Order and OrderType


I considered whether the OrderType is really an Entity [Evans DDD], and I don't think it isit is a Value Object [Evans DDD]. The set of possible values are "global" for the whole application and are very small and static.

I'm probably on the wrong track here. Sure, I could implement OrderType as a Value Object, but much is pointing in the direction that an enum is good enough, and especially good enough for now, so I define an OrderType enum and add such a field to the Order.

Reference Person for an Order

It's time to talk about ReferencePerson of an Order again. There I think we have an example of a Value Object [Evans DDD], although it is a bit different than the OrderType (which was a value object candidate) because reference people aren't global for the whole system but rather specific per Customer or Order. (Well, that's a good indication that ReferencePerson shouldn't be an enum.)

In Figure 5-15, you can see the ReferencePerson "in action."

Figure 5-15. Order and ReferencePerson


When we go for a Value Object pattern [Evans DDD], it might feel obvious that we should use a struct in .NET instead of a class, but there are recommendations for size regarding when to use a struct and when not to, and you'll get more problems with infrastructure when it comes to structs. It's also the case that you will see more boxing when using structs, so the decision isn't clear-cut. I'm actually leaning to using classes, but most often I'm making them immutable. If you go that route, you need to use all the values of the class for when you are overriding the Equals().

This is what the Equals() could look like for the Value Object ReferencePerson. (Note that I'm comparing all the fields of the Value Object, unlike how I did it with the Entity before. Also note that, Identity Map or not, overriding Equals() for Value Objects is needed.)

//ReferencePerson public override bool Equals(object o) {     if (o == null)         return false;     if (this.GetType() != o.GetType())         return false;     ReferencePerson other = (ReferencePerson) o;     if (! FirstName.Equals(other.FirstName))         return false;     if (! LastName.Equals(other.LastName))         return false;     return true; }


Note

Ingemar Lundberg commented on the previous listing with a more condensed version:

//ReferencePerson.Equals() ReferencePerson other = o as ReferencePerson; return other != null     && this.GetType() == other.GetType()     && FirstName.Equals(other.FirstName)     && LastName.Equals(other.LastName);



So we have now written some of the core functionality in the Domain Model. In Figure 5-16, you can see how the developed Domain Model looks for the moment.

Figure 5-16. Implementation of the Domain Model so far


OK, I think that will do for now and we need a break. The break will also mean a change. When we get back to refining the Domain Model in later chapters, I won't use such a TDD-ish way of describing all the tiny design decisions as we go. It will be a more condensed description.

But let's end the chapter with a discussion about another style of API.




Applying Domain-Driven Design and Patterns(c) With Examples in C# and  .NET
Applying Domain-Driven Design and Patterns: With Examples in C# and .NET
ISBN: 0321268202
EAN: 2147483647
Year: 2006
Pages: 179
Authors: Jimmy Nilsson

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net