Hi thyrell,
After grabbing a copy of "Domain Driven Design" and reading a bit I'm now back to fully integrating the User into the domain model.
This is a great book. Keep an eye for the bounded context. If you carefully watch it, you will see this pattern to appear nearly everywhere and on every level - projects/modules/packages/types/methods etc.
1. Is it fine to do so ? Wink
Sounds good. Watch for any dependency cycles in the type/class hierarchy (especialy in the type (interface) hierarchy). Also if the unit-tests are complicated, you know there is some sort of a problem. So if you extend your domain layer, just watch the unit-tests, they will tell you when you start to have an issue... .
2. Using the model directly in the web tier. Good or evil. I read pros and cons, cons mostly because it's more work in sense of time to invest writing DTOs. I'm interested in the best solution of quality/abstraction/design. So good or evil?
It depends. It matters what you really want to do with your model objects. As long as you use them for read only access, it is mostly an easy way to use them in a presentation layer (especially in a light weight presentation layer)
But if things get more and more complicated or you have co-developers developing the presentation layer on their on, you might want to go for some sort of protection. Protection comes here in form of a more strict separation of the presentation and the domain layers. If you need such a separation depends on the size of the projects and the number of teams, I guess.
I have seen such a separation only when there was a complex client application involved. For the client <--> server communication there is always some sort of strict separation and so this can be used by the domain layer<--> presentation layer communication as well.
3. If DTOs are used, how are they handeled? I mean do i pass them from the web-tier to the service or do i pass them to the model classes.
I don't like to use DTOs (or Data Objects - it doesn't matter for what purpose). If you analyse the scenarios when using DTOs, it often comes down, that these DTOs are only used to formulate a language (inter-module language). There are other ways to formulate a good language. Also there is a reason why we usally don't see the words of a page as being objects - (except when modelling the structure of a page, but this is a totally different task).
Other forms of formulating a inter-module language is by using special service interfaces or a special communication format (xml etc.). But DTOs often appear to be the easiest thing to start with, so it isn't that bad to go with DTOs until enough is learned about the certain inter-modul communication requirements and sometimes DTOs get never replaced... .
But yet again this depends and there are these nasty non-functional requirements, like performance and memory consumption or time to market etc, which will demand a solution that isn't ideal in terms of design or simplicity.
4. What about DAO access in model classes. There's a thread where a hibernate interceptor injects dao stuff in the model objects that then again use it to look up things. It feels not very good to me, since the service should do those things.
What is a model class for you? For example implementing a repository or a registry may be also part of the domain model. Check out the dependency graph of all domain types (classes/interfaces) and if there is a cycle you know you have a problem. But there are times a DAO needs to know more about the domain itself. I found that these logical cycles (DAO calles Domain Model Objects) is simply an expression that you don't have a DAO layer, but have several one supporting different parts of the Domain Model (modularization).
Also I think there are many possiblities to avoid such 'logical cycles' by using the strategy pattern or stubs or whatever. But I wouldn't consider it to be such harmful.
5. The term Business Object seems to be used in different meanings. What is a business object? The service or a model enity class?
Normally you can describe the task of an application using a certain language (or a certain model of thinking). For example, if you go for a billing application you may end up using some words like Bill, Customer, CreditCard etc. Such words stand for different concepts of thinking and there is a reason why there are special languages for special domains (physic-scientists may use other terms than therapists when speaking about the same thing).
So we may end with such a 'definition': A business object is an object that takes part in a business process. The sum of the required (necessary) business processes may fully describe the problem domain the application applies to.
This is how I have learned it, but there may be other distinction and if you speak about a business layer it may get a different meaning, so I am not sure about this.
6. When I'm invoking business strategies on model objects should i do this via itermediate classes like:
Code:
scs = new ShippingCalculationStrategy()
scs.setDomestic(true);
scs.setExpressShipping(true);
user.calculateShipping(scs)
or is this besser:
Code:
user.calculateShippingDomestic();
I tend to favour the first one.
By removing all the business semantic (generalize the code snippet), I end up with this:
Code:
strategy=new Strategy()
strategy.setAttribute1(true);
strategy.setAttribute2(true);
object.calculateUsingStrategy(strategy)
This is about using the Strategy pattern, alright. The strategy pattern is for providing a plugable or interchangable mechanism to support a certain task of the main object.
Now lets remove the unnecessary implementation details:
Code:
strategy=new Strategy();
object.calculateUsingStrategy(strategy)
Now we apply something very useful. We simply go back a step in the evolutionary development of programming languages. We forget about OOP and do it totally procedural:
Code:
strategy=new Strategy();
object=new Object();
calculate(object,strategy);
(This is a fine trick, I often use when thinking about where to place responsibilities.)
Now we have two chances to put the above code snippet back into the OOP world:
object.calculate(strategy); vs strategy.calculate(object);
Now lets put back our semantics (specialize):
Code:
shippingCalculationStrategy.calculateShipping(user)
vs.
user.calculateShipping(strategy);
So the question is: Should a user be responsible to calculate shipping costs?
Another good rule of thumb is: Simple design reduces the knowledge needed to (fully) understand each of its components. (a good indicator are coupling metrics by the way).
Trying to remove the necessary special knowledge about shipping from from the ShippingCalculationStrategy doesn't make any sense here. So only the User is left to give it a try. And we are in luck, it works well with the User. Now we end up favouring this one (at least I end with it of cause ;-)) :
shippingCalculationStrategy.calculateShipping(user )
The typical question after such a restructuring/refactoring: If the strategy now has the responsibility to calculate the shipping itself, is the name-part 'strategy' still sufficient to describe the object? -> No. So we have to rename this type.
Since objects should be named by their functionality (what) instead of the way the functionality is achieved (how), we abstract the semantic of the name. -> calculationStrategy.calculate(object) -> A better name would be calculator.calculate(object) -> Now we specialize again -> shippingCalculator.calculateShipping(user).
So everything ends with having one or more shipping calculators and a user object knowing nothing about shipping after all. (also we solved a dependency cycle here I guess).
(Calculating the shipping cost may be now considered to be part of the business logic (business (sub)layer) rather than the domain model.)
Should this happen in the web-tier (client tier) or in the service.
What do you exactly mean by 'Should this happen in the web-tier' ?
7. Interfaces. I'm used to code most of my classes to interfaces. Should I do that with my domain model too (an i.e. things the strategy stuff like described above or DTOs). Intefaces for all model classes could end up in many many classes. I've created interfaces for entity model classes only, not for the value object (i.e. TimePeriod would not have an interface since it's only a value object (VO in terms of Evans)). Good practice.
I use interfaces for value objects, too. I mostly find it preferable to stick to the factory pattern - using mostly static factories in terms of the value objects. I also simply like to refer to abstract types rather than concrete implementations. But this is a habit and there are other schools of thinking out there :-).