Dave Gladfelter has written a great question which I think a lot of people may be asking an therefore I am sharing the letter with the answers here…
Misko,Thanks for all your interesting posts on testability. I’ve been using DI and other techniques for some time for both testability and for maintainability and readability, but you’ve helped me understand some subtleties that I think will really help me write better code.I have a question about your distinction between “newable”, value classes and “injectable” or “service” classes.
Domain-Driven_Design by Eric Evans divides classes/objects into basically 3 categories, SERVICE objects, ENTITY objects and VALUE OBJECTS. VALUE OBJECTS are leaf classes like string classes and are obviously “newable”. SERVICES represent external infrastructure, they don’t model domain state, and they tend to be singletons. This makes them very similar to injectable objects. My main concern is with ENTITY objects. ENTITY objects in Eric’s methodology represent domain concepts that have specific lifetimes and identity. Eric is primarily focused on enterprise/database style applications where the primary concern is data integrity, so the concept of the ENTITY is key to his modeling technique.
The domains I’m working in at present are more functional / operational and aren’t concerned with identity, so I haven’t had an opportunity to put Eric’s methodology through the wringer yet to see what leaks out. After reading your articles I am now confused about how to fit ENTITY’s into the compelling design-for-test methodology you’re advocating.In your post “Writing Testable Code”, you say that a CreditCard class would tend to be a value object. In Eric Evan’s methodology, I would think it would be an ENTITY. I get the impression you advocate using value objects to hold domain data. This would make maintaining domain-dictated identity and lifetimes hard, since value objects are newable, often copyable, and generally not too concerned with lifetime or identity.
I get the impression you are okay with treating domain data as dumb data which service objects manipulate based on the application domain logic. In my mind, this creates an impedance mismatch between the object hierarchy and the domain under modeling. I’ve always thought it a good rule of thumb to place an operation on the class whose state is most queried/modified by the operation. In the case of processing a credit card transaction, it would be the credit card that is most affected by the transaction, not the credit card transaction processor service, and it would therefore be natural to place the operation on the credit card object. The card would still need to collaborate with such a service for aspect-oriented binding for services such as fraud prevention, but it would be the credit card’s responsibility to form the messages and operations that comprise a credit card transaction and to pass them to the appropriate players.
So, if I understand Eric’s approach properly and if he were trying to design for testability as well, I think he would advocate creating the credit card with a factory that would tie it to whatever services its various methods would need, and internal fields would be set during construction-time in the factory. The credit card would then use internal logic to determine what messages to send to the services to respond to application requests (Charge transaction, generate monthly late notice batch script, etc.)
If I understand your methodology, there would be several global credit card servicing objects with the business logic for the various operations, and the application would pass dumb value objects to those services as needed to fulfill requests.

Now, imagine one logical credit card operation required several orthogonal services to complete. Where would the business logic for that operation live? Would there be yet another service object responsible for coordinating subordinate service objects? What if one of the operations failed and the transaction needs to be rolled back. Who is responsible for coordinating this? Following Eric Evan’s methodology, the credit card would have all the information and logic needed to keep track of these higher-level concerns and would use the services as needed to create a valid application state even in the face of failures (the strong exception guarantee.) The credit card would not allow multiple simultaneous operations to create a race condition in multithreaded environments because it would be simple to add locking to the operations on the credit card class. In the test-driven model you describe, who would be responsible for detecting multiple simultaneous operations on the same card? If a service had to do it, then it would have to maintain internal state corresponding to all the active credit cards in the system to detect such conditions, which would be duplicative and would decrease data coherence in the system. You couldn’t put locking on the value-object-CreditCard class because it could have been copied (or deserialized multiple times) and therefore there would be no connection between the domain concept of serialization of transactions and the behavior of multiple credit card value objects with their own mutexes.
Are you familiar with this book? Do you see its design methodology as being compatible with design for testability? If so, how do you map the concepts in the two methodologies?Thanks,
Dave Gladfelter
Hi Misko,Sorry in advance for another long message. There aren’t any questions in it, and it is purely for your benefit, so feel free to read it whenever or never. I’ve been thinking about your comments and I reviewed some key sections of Evan’s book. I think there is not as much of a conflict as I thought. It is remarkable to me that the testable design methodology and the domain-driven design methodology are so compatible since they serve somewhat differing goals.
Anyway, I think I got hung up on “newable” as meaning “value object”. Entities need to be aware of their external, long-lived identities, but I think it is okay for the purposes of testability to make them newable. I think it would be bad for anyone other than a “repository” (Eric’s term for a persistent-storage-backed factory) to create a credit card object. Except during testing!
![]()
Also, Eric does anticipate that some services will peform purely domain operations. He agrees with you that keeping the set of operations on entities relatively uncluttered is crucial. Some domain operations are simply defined by a set of procedural business rules, and they belong in a stateless service.
I was initially confused at how newable entities would get re-serialized. At first, it seemed to me, since one doesn’t want (usually domain-state-free) services holding references to domain objects, and one doesn’t want domain objects holding references to services, that the only way to commit a transaction would be to have a method call that spans every transaction.
If an entity becomes unreachable from all threads in the process, then it will be unable to commit because it will not have access to its repository and there is no other object that can give it access to the repository, since no object has a reference to it other than the GC. This means that for a testable, domain-driven system, either:
1. All “write” operations need to occur within the context of at least one, continuous thread of execution.
or:
2. There must be some injectable service that needs to hold references to domain objects that are in-use.The first choice is not scalable and the second choice violates the literal definition of Eric Evan’s definition of a SERVICE (“A SERVICE is an operation offered as an interface that stands alone in the model, without encapsulating state, as ENTITIES and VALUE OBJECTS do.”). However, since moving transaction state from the stack to the heap is arguably just a change in execution strategy for performance reasons, I guess I could argue that the spirit of Evan’s methodology is not violated because a service that holds suspended / waiting transactions could arguably be said to simply be executing those transactions temporarily off-thread. Modern OO libraries even have such services pre-defined for just this purpose.
Anyway, thanks for your help, After hearing from you and thinking a bit more about this, I think the two techniques actually match up incredibly well. I do recommend the book if you get a chance, and I would look forward to reading about your thoughts on it in your blog posts.
Thanks,
Dave Gladfelter
5 responses so far ↓
Miško,This is a very interesting topic, which I was raising in my head ever since I read Martin Fowler’s post about anemic domain models (http://technorati.com/search/http://martinfowler.com/bliki/AnemicDomainModel.html) – this got me into DDD area, so I started reading Eric’s book (I’m halfway through it). What’s your opinion about anemic domain models? BTW I’m not sure relying on a specific technology (like Hibernate) helps the discussion. I come from the .NET sphere and I (usually) do not use NHibernate for DB persistence. But I still want to be able to understand the implications of using either Eric’s DDD approach or some alternatives.
igorbrejc.net » Fresh Catch For March 17th // Mar 17, 2009 at 4:04 am
[...] Design for Testability and “Domain-Driven Design” [...]
@Igor, After reading http://martinfowler.com/bliki/AnemicDomainModel.html I agree with Fowler, your objects should have appropriate behavior on them. As he puts it “The logic that should be in a domain object is domain logic – validations, calculations, business rules – whatever you like to call it.” The point I am trying to make is that it is not where the behavior is, but rather how this behavior gets a hold of its collaborators. What if your DomainModel is an Invoice and the calculation behavior need to get a hold of TaxTable to do the job. How should the Invoice get a hold of TaxTable? Here my point is that the TaxTable should not be a field of DomainModel, therefor TaxTable can not be constructor injected.
@Miško, I guess it depends on the nature of the behavior (and the domain it tries to describe) – sometimes it is appropriate to put that kind of domain logic into an Invoice object. Sometimes a separate service or strategy pattern is more suitable. As for your reservations about having non-persistable fields, I would say the best way would be to hide the domain from the persistance technology (like Hibernate) through some kind of factories and repositories. Then you wouldn’t have to worry how these fields get filled (at least not from the domain point of view).In the case of invoicing (of which I’m not an expert): maybe a ITaxation service which would accept Invoices as arguments in the Tax method would be a solution? In that case an Invoice would not care about the tax table in the first place.
Misko, I really enjoy your articles. I have learned a lot. This post deals with some questions that I had thought a small, but complete sample app would be very helpful to clarify. Any interest in providing one?
Leave a Comment