views:

1081

answers:

11

One part of domain-driven design that there doesn't seem to be a lot of detail on, is how and why you should isolate your domain model from your interface. I'm trying to convince my colleagues that this is a good practice, but I don't seem to be making much headway...

They use domain entities where ever they please in the presentation and interface layers. When I argue to them that they should be using display models or DTOs to insulate the Domain layer from the interface layer, they counter that they don't see the business value in doing something like that, because now you have a UI object to maintain as well as the original domain object.

So I'm looking for some concrete reasons I can use to back this up. Specifically:

  1. Why should we not use domain objects in our presentation layer?
    (if the answer is the obvious one, 'decoupling', then please explain why this is important in this context)
  2. Should we use additional objects or constructs to isolate our domain objects from the interface?
+6  A: 

Quite simply, the reason is one of implementation and drift. Yes, your presentation layer needs to know about your business objects to be able to represent them properly. Yes, initially it looks like there is a lot of overlap between the implementation of the two types of objects. The problem is, as time goes on, things get added on both sides. Presentation changes, and the needs of the presentation layer evolve to include things that are completely independent of your business layer (color, for example). Meanwhile, your domain objects change over time, and if you don't have appropriate decoupling from your interface, you run the risk of screwing up your interface layer by making seemingly benign changes to your business objects.

Personally, I believe the best way to approach things is through the strictly enforced interface paradigm; that is, your business object layer exposes an interface that is the only way that it can be communicated with; no implementation details (i.e. domain objects) about the interface are exposed. Yes, this means that you have to implement your domain objects in two locations; your interface layer and in your BO layer. But that reimplementation, while it may initially seem like extra work, helps enforce the decoupling that will save TONS of work at some point in the future.

McWafflestix
Thanks for the great answer!
Mark Rogers
You're welcome; it's a good (and important) question. Kudos to you for asking it and not just bowing to peer pressure.
McWafflestix
What do you mean by "implement your domain objects in two locations?"
jlembke
This just seems silly to me. Why do the extra work now that MAY save work in the future? 9 times out of 10 you'll never need to need to make the change that would save "TONS" of work.
Jess
@LuckyLindy: 99 times out of 100 (actually more), wearing my seat belt isn't necessary to keep me from getting injured. However, in the one instance when I really need it, it will (likely) keep me from getting killed or badly injured. An ounce of prevention is worth a pound of cure. I suspect your opinion about this will change after you have more experience.
McWafflestix
+3  A: 

You do it for the same reason you keep SQL out of your ASP/JSP pages.

If you keep only one domain object, for use in the presentation AND domain layer, then that one object soon gets monolithic. It starts to include UI validation code, UI navigation code, and UI generation code. Then, you soon add all of the business layer methods on top of that. Now your business layer and UI are all mixed up, and all of them are messing around at the domain entity layer.

You want to reuse that nifty UI widget in another app? Well, You have to create a database with this name, these two schemas, and these 18 tables. You must also configure Hibernate and Spring ( or your frameworks of choice ) to do the business validation. Oh, you must also include these 85 other non-related classes because they are referenced in the business layer, which just happens to be in the same file.

digitaljoel
Thanks for the great answer! I'm sorry I couldn't choose two
Mark Rogers
Thanks. It's cool. McWafflestix had a great answer. This one hit home for me since I've spent the last week working on refactoring to introduce a business layer in some of our stuff.
digitaljoel
+1  A: 

We are using the same model in the server and on the ui. And it's a pain. We have to refactor it some day.

The problems are mainly because the domain model needs to be cut into smaller pieces to be able to serialize it without having the whole database referenced. This makes it harder to use on the server. Important links are missing. Some types are also not serializable and can't be sent to the client. For instance 'Type' or any generic class. They need to be non-generic and Type needs to be transferred as string. This generates extra properties for serialization, they are redundant and confusing.

Another problem is that the entities on the UI don't really fit. We are using databinding and many entities have lots of redundant properties only for ui purposes. Additionally there are many 'BrowsableAttribute' and others in the entity model. This is really bad.

At the end, I think it is just a matter of which way is easier. There might by projects where it just works fine and where is no need to write another DTO model.

Stefan Steinegger
If your going to use databinding run a linq query and bind to an anonymous type. This lets you flatten and change the heirarchy. You can also implement filtering and sorting very nicely with this.
JoshBerke
@Josh: Thanks for the advise. This might partially work. I'm not a GUI programmer myself and am not involved in GUI concepts much. The problem will be in cases where the data is manipulated and sent back to the server.
Stefan Steinegger
+3  A: 

It's about dependencies for the most part. The core functional structure of the organization has its own functional requirements, and the UI should enable people to modify and view the core; but the core itself should not be required to accommodate the UI. (If it needs to happen, it's usually an indication the core is not property designed.)

My accounting system has a structure and content (and data) that are supposed to model the operation of my company. That structure is real and exists regardless of what accounting software I use. (Inevitably a given software package contains structure and content for its own sake, but part of the challenge is minimizing this overhead.)

Basically a person has a job to do. The DDD should match the flow and content of the job. DDD is about making explicit all the jobs that need being done ad completely and independently as possible. Then the UI hopefully facilitates getting the job done as transparently as possible, as productively as possible.

Interfaces are about the inputs and views provided for the properly modeled and invariant functional core.

le dorfier
Thanks for your input, good answer
Mark Rogers
A: 

Perhaps you are not conceptualizing the UI layer in broad enough terms. Think in terms of multiple forms of response (web pages, voice response, printed letters etc) and in terms of multiple languages (English, French etc.).

Now suppose that the speech engine for the telephone call-in system runs on a completely different type of computer (Mac for example) from the computer that runs the website (Windows perhaps).

Of course it is easy to fall into the trap "Well in my company we only care about English, run our website on LAMP (Linux, Apache, MySQL and PHP) and everyone uses the same version of Firefox". But what about in 5 or 10 years?

JonnyBoats
A: 

The only sensible reason for adding additional mapping between generalized and domain specific semantics is that you have (access to) an existing body of code (and tools) that are based on a generalized (but mappable) semantics distinct from your domain semantics.

Domain driven designs work best when used in conjunction with an orthogonal set of functional domain frameworks (such as ORM, GUI, Workflow, etc.). Always remember that it is only in the outer layer adjacencies that domain semantics need to be exposed. Typically this is the front end (GUI) and persistent back-end (RDBM,ORM). Any effectively designed intervening layers can and should be domain invariant.

I have a clarification question on this answer: WHAT?????
HDave
+2  A: 

Dammit, I swear this said persistence.

Anyway, it's one more instance of the same thing: Parnas's law says a module should keep a secret, and the secret is a requirement that can change. (Bob Martin has a rule that's another version of this.) In a system like this, the presentation can change independently of the domain. Such as, for example, a company that maintains prices in Euros and uses French in the company offices, but wants to present prices in dollars with text in Mandarin. The domain is the same; the presentation can change. So, to minimize the brittleness of the system — that is, the number of things that must be changed to implement a change in requirements — you separate the concerns.

Charlie Martin
thanks for your input.
Mark Rogers
+6  A: 

I have struggled with this myself. There are cases where a DTO makes sense to use in presentaton. Let's say I want to show a drop down of Companies in my system and I need their id to bind the value to.

Well instead of loading a CompanyObject which might have references to subscriptions or who knows what else, I could send back a DTO with the name and id. This is a good use IMHO.

Now take another example. I have an object which represents an Estimate, this estimate might be made up labor, equipment etc, it might have lots of calculations that are defined by the user which take all these items and sum them up (Each estimate could be different with different types of calculations). Why should I have to model this object twice? Why can't I simply have my UI enumerate over the calculations and display them?

I generally do not use DTO's to isolate my domain layer from my UI. I do use them to isolate my domain layer from a boundary that is outside of my control. The idea that someone would put navigation information in their business object is ridiculous, don't contaminate your business object.

The idea that someone would put validation in their business object? Well I say that this is a good thing. Your UI should not have sole responsability to validate your business objects. Your business layer MUST do its own validation.

Why would you put UI generation code in a busienss object? In my case I have seperate objects which generates the UI code seperatley from the UI. I have sperate objects which render my business objects into Xml, the idea that you have to seperate your layers to prevent this type of contamination is so alien to me because why would you even put HTML generation code in a business object...

Edit As I think a little bit more, there are cases where UI information might belong in the domain layer. And this might cloud what you call a domain layer but I worked on a multi-tenant application, which had very different behavior both UI look and feel and functional workflow. Depending on various factors. In this case we had a domain model that represented the tenants and their configuration. Their configuration happened to include UI information (Label's for generic fields for example).

If I had to design my objects to make them persistable, should I also have to duplicate the objects? Keep in mind if you want to add a new field now you have two places to add it. Perhaps this raises another question if your using DDD, are all persisted entities domain objects? I know in my example they were.

JoshBerke
nice semi-counter-answer
Mark Rogers
+1  A: 

See also the section "Data propagation between layers" in the following, which I think presents compelling arguments:

http://galaxy.andromda.org/docs/andromda-documentation/andromda-getting-started-java/java/index.html

lumpynose
+4  A: 

I disagree.

I think the best way to go is to start with domain objects in your presentation layer UNTIL IT MAKES SENSE TO DO OTHERWISE.

Contrary to popular belief, "Domain Objects" and "Value Objects" can happily co-exist in the presentation layer. And this is the best way to do it - you get the benefit of both worlds, reduced duplication (and boilerplate code) with the domain objects; and the tailoring and conceptual simplification of using value objects across requests.

Using OpenSessionInView simplifies this too. Then the only time you have to think is when you need to re-attach a domain object to a new persistence context, and a LazyInitializationException will make it abundantly clear if you happen to forget.

Daniel Alexiuc
Thanks for your input, I see where your coming from. While I'm not saying that this isn't another of the infinite ways to create a successful project, it seems to run counter to the "Domain-Driven Design" style, which is for larger and more complex projects that are harder to maintain in the long run.
Mark Rogers
A solid, common sense answer.
HDave
+2  A: 

Your presentation may reference your domain layer, but there should be no binding directly from your ui to your domain objects. Domain objects are not intended for UI usage since they are often, if properly designed, based around behaviors and not data representations. There should be a mapping layer between the UI and the Domain. MVVM, or MVP, is a good pattern for this. If you try to directly bind your UI to the Domain, you will probalby create a lot of headache for yourself. They have two different purposes.

jlembke