My Photo

My Online Status

SW Process

Best Books on Design and Development

« Domain Objects as Data Transfer Objects? | Main | The Smallest API for Average Developers »

Protecting the Domain Model

Condpic1In my previous blog post I found several reasons for using DTOs instead of using the domain model classes as transfer objects. I received some feedback and several people were saying that DTOs are a thing of the past and should be now considered an anti-pattern.

My main argument in favor of using DTOs was that they provide protection for the domain model and facilitate easier refactoring. The domain model needs to be protected from getting polluted with presentation related concerns. Refactoring would be easier if you could change the domain model classes without the client code being affected. This would be possible if the client was not dependent on the domain model classes directly. When using DTOs the dependency is not direct, the DTO classes provide some isolation. Effective refactoring is necessary in order to achieve a working domain model and not end up with an anemic one.

In this post I will discuss some other ways to protect the domain model and to facilitate effective refactoring. This time I am assuming that domain model classes are exposed to clients and DTOs are not used.

Avoid Anemic Setters

I learned the term "anemic setter" from the Spring forum's architecture discussions. An anemic setter is a setter that uses a primitive (or a String or some other JDK type) as it's parameter type and assigns the parameter value value to the domain object's field. In some cases anemic setters should be avoided. For example if your Customer object stores an address it probably should not expose setters for individually assigning the street address, the zip code and the country. Instead the address should be modeled as a separate Address object and the Customer should have a setter that takes the Address as a parameter. Or alternatively, the Address could be specified when the Customer is created. The latter is probably better if every Customer must have a valid Address. The Address class must also enforce that all it's component values are provided when instances of it are created.

This arrangement guarantees that the Customer state is never corrupted. A buggy or malicious client is not able to assign a partial address consisting of, for example, only the zip code. The anemic setters design relies that all clients, in all situations, use all three different setters when storing or modifying addresses.

The lack of anemic setters places some challenges for the data binding solution. A primitive binding framework might require that all fields coming from the UI (HTTP request or a Swing form) must be stored using anemic setters.

Domain Logic Only

The domain model should contain only logic from the core domain. Presentation logic should never find it's way to the domain model classes. So what is the proper place for presentation related functionality then? Here are two options:

  • Create separate model classes (MVC models, form objects)

Unusable Methods with a Distributed Environment

I discussed unusable methods in my previous blog entry. I haven't figured out how to avoid them. AOP magic comes to my mind again here... Does anyone have suggestions?

Evolving the Architecture

My recipe for success follows here.

Start simple and use the domain model throughout the the system, including the presentation and other types of clients. This way you will be enjoying the benefits of the domain model everywhere. Your client code will appear to be speaking the domain specific language.

After this you need to keep your eyes open all the time. Look at your domain model:

  • Is it alive and rich with domain logic?
  • Has the domain logic leaked out of the domain model?
  • Has non-core functionality leaked into the domain model?
  • Is refactoring painful and hurting domain model evolution because you are  worrying about breaking hard-to-change client code?

If these kind of signs are visible, it is time to refactor. Maybe some additional UI specific helper classes or model classes are necessary to host the presentation logic that was leaked into the domain classes. Or maybe you even
need to introduce command classes (or DTOs) to isolate the domain model in some troubled area. You need to be alert all the time to be able to react quickly. Even better, you can refactor the architecture before adding anything that would lead to a problematic design.

TrackBack

TrackBack URL for this entry:
http://www.typepad.com/t/trackback/351993/2540827

Listed below are links to weblogs that reference Protecting the Domain Model:

Comments

I blogged on a conversation that Gregor Hohpe and I had about DTO and how it was a symptom of an anti-pattern. We both had different names but they said the same thing. Gregor called it false decoupling where as I called obfuscated couplings. The reason being.. you will have to change your DTOs when as you change the shape of your domain model or your DB as these things are tightly coupled. They need to be tightly coupled because you are exposing the internal state of your object to an external system. The fact that you use a DTO just adds another layer in the mix. It doesn't really fix the problem, just obfuscates it.

For unusable methods, I like to have interfaces which expose the methods that should be available and use that as the return type for methods getting the domain model object for presentation (for example). If you want to enforce this you can then transparently apply an AOP pointcut to create a dynamic proxy which wraps the object and only implements the interface. I've applied this pattern to protect methods like setId() which are on the domain object but not part of the interface I expose the the presentation layer.

I guess I don't understand why people are afraid to bring their domain object to the presentation tier. Aren't your domain objects modeled to represent real objects? Seems to me what you are doing is trying to write code to fix bad habits. Display logic should never be in your domain object. Your presentation tier shouldn't set the Id on an object (if this is your business rule). Seems like a lot of extra code and complexity to solve a problem that would be solved by a simple code review and some helper classes.

A couple of comments.

I would try to avoid setters on domain objects entirely and have methods that do something meaningful. For example, rather than Account.setBalance() have Account.debit() and Account.credit().

One variation on what Jason proposed is to implement interfaces using an adapter. Most of the methods of the adapter delegate to the domain object. But some of methods could return values that were precomputed by the business tier using the "unusable" methods.

Chris
----

Enterprise POJOs blog - http://chris-richardson.blog-city.com

Hello Anssi,

In my opinion, DTO's are worthwhile when you are using distributed objects and you want a coarse grained interface, thus decreasing the serialization and network overhead. I like to use DTO's when I have a huge list of parameters in a method, but I think it's a question of personal taste. Some people argue using DTO can simplify the methods signature, because if you need to add or remove a DTO attribute you don't need to modify your method signature. Furthermore, I think using Façades and ApplicationServices a good strategy to protect your Domain Model using DTO's iff you need to distribute your objects or agregate a huge list of method parameters.

Regards,
Rafael

Rafael,
If one needs a DTO to deal with a huge parameter list - it is sign that refactoring is needed.

Mark,

Are you saying you have never had to retrieve a pile of data from some sort of datastore and present it to a user? Just because 'one' needs to retrieve a large parameter list does not necessarily mean refactoring is required.

Also, I don't really see the problem (generally speaking) with exposing domain objects to the presentation layer as long as the granularity is a rough match. Unless of course you're using CMP, in which case you need DTO's.

Regards
Rob

Unusable Methods with a Distributed Environment possible solution....

What might be a solution to your problem would be to specify a simple security scheme for the domain objects where each forbidden method requires a key to be used. The key could be as simple as an Integer or String key initated on startup and distributed to all parts of the systems that are allowed to manipulate domain objects. By passing the key to all methods that you want to restrict the call scope of, you create a simple, flexible and extendible security scheme. Whenever someone tries to invoke the method without the key, a ForbiddenAccessException could be thrown.

NB, not security as in "hacker security" but as in "rigid structure security" preventing programmers from shooting themselves in the foot.


Downsides:
Slightly more complex domain models, although it would only be restricted to something like
if(!key.equals(unlockKey)).... else throw ForbiddenAccessException
for each method that needs protection. Of course you also need a "lock(String key)" method to be able to lock the object and possibly an "unlock(key)" method too.

No compile time check of security restrictions which also means no IDE or compiler support to prevent erraneous behaviour. Note that completely runtime based may also be a plus.


Upsides:
Very flexible, ranging from the simple:
- global distributed key where only selected methods are protected
to the complex:
- uniquely generated keys held by specific central objects for each newly created domain object where access to methods may not only be restricted method access but also on how the method is accessed, if parameters are within a specific range etc.

Locks can be set and released over time, rendering the object inaccessible at some point, partly accessible at others and completely open at a third point in time.

Locks can be set differently for different parts of the system with several keys specifying several security levels. Different security domains can therefore effectively be created with a possibly infinite number of levels for access and manipulation.

Comments?

The DTO choice (apart from considerations such as granularity, efficient bandwidth usage, etc) may also be influenced by decisions such as how your domain model is persisted.

If you map it to an RDB, using an O/R mapping tool, it is very likely that the domain model class instances you manipulate get polluted with O/R mapping framework classes - especially if you use things like lazy loading, which you should, for performance reasons. Toplink for example injects it's own collection classes in your domain objects in order to implement transparent lazy loading for 1N, NN relationships. Other frameworks may hand you byte code manipulated objects or dynamic proxies of your domain objects to achieve the same goal. Once you get such a polluted instance, you don't really want to transfer it to a distant client, for the simple reason that it depends on system resources that only exist on the app server, like ongoing transactions, data sources, units of work, even class definitions - because why would I put toplink.jar or hibernate.jar in my swing app's classpath, which is supposed to be a pure presentation layer? And even if I'd do so, calling getAddresses on my Person instance would call toplink's special collection instance which would try to use the app server's data source to load the addresses. The data source does't exist in my distant client so the call will definitely fail with a nasty exception. So, in this case, how do I transfer data to/from my remote client? There are not many choises apart from using DTOs which are guaranteed not to have unnecessary dependencies.

Of course there are architectures where DTOs are overkill. For example, think of a fully self contained web app which talks directly to the databse using O/R mapping. I don't need to transfer object to remote locations, there are no classpath problems, so why would I need DTOs? It would definitely be overkill.

regards,
Emil.

Rob! It is recommended that large parameter list should be refactored. After that we have DTO and I would say we have a better way. I just posted my thoughts on
http://dkrukovsky.blogspot.com/

Denis Krukovsky
http://dotuseful.sourceforge.net/

Denis,

I read your blog entry but I fail to see your point.
What is this "alternative" you're talking about?
You either transfer the domain objects or some other
representation of them (DTOs). Do you have any other choice ? (Besides rowsets ofcourse)

Cristian! I suggest to review the need for "transfer". In many cases there is no real need for organizing a transfer. Find object who demands the information. Find object which holds the information. While in your demanding object, get the information from the direct source.

This is an alternative. Thanks for your comment. I updated my blog entry. If you know how to make my post more understandable - please suggest.


Denis Krukovsky
http://dotuseful.sourceforge.net/
http://dkrukovsky.blogspot.com/

Kirk is absolutely correct. DTOs encourage coupling across multiple layers of your system. This can be hard to understand for MVC advocates since the very seperation they desire tends to create couplings and rigid applications. Trying to protect the domian model usually implies procedural thinking, i.e. trying to seperate your data from how it used. Data from a database is not an object. If you try to make an object that is just this data, without any business logic (and that includes presentation logic!) then you should be using a non-object oriented language. The author makes a good point in considering : "Is refactoring painful and hurting domain model evolution because you are worrying about breaking hard-to-change client code?" However the author needs to consider what happens when the domain model itself changes.

http://tsoa.info a [url=http://tsoa.info]a[/url]
http://trha.info b [url=http://trha.info]b[/url]
http://trpa.info c [url=http://trpa.info]c[/url]
http://biia.info d [url=http://biia.info]d[/url]
http://dbta.info f [url=http://dbta.info]f[/url]
http://dbra.info e [url=http://dbra.info]e[/url]
http://cbla.info g [url=http://cbla.info]g[/url]
http://ibka.info h [url=http://ibka.info]h[/url]

http://caz678.awardspace.co.uk/casino-com-site/ casino [url=http://caz678.awardspace.co.uk/casino-com-site/]casino[/url]
http://caz678.awardspace.co.uk/casino-com-site/casino-com-site-that.html game [url=http://caz678.awardspace.co.uk/casino-com-site/casino-com-site-that.html]game[/url]
http://caz678.awardspace.co.uk/casino-com-site/casino-com-site-mississippi.html poker [url=http://caz678.awardspace.co.uk/casino-com-site/casino-com-site-mississippi.html]poker[/url]

http://caz678.awardspace.co.uk/casino-in-la casino-in-la [url=http://caz678.awardspace.co.uk/casino-in-la]casino-in-la[/url]
http://caz678.awardspace.co.uk/casino-in-la/casino-la-shreveport.html casino-la-shreveport [url=http://caz678.awardspace.co.uk/casino-in-la/casino-la-shreveport.html]casino-la-shreveport[/url]
http://caz678.awardspace.co.uk/casino-in-la/casino-la-posta.html casino-la [url=http://caz678.awardspace.co.uk/casino-in-la/casino-la-posta.html]casino-la[/url]
http://caz678.awardspace.co.uk/casino-in-la/casino-kinder-la.html casino-kinder [url=http://caz678.awardspace.co.uk/casino-in-la/casino-kinder-la.html]casino-kinder[/url]
[url=][/url]

hello world!

my name is murava! are you? http://www.benimblog.com/murava/


Stamps the postcards of auguries, the trades of Passover and a lot piu with generate and print ! 3d postcards links of what by if you smash in newsletter of auguries : regali natale. of the caprio many postcards phrases .. All data skin with virtual postcards its sluices human area children - http://auguri-natale.cartoline-natale-it.com/ - auguri natale. Then arrives the auguries of Been born them and the panettone is eaten . Segui the little and easiest instructions of the Tutor you will be able to send en
dured the auguries of good year with images and designs good New Year's Day augurs them .

hello world !! http://viagra.bloggcasting.com/

rosie@triad29.com

rosieponder@verizon.net

Not only do they try to rip you off, they send your email out and you get a ton of junk mail.

uezvyadnq neirst jspbcw cpzvdems iefco mpvjhtczq hcfzbj

Are you using one of our products and need to send reliable and timely emails? Having problems with your current mail sending / SMTP server?

With our new SMTP partner , you'll be able to get your emails out no matter what the circumstance. No more hassles with slow relay servers, ISP limits, or spam blacklists and feedback loops.
online roulette
blackjack
online video poker

Post a comment

If you have a TypeKey or TypePad account, please Sign In