Saturday, July 11, 2009

Naked objects, DDD and the user interface

The SeparatedPresentation pattern is used to abstract the user interface from the domain model of an application. But it isn't more useful to enrich the user with a view of the domain itself?
The MVC pattern is all about separating the presentation of data. The major frameworks like Zend Framework and Rails are built to take advantage of an MVC stack, which means write your models, controllers and views.
Tipically we have a Post model with a PostController class that governs the operations that can be performed on the model and which views to show.
But there's more than MVC in the world.
What I'm talking about is Naked Objects pattern, that is currently implemented in the Java and .Net world by a framework with the same name. This pattern can be the next paradigm shift in development: in short, the V and C from MVC are completely generic and are built from the M part, the model classes. Also the infrastructure part, like database persistence of entities, are taken care by the framework that includes an Orm in its libraries.
Let's discuss the advantages of this approach:
  • there's no mapping between concepts, as the user interface is automatically created on-the-fly or generated and the user gains insight on the model (and thus on the domain). A driver aware of the fact that there is an engine will use the accelerator at its best. This helps an Ubiquitous Language to take shape.
  • there's no views and controllers to write, obviously.
  • there's no infrastructure coupling, also obviously if we exclude the annotations or xml metadata needed to make Hibernate or another Orm work. ActiveRecord is a reminescence of the past.
  • there's no logic in the controllers: they are automatically generate and delegates to the model. Fat model, skinny controller is achieved by force.
  • the domain model will be built without caring much of the other parts because it is the only thing to write. This allows a DDD approach, and the only attention is to conform to the conventions of the framework.
  • no more repeated validation on the ui: it is simply delegated to the model, where it should reside.
  • if the generated user interface does not satisfy you, what remains to you is a powerful and complete domain model that can be used to write an MVC application (thus using naked objects pattern only to prototype).
There are also issues of giving a complete user interface that cannot be edited by hand: this is not scaffolding. In the next posts I will talk about my journey in learning to use Naked Objects framework for Java, which is distributed as open source software.

9 comments:

Richard Pawson said...

Nice summary of Naked Objecta pattern.

Developer Dude said...

I can see the value of a bare presentation of domain objects for certain venues/apps or parts of apps. I have seen/worked on a variation of this for one app where the view was controlled by the user such that they could define a query and projection, then edit/view the results in a spreadsheet format. This worked well for one type of 'big picture' viewing with detail of the data, and for mass editing/entering of the data.

But for most enterprise apps the generated approach would not work without some type of framework (maybe by annotation) which controlled the entry/validation of the data such that bad data was not allowed. Typical UI best practices indicate intimate knowledge of constraints and dependencies within the domain object to enable a user friendly approach to such validation. For example, only enabling one field in the UI when it depends on another value in the domain object.

Then there is the idea of a mixed view of more than one domain object at a time, presented as one view, which is quite common.

Another common need is the ability to hide portions of the domain objects/model from the user because it would confuse them given their use case.

From the Wikipedia article: "1. All business logic should be encapsulated onto the domain objects."

If this means that business logic is *IN* the domain object, then I have to disagree. I have gone the opposite direction: bare bones POJOs/data objects/property value objects, then implement business logic that operates on these POJOs. Not even so much as property change listeners - just setters/getters (and I am hoping for even more bare bones property support in Java 7 or 8 where setter/getter methods are optional for beans).

The business logic can change quite a bit depending on the context (for example, the server side logic v. the client logic).

FWIW

Giorgio said...

There is work on the NO Java framework that overcome some of these issues: disabling fields, validating and hiding them basing on context is performed by an implicit interface of the "beans".
I agree on the fact that not all the logic should be strictly encapsulated in a bean object, but the Naked Objects pattern only says that it should be on an object that is in the domain layer (since the other layers are generic). That's why we have repositories, because an object should not persist itself, and services, such as it does not have unnecessary coupling to infrastructure. There's not only beans in the domain model.
But keep in mind that some of the logic should be in the object, otherwise you're duplicating it in every context where you use that bean, and it is more a procedural approach than an object-oriented one. Imho only the logic that does not fit in an entity should be put in a service; and the service is by the way part of the domain.

Developer Dude said...

Giorgio:

Well, business logic outside of a domain object (I am assuming we are talking about beans/POJOs here - that are abstractions of domain concepts, like an address, or a person (employee, client, etc.) doesn't have to be duplicated because of a different context. No more so than if it was inside the domain object.

For example, you could have a validator for a bean. You might have a different validator for the client than you do for the server, or for a different application. The common validation logic would be in the base validator and only that which changes would be in a specific subclass implementation. Dependency injection (like Spring/etc.) makes this very easy.

In short, just because the business rule logic is outside of the domain object doesn't mean it can't be reused.

As for UI rules/etc., I have done some work where I used annotations on properties in beans to give hints to reusable fields on how to constrain user entry - and this works well for individual fields, but I have not tried this for dependencies between different properties - some of which are in different objects and which can change at runtime depending on the context (the type of view itself, the user [rights, preferences, etc.], the application).

IMO, this business logic is what the code outside of the domain object is all about - it is the workflow that operates on the data. The domain object itself only contains that which is 'constant' and applicable for all contexts - which if often only the data types and names for the properties.

So, I guess I remain unconvinced. My domain objects (the POJOs at least), will consist of getters/setters, an overriding implementation of equals()/hashCode() (extremely important to get right for collections) and toString(), clone() (useful for UIs to keep temp copies of the object for editing) and maybe some constructors (usually not since they are almost always created from a datastore or UI).

For me, services, such as persistence, validation, input (from XML, CSV), output (to a different temporary format like XML), and yes views, are what get the work. And the domain object doesn't need to know about those services - indeed it shouldn't.

Maybe I am misunderstanding? Or maybe I am using a different concept for the idea of a domain object?

As a dev who has a lot more UI experience than server side experience, I know that the UI is user driven, not model driven. The workflow of the user, and the business rules of their domain, are what drives how the UI should appear and flow, from validation, to dependencies, to tab order, to what properties need to be shown (or not shown) - these are all context sensitive - a context that is at least partly or wholly outside the domain model itself.

Generic views that can be created at runtime from a domain object (and/or be configured by the user at runtime) definitely have value for certain workflows, and yes, high re-usability - but for other workflows they may be wholly inappropriate.

As for encapsulating business logic into domain objects - no. I am totally unconvinced. Indeed, to me, it begins to smell of a God Object. BTDT.

Giorgio said...

Let me argue a moment. :)
"For me, services, such as persistence, validation, input (from XML, CSV), output (to a different temporary format like XML), and yes views, are what get the work. And the domain object doesn't need to know about those services - indeed it shouldn't."
Certainly an entity object (like a bean) should not know about persistence and input/output formats. Persistence is an infrastructure concern, while input and output formats should taken care by the *generic* presentation layer. But validation (at least the part with immutable rules like what is a string and what is a number) can belong to the entity. If it does not, it could be an instance of Anemic Domain Model:
http://en.wikipedia.org/wiki/Anemic_Domain_Model
where you lose encapsulation: the bean becomes not an object but a plain old structure without business methods (procedural programming). Not all the logic goes in an entity, there are also services, but the cohesion of the domain model is largely improved by putting the basic logic in the bean where it belongs. Obviously if I need to output an xml representation of an object I wouldn't put this in a bean, I would write a service.
"As a dev who has a lot more UI experience than server side experience, I know that the UI is user driven, not model driven."
The point of the Naked Objects pattern is to present the domain model to the user, without translation, for empowering him to understand the application at its best. I wrote another post on issues on this pattern:
http://giorgiosironi.blogspot.com/2009/07/look-at-technical-question-on-naked.html

Developer Dude said...

Exactly. It *is* an instance of the 'Anemic' domain model, and my argument is that in my experience this is preferable from the POV of code flexibility. The reason I argue this is because I assert that the domain object itself gets overly complex when it needs to know about every context it is used in.

A very simple example was when I made the mistake of adding property change support to a lot of domain objects to help support their use in a Swing UI. What I should have done was use something like Swing to provide a proxy wrapper for the domain object that implemented property change support using AOP.

The problem was when the domain object was used outside of the context of the UI (for example, on the server) where the property change support had no meaning and confused coders who wondered what this code did (in every setter/getter) and whether it was the source of some problem they were trying to debug. It wasn't the source of their problems, but it was noise in the code.

I have seen examples of this many times - bloated domain objects that try to handle every context they are used in. They become confusing and eventually (if not instantly) unmanageable.

As for having the user see and use the domain model unvarnished, I assert that the use cases should drive the UI, not the other way around. In some use cases giving the user a generic property sheet or spreadsheet type UI can be useful to them, but no, I don't believe that is the common use case for most business workflows. One size does not fit all.

I guess we are going to have to agree to disagree on these issues. I can see some of the benefits, but I don't necessarily agree about the philosophy of where biz logic is placed and the problems with the 'anemic' model. As I said, I have already been down the road of bloated domain objects and I didn't like what I saw. I can't think of an instance where the domain objects wouldn't become bloated once you go much beyond the minimum needed (setters/getters/equals/hashcode).

A compromise might be to use AOP to wrap the domain object on a per context basis, but IMO, even that should be kept minimal.

Giorgio said...

A possible solution to the context problem is to embrace the BoundedContext approach and partition the model to cover the various environment where it will be used. It is best described as having more than one model, that can share the same backend (usually a database).
I think that some logic is intrisic in every domain class - otherwise why having one at all? A C-like structure does a better job. In the Swing example the property change approach implemented as a wrapper is best, because it is not intrinsic to the object itself, while there are business rules that says how it should *behave* and to ensure that it is always valid. That's for instance why we have Aggregate Roots in DDD: to ensure the validity of a subset of the object graph.
My example is an Invoice object with various rows: a particular behavior is to have a read-only field 'total' that should be calculated as the sum of the total of its InvoiceRow objects; Invoice is the root of this aggregate. Burying the algorithm in the Invoice class for the sake of cohesion ensures that it is always calculated correctly. If fields like taxes and discounts are added on the Invoice class the algorithm is right there to modify.
Having an external class will force to expose a public setTotal() method which could be used to do wrong things.

Anonymous said...

"In the next posts I will talk about my journey in learning to use Naked Objects framework for Java" - I'd love to see this post! I couldn't really find it among the posts tagged as 'Naked Objects'.

Giorgio said...

I have keeping using Naked Objects applications to study the web interface to duplicate in my project, NakedPhp. In January I'll try to talk more about that while returning to regular posting.

ShareThis