Javier poses the question: “how many [CLR Objects] does it take to represent a Real World Object?” I have posted in about this in the past, but it’s an excellent question that throws a lot of folks. I also think I’ve refined my opinion on the question and it’s good to revisit these things every so often. The question made me think back to an old school commercial for Tootsie Pops that aired during Saturday morning cartoons:
In the commercial a boy approaches an owl, Mr. Owl to you, with a question: “how many licks does it take to get to the center of a Tootsie Pop?” Ever the empiricist, Mr. Owl engages in a short experiment. Loosing his discipline after three licks the owl bites into the candy’s chewy, pseudo-chocolate inner core. The owl licked thrice before chewing. He asserts, therefore, it takes but three bites to get to the center. The boy seems dissatisfied with the conclusion of Mr. Owl’s investigation worriedly observing that ”the world may never know.”
The number of objects you need to represent a real world entity can vary greatly depending on the needs and architecture (which should be driven by the needs) of your application. I’m still a believer in one entity probably isn’t enough. Let’s introduce an example. Say we have to represent Customer somewhere in the application.
My first question is what makes up the Customer? Likely they’ll have one or two address objects? Let’s say they have two, a shipping address and an office address. So far we’re up to “thu-ree” - as Mr. Owl says - objects. Customer in this sense is a composite or, in DDD terms, an aggregate root. So right we’ve got (potentially) an effective infinite number of “objects”. Let’s make “object” mean “type” or “class” going forward. If we recast the question as “how many types does it take to represent a real world object” we can come up with a finite number of associations be they many-to-one, many-to-many (association class), or one-to-many (collections). Still I like the idea of “Customer as boundary” that comes with the DDD notion of aggregate root.
So how do we get that Customer to our application layer? Generally speaking I look for an organizing principle (information architecture) centered on the main entities of the application. I like to group screens and actions in the UI around the entity. So I’d like to come up with a screen that lets you act on a list of Customers or open an individual customers, browse its data and take action on that instance of customer. Even though there’s a certain nakedness to these business objects I tend to favor creating DTOs or messages that represent the required slice of data. For example, I’d consider a list-like DTO of Customers that’s contains data that helps you find an individual Customer represented by a more jagged, higher resolution detail DTO. I also don’t invest too much time in factoring my DTOs for re-use, so I’m apt to create a DTO specific to the purpose at hand.
Sidebar: I use a base class and external DSL for data transfer objects and have them support data-binding. Read more about it. I know CSLA, for example, goes with a kind of single entity approach. Rocky calls it “mobile objects.” That is a customer is a customer is a customer. I don’t like this because I feel that it creates a lot of transformation code everywhere and I like to centralize this in a Service Layer. I also avoid loading my entity classes with responsibilities orthogonal to business logic such as data-binding support. Instead I favor a Service Layer peopled with Application Services. An Application Service is really a facade to the Model layer that brings infrastructure (sending an email) in to the mix with Domain artifacts: Entities, Repositories, Factories, and Services.
Now we’ve got all these messages that support a user interacting with the model of a “real world object” and we’ve got a number of MVP triads that ultimately construct these messages that work on the entity. I guess my answer is as many as it takes and it can take quite a few. The benefit of splitting a real world object into a number of tailor-made (for the layer) objects is that it preserves a layered architecture which benefits through partitioning and isolation. That’s a Byzantine way of saying layers make a code base easier to evolve/maintain.
If I had to break it down to for my current default architecture for smart clients that work over a firewall:
-
Customer (Aggregate Root Entity)
-
Address (Value Object)
-
CustomerRepository (Finds/Saves/Deletes Customers)
-
PreferredCustomerService (Gets a list of Orders for a Customer and determines if they’re standard, gold, or silver)
-
CustomerService (CRUDdy Application Service for Customers)
-
CustomerDetail MVP Triad
-
CustomerSearch MVP Triad
All of these items are required to represent the real-world customer given my architecture. Even if you go directly to model you still need to display stuff. Even if you’re not using MVP and are using Autonomous View, it’s still another object required to “represent” the real-world concept of customer. My preference is simply to let the concept of “Business Entity” flow through a layered architecture when it’s natural to the end user. In general I think it is a natural concept for a lot of entities. Adjusters talk about working with claims; underwriters write, renew, and terminate policies; project managers manage, well, projects…
Having this baseline set of patterns helps you avoid the trap Mr. Owl fell in to. Namely, patterns control how many licks, um, objects it takes to get to the center of a user story and at the heart business value. You don’t need to go nuts with an over-arching, prescriptive framework. Pick a few design patterns to start with and a framework will emerge over time as you suit immediate needs, ease frequent pain points, and address redundancy. I, personally, look for how entities are treated, look to them (initially) for an organizing principle of user experience, and find design patterns that mesh my findings with a good measure of maintainability and testability.