This forum is now a read-only archive. All commenting, posting, registration services have been turned off. Those needing community support and/or wanting to ask questions should refer to the Tag/Forum map, and to http://spring.io/questions for a curated list of stackoverflow tags that Pivotal engineers, and the community, monitor.

But since good practice is reusing domain objects in UI layer, thus avoiding DTOs for that, that means someone in UI layer could easily call this Employee.fire() method in that layer, which is dangerous since it is out of transaction?

I think you have to make a choose:

1. anemic model + domain model in view
2. smart domain model + dto's

1.
---
So or you work with the anemic model, in that case you will not have any problems using the domain objects in the view. We are working this way now (not by choice). And I have some issues with that:

- We have implemented our persistence using Hibernate but using lazy initialization and the domain object in the view sometimes causes extra work not to get a lazyInitException.
- Most of the time data that should be showed on the view can be represented by the domain object. But there are cases in which we like to show a list of domain objects on the view ... BUT some domain object fields should be replaced by another value under certain conditions ... we cannot simply modify the particular domain object field that needs to be shown because with the next Hibernate flush Hibernate thinks the domain object has changed and it will be persisted. So for those cases we still need dto's.
- When you start putting logic into your anemic model... suddely your view can access that logic and who nows what happens then

So... we have a second solution

2.
---
We could throw away the anemic model (which a prefer) and start to create well designed smart domain model. I would then let the domain model go as far as the controller, and it is the mvc controller's task to create a dto. Some thoughts:
- I agree that dto's need to be maintained, if your domain model changes, yout dto needs to change too.
- Perhaps a nice framework should be used to do the mapping or perhaps it can be done by hand... no experience in that.. but will give it a thought.
- No more Hibernate LazyInitException in my view when using dto's
- No more spooky object updates during a flush because someone has accidently modified something in the domaon object to show it as read only in the view
- you are sure that NO DOMAIN LOGIC can be called from the view! I would not like to go to projects where people put all kind of business logic into jsp tags causing not only unmaintainable code but mostly excessive use of database connections
- I think that is a nice role for the mvc controller, receive data from the service and map it to a view object.
- For those developers who only make layouts / views all day long and are not concerned about business logic that appears behind the scenes, those dto's ar emucg more clear to work with then a complex domain object grapgh in which he is not interested. (for example a view that needs data from 10 domain objects is probly for a gui designer harder to figure out than to give him a dto with just those 10 fields on it)

But I have to admit that I'm just a junior developer (3.5y experience) so I'm still in the learning process

But I think its harder for people who for example get right from school and need to start developing layered architecture and have to make GOOD domain models, after 3.5 years it is still hard ... but sometimes there is a little light at the end of the tunnel that keeps us going on

I think we are in need of more professionel people sharing there experience, people who have seen projects fail or succeed for certian reasons... that informations should be gathered on a site that keeps track of these things and give us good discussions ... so that when we start a new project we can learn from other peoples mistakes instead of reinventing the wheel and making the same mistake. Actually I expected more feedback from the Spring guru's on these forums. Or are tehy in the dark when we are talking about there anemic model approach ... because I think that is one of the Spring weaknesses for now.

But even in were I work now there is some people who like job protection just too much ... its a too bad ... software developemt is a dificult topic, the world would be a better place if we would all help each other out ... *whishfull thinking*

Comment

this is an interesting post and quite timely because i am currently reading Patterns of Enterprise Application Architecture (PEAA) by Martin Fowler.

The first chapter is about Layering so here's my take from it:

There is no one layering technique that works in all cases. I believe alot of difference stated in this post about where business logic goes is the choice between 2 particular patterns.

Transaction Script: This is where your service layer also handles your business logic with domain objects being quite simple (if you have them at all). The service methods implement use-cases in an almost one-to-one manner.

Domain model: This is where the service layer is very simple and acts more as a convienient API for the app and a place to demarcate transactions and enforce security. The business logic is all done pure oo-style in the domain objects.

The book says use either depending on your environment. The Transaction Script works well but will cause issues with more complex domains and you have to be disciplined about factoring out duplication. With simpler domains its easier to implement.

The domain model can be alot of work though. It also requires good OO knowledge, something Martin Fowler states "a significant minority of developers seem to be unable to make the shift (to pure OO thinking)". The mapping between rich domain models and the datasource can also become more complex.

I'm no expert by any means but thought that might be useful. I'm still grappling with where to put logic myself. Will keep monitoring this post!

Comment

I agree good OO is just hard work ... and you get easily temptated to write 'procedural' style code mostly because you are in an extreme deadline!

But we all know that good OO design comes from experience and in many projects I worked ofn the lead architects or project managers just hired junior developers to do code-monkey work. Not involving them in the "think thank" process will cause that they have to learn OO development by trial and error.

But we all know that most of the time speed of developments is required before quality ...

But that's off topic

No responding on your post ... for me terms like transaction script are new to me, so even the great guru's like to use UBIQUITOUS LANGUAGE

I think indeed it would ge nice to divide such discussion into small and medium / large projects. Onze size doesn't fit all but perhaps one particular size would fit small projects and another size would fit the other medium and large projects.

Perhaps we should start a new site dedicated to Spring architectural design (not impl details, not the 'i have an error') where use case problems are in detail explained, architectural designs are suggested for a certain problem and were we can have discussion. Other developers with problems can then read about real life solutions that worked or failed .... well this is ofcoarse utopia ... but a boy can dream can't he

Comment

- Most of the time data that should be showed on the view can be represented by the domain object. But there are cases in which we like to show a list of domain objects on the view ... BUT some domain object fields should be replaced by another value under certain conditions ... we cannot simply modify the particular domain object field that needs to be shown because with the next Hibernate flush Hibernate thinks the domain object has changed and it will be persisted. So for those cases we still need dto's.

Dunno if I understood you well, but maybe you need some better web framework. There are frequent situations when I have to present list of domain objects on my web page, and for eg. localize value of it's particular field. In Tapestry, during iteration, current domain object is injected back into page (java code), and you can perform any kind of logic on that particular object or field and render HTML results on the page. All logic is placed inside page java class. No need for page-specific DTO. This way you are not forced to prepare everything upfront befor rendering, since render flow goes back to page during iteration.
It was one of best features I encountered when I switched to Tapestry.

Originally posted by rebornspirit

- When you start putting logic into your anemic model... suddely your view can access that logic and who nows what happens then

Maybe it isn't so bad tradeoff if people who fully understand the architecture also develop UI layer, thus trhey know that touching some logic on domain object is dangerous.

Comment

Maybe it isn't so bad tradeoff if people who fully understand the architecture also develop UI layer, thus trhey know that touching some logic on domain object is dangerous.

Yes and no

Yes, if you work on a small non enterprise project.
No, if you work on enterprise projects with complex integration, many developers, long lifespan, multiple new developers over time. I would not like too see the end result of that. Given people access to business logic on the view is tricky, and should be monitored closely, especially risky when that logic can cause multiple database requests. Projects mostly don't have the time for zuch dedicated code reviews, so I prefer to use a view were no business logic can be implemented

Comment

The responsability of
Presentation Layer
Business Layer
Persistence Layer
Domain Layer
Is well explained there.

Important note is that the domain layer is a "cross-layer" layer (not just a layer on top of another layer).

Quote:
"The business layer should be responsible for the following:
* Handling application business logic and business validation
* Managing transactions
* Allowing interfaces for interaction with other layers
* Managing dependencies between business level objects
* Adding flexibility between the presentation and the persistence layer so they do not directly communicate with each other
* Exposing a context to the business layer from the presentation layer to obtain business services
* Managing implementations from the business logic to the persistence layer"

Quote:
"... The domain object layer consists of objects that represent real-world business objects such as an Order, OrderLineItem, Product, and so on ..."

Comment

That is what I meant with my previous post! Its VERY easy to explain a layered architecture using a hello world example just like in the link provided in the previous post.

BUT ... there is a BIG difference between a hello world and real life examples. Real life examples just are much more complicated with much more complicated dependencies and much much more difficult business logic.

So I think books like DDD are very interesting to read because he explains why he does something using real life enterprise problems ...

For example the article doesn't mention are warn you for the Anemic model, and that should be the key in the article. Does it mention where the domain related logic goes, does it mention were the domain related logic goes that had dependencies with other interfaces....

Anyways thanks for the article ... it proves that we should be elvolving in two kinds of article:
- hello world
- people who tell their story about there enterprise project

Comment

I want to add my own ideas about the subject of this post... sorry if my english isn't good

Originally posted by Alarmnummer

I think you mean a service layer when you say use-case layer. Service layer shouldn`t contain much logic and the service layer is the place to add transaction/security. If you need to combine different services to create a new piece of functionality, this new peace of functionality also is a service. And if those other 'lower' services only are called from 'higher' services, I think it is questionable if those lower services should be called service.

I agree with the higher & lower services approach.

I prefer the term "service" for the higher services (a facade that deals with transaction/security issues, one for each client of the application), and the term "manager" (or "controller" or "administrator") for those other lower services. The managers are derived from DDD concept of Modules. I think that Aggregates are the key...

My analysis follow this path:
. identify and demark boundaries of Aggregates
. each aggregate lead us to determine the necessity of a Manager to handle logic cohesive and internal to the aggregate (that can't be solved by domain objects itself)
. the Aggregate/Manager also determine the necessity of a Repository
. at this point, we have at hands a subset of domain objects with a repository and a manager, and a Module emerge...

So, Aggregates are good starting point to define lower services, repositories and modules. This approach not cover all cases, but is really useful to me.

I used to work with an analogous approach, and Eric's book give me a really useful insight to refine it and get this one.

I'm still learning and finding better ways to improve our process. But I think Spring framework + Hibernate + DDD can lead us to projects with clean and pure domain models put to work with POJOs.

Comment

In examples I almost never write access modifiers, but in most cases these methodes are public.

I take a different approach. In my domain objects I generally provide public getters, public setters if the property is not "state managed", and actual methods for modifying "state managed" properties, like fireEmployee(). Now if fireEmployee() should only be called as part of a transaction-controlled workflow, I use access modifiers to make it package protected. I put the services layer in the same package as the domain object. Sometimes we need state managed methods to be callable by other domain objects, like a BankAccount that has a changeBalance() method (because balance is "state managed") that accepts a Posting. Because Posting and BankAccount are different "aggregates" (as per DDD terminology - a very useful pattern in teaching people this stuff I find) we need an intermediate object for passing the Posting to the now-forced to be public BankAccount.changeBalance() method. So we create a posting.BalanceChangeRequest, providing a package protected constructor that accepts the Posting. The BankAccount.post() only accepts a BalanceChangeRequest. Thus you've effectively used access modifiers to extend package protection to the Posting package. I also use Hibernate field-level access, and overall it all works pretty nicely.

On the subject of reusing domain objects for DTOs and web form backing objects, I've found it not worth the hassle. Such form backing objects / DTOs can be created in seconds as they're just simple JavaBeans. It's more important to have a rich domain model that is infrastructure independent.

Comment

On the subject of reusing domain objects for DTOs and web form backing objects, I've found it not worth the hassle. Such form backing objects / DTOs can be created in seconds as they're just simple JavaBeans. It's more important to have a rich domain model that is infrastructure independent.

Hear, hear! I agree 100%. I'm glad that a member of the Spring team is expressing this opinion. I thought that reusing your domain objects in the web tier was being pushed as a Spring best practice.

Comment

On the subject of reusing domain objects for DTOs and web form backing objects, I've found it not worth the hassle. Such form backing objects / DTOs can be created in seconds as they're just simple JavaBeans. It's more important to have a rich domain model that is infrastructure independent.

I agree with this statement as well, except I certainly don't think it's a best practice to always create DTOs for web form backing objects.

The ability to use a domain object to back a web form is one of the reasons I love Spring. But probably what I love more is that I have the choice to do it. With Struts I don't have that choice.

Comment

Interesting discussion and in line with my thoughts concerning the layered approach.

One thing I am (repeatedly) running up against is the mix of domain Objects and database mapping (objects).

Let me explain:

Far too often I see the approach that apps are built from the database up, whereby the Objects used to map to tables are used as domain objects. Although this may be appropriate in some cases where the database is normalised to the extent that it mirrors the actual domain model, in many circumstances it's not appropriate. Furthermore these *domain* objects are often without behaviour whereby they resemble DTO's more than actual domain objects.

I recently posted a question releating to the use of OpenSession (hibernate) in view layer and whether this was good practise? Again using lazy-read limits overhead the idea of always throwing hibernate objects into my templates doesn't feel right.

Comment

A project I'm working on now is showing bad signs of using domain objects in the web layer, let me explain.

We are using hibernate with most of the relationships defined as lazy which causes sometimes LazyInitExceptions in the web layer.
Also be aware of the Hibernate dirty check, I've seen too many developers that need to shown some domain obejt data on the screen, but in a certain case certain field of the domain object should have a different value to be shown on the screen. So they change the domain object to show the correct data on the screen (but ofcoarse this data should NOT be persisted). What happens a few steps later is that when Hibernate is flushing its session, its seeing that domaoin object as changed and it will be persisted.

So I agree that creating DTO's is a small effort but can help avoid multiple problems.

Question:
In a layered architecture, where do you create the dto's, for example when I have the following layer

Comment

shown on the screen. So they change the domain object to show the correct data on the screen (but ofcoarse this data should NOT be persisted). What happens a few steps later is that when Hibernate is flushing its session, its seeing that domaoin object as changed and it will be persisted.

That's just a horrible practice. If you need different values, then you introduce a DTO specific to the view. It's not a fault of Hibernate or the layering that the developers are changing values on your domain objects for the view.

Being able to move your domain objects around layers is a good thing, I believe. At least you have the choice to do it.