Hal and Jeff Discuss Domain Models
18 Mar 2005
Jeff: So, Hal, you were telling me about someone you talked to who recommended Fusebox if you don't want to use objects, and Mach-II if you do.
Hal: Yes--and I was surprised that another person in the conversation shared the idea that OO = Mach-II while Procedural = Fusebox.
Jeff: That certainly seems to be a prevalent idea. After all, Fusebox was developed in a non-OO world, and Mach-II is decidedly object-oriented.
Hal: That's true, but what does it mean to say "Mach-II is object-oriented" while Fusebox is not?
Jeff: I wouldn't say Fusebox is not object oriented so much as it doesn't need to be. With Fusebox, you can choose to use objects if you want. Mach-II, on the other hand, requires rigorous use of OO concepts, design, and coding.
Hal: Exactly. When we say Fusebox is procedural and Mach-II is object-oriented, we're talking about the framework, not the application. That's a critical distinction.
Jeff: Let's make this very clear then: what makes Fusebox a procedural framework?
Hal: Fusebox isn't built with objects. That is, the framework code itself isn't built with and around CFCs. In Mach-II, the framework is nothing but CFCs.
Hal: But both offer full support for objects and really, I don't think one framework has the edge over the other as far as that goes.
Jeff: Slow down, big fella. I want to make sure this is crystal clear. So we call Fusebox a procedural framework because the core files: the runtime, loader, parser, and transformer, are written procedurally. Whereas the corresponding code in Mach-II is CFCs.
Hal: That's right. Now, the interesting thing is that we could rebuild Fusebox entirely in objects -- and no one would need to know. It wouldn't affect current code and new code could be built on it without understanding that such a change occurred.
Jeff: Absolutely. OK, let's talk about the applications then. We can do OO in Fusebox.
Hal: Yes. Let's talk about what it means to "do OO". The issue is a different one than OO v. procedural. It's an issue of page-centric architecture v. the domain model approach.
Jeff: Good. Let's define those terms first. Page-centric is "they way we've always done" web sites: thinking in terms of the HTTP request-response cycle.
Hal: Right. Both logic/business rules/data access and presentation are done together within the context of a page. Even if you use cfincludes or make custom tag calls, the paradigm stays the same.
Jeff: And Fusebox just lets us organize those various types of code to "separate" them from the developer's point of view. Once the fuses are processed and the request is submitted to the server, all the flavors of logic are mingled within the request.
Hal: Yes, if you're using a page-centric approach, that's exactly what happens. And, by the way, you can do exactly the same thing with Mach-II. But when we say "OO applications", we typically have in mind something quite different.
Jeff: Using the domain model approach. Let's define that term as well.
Hal: Good. In the domain model approach, we create a software version of our little corner of the world--typically our company or organization. In this way, both maps and domain models are similar: both derive their power from their smaller size and greater simplicity. Maps are smaller and simpler than the terrain they represent. Domain models are smaller and simpler than the domain they represent.
Hal: A domain model is a scale model of your world. Do you have customers in your world? Then you'll have customers in your domain model.
Jeff: So instead of starting application design with "What do you want this application to do?", we start it with "Where does this application fit into the domain?"
Hal: Maybe even different from that. When you create a domain model, you're designing it so that it can work with possibly many different applications -- including future applications. If you've done a good job defining and implementing a Customer, for example, that should be reusable across all applications that need to work with customers.
Hal: So the domain model is not an application, but exists to be used by applications. By itself, it doesn't do anything.
Hal: Maybe we should have an example?
Jeff: Sounds good to me.
Hal: OK. When designing a domain model, I start by writing down a little narrative that expresses (in words used by users) what the world looks like. Maybe something like "In our world, we sell classical music CDs. Each of these CDs is the work of one or more artist and is put out by one label..."
Hal: And I keep going for about a page, usually, until I have a good narrative (both sufficiently accurate and complete).]
Hal: Then I look for nouns and verbs in my narrative. This is an old trick, but it works pretty well. My nouns become candidates for entities in the domain model.
Hal: My verbs become candidates for things that these entities can do.
Hal: Make sense so far?
Jeff: Yes. Now its sounds like we're talking about objects and methods.
Hal: Well, funny you should say that -- because that maps very well to the idea of objects with methods. Domain models and OO languages just fit together very nicely.
Jeff: OK, but let me not jump things ahead too quickly. We can develop the domain model irrespective of application intentions, right? We don't have any applications in mind at all to do the domain model.
Hal: Right. When working with the domain model, we're in the mode of what I call "Applied Ontology". You know, if it's a big name, it must be profound, right?
Jeff: Ontology: what it is, brother.
Hal: Ontology is the study of being.
Jeff: Right. Ontology = what it is
Hal: Ontology studies the nature of being and the categories of being. What beings exist and what is each's proper character and nature?
Hal: Completely useless area of metaphysics, right? It's just that general philosophical study, which, as we all know is useless in the real world. Except that it isn't. It turns out that ontology is exactly what we need when we create domain models. Now, we don't need to use the term, "ontology", but what a good domain modeler does is ask, "What does it mean to be...[entity here]?" What does it mean to be a Customer. What do I know about myself? What sort of things can I do?
Jeff: Sounds more like omphaloskepsis to me. ;)
Hal: You do that and you'll clean it up.
Jeff: omphaloskepsis means contemplating one's navel.
Hal: I was working with a client on a very difficult domain model one day and it popped into my head, "Good heavens, I'm using all that stuff I studied in philosophy classes -- just in a different context." But approaching it from this point of view is enormously helpful in keeping us from tripping ourselves up.
Jeff: I like your application of philosophical ontology to domain modeling.
Hal: We can continue with the idea of a Customer. What does it mean to be a Customer? What do I know about myself? What sort of things can I do? These questions help us when we try to decide something like -- "Should a Customer have a method for saving itself to a database?"
Jeff: OK. Should a Customer have a method for saving itself to a database? I guess if we want to welcome the customer back, and have their information available, then yes.
Hal: But before we mark that as our final answer, let's put on our Ontology hats. What does it mean to be a Customer? Does it mean that you know how to save yourself to a database? Of course not. You're an Amazon customer. Do you know what databases are being used, much less the data schema? Nope. Why not? Because Customers don't know anyting about databases.
Jeff: I see two points of view for the Customer data, though: welcoming a customer back is an application-specific idea, where having customer data available is a domain-related idea.
Hal: Now, clearly, SOMEBODY better know how to persist a Customer to a database, but just as clearly (with the help of a bit of applied ontology), we can see that it isn't the Customer.
Jeff: So when we're defining Customer, we have to think like a customer, not like somebody who knows about the customer.
Hal: We have to dig deeply into the nature of being. Of being...a Customer, in this case. At every step in building the domain model, you can see Plato's ideas implemented in 21st century technology. Talk about having a long shadow. But, I don't want to get too deeply into how domain models are built, other than to say that the idea of a domain model is very different from an application. And that a page-centric application is very different from one that relies on a domain model.
Jeff: So let's jump to the end-point of defining the domain model. We have a model produced, and we want to build an application. How do we take advantage of the domain model?
Hal: All of the rules governing domain ontology are stored in the domain model. And applications can make calls to the domain model. I'll bet you want an example.
Jeff: Of course.
Hal: We'll build a simple domain model. So, let's say that you're a manufacturer, Jeff. As a matter of fact, I believe you're one of the major stockholders in WegotWidgets, Inc? Now, you manufacture widgets. Tell me, Jeff, what does it mean to be a Widget? What does a widget know about itself?
Jeff: I know my name, what I do, and how much I cost.
Hal: Do widgets have an ID?
Hal: And--forgive my ignorance of widgets--do they come in different sizes?
Jeff: Some do, and some don't.
Hal: Would two widgets that look and function the same but have different sizes have separate IDs?
Hal: Great. Now, this is how it works in real life, where I ask questions -- initially, very simple questions -- to "build up" my domain model and make sure that I understand each entity thoroughly.
Hal: Oh, one other thing, does a Widget know if it's taxable?
Hal: OK. And as a manufacturer, you have customers. I happened to hack into your database and I saw that you had the following fields: customerID, firstName, lastName, street1, street2, city, state, zip, country, creditLimit.
Hal: All in the interests of science. Computer science.
Jeff: OK, I'll put off the lawsuit for now.
Hal: Now, let's say that you get bit by the internet bug. "I'm gonna have me one of them internet stores," you say to yourself. We could produce some structure or array or query to represent the idea of ShoppingCart. Or, we could just decide that we need a ShoppingCart entity in our domain model. Now, what does it mean to be a ShoppingCart? What do you know about yourself?
Jeff: I have items, and I belong to a customer.
Hal: Good. You have items and you have a customer. And, I suppose, a customer has a shopping cart. One thing you see when working with domain models (and with OO, in general) is that it's very helpful to think of the domain entities as though they were conscious beings. Now, what does it mean to be an Item?
Jeff: Yes, that's apparent. As an item in the cart, I have a widget ID and a quantity.
Hal: So in our domain model, we've identified a Product, a Customer, a Cart, and a CartItem, right?
Hal: OK. You told me what a Cart knows about itself. Tell me, what sort of things it can do: what sort of methods you can call on the Cart.
Jeff: I can add items, delete items, and tell what my contents are.
Hal: Yep. So, now, let's think about an application. You wanted to know how we'd use the domain model. Now that I have these entities, my application code is pretty simple. Let's say that the user clicks on a "Add to Cart" button with this code behind it: <form action="index.cfm?fuseaction=addToCart&id=39904>
Jeff: Makes sense.
Hal: Our next step is to create an instance of the 39904 widget. Maybe something like this.
Hal: <cfset widget = CreateObject('component', 'Widget39904').init() />
Hal: What about a shopping cart? Maybe something like this:
Hal: <cfif NOT IsDefined('session.cart')>
Hal: <cfset session.cart = CreateObject('component', 'Cart').init()>
Hal: <cfset session.cart.add(widget) />
Hal: That's it. Pretty small application, no?
Jeff: Absolutely. And so far I haven't seen anything that couldn't be done in Fusebox, either.
Hal: Yes, the only question is: where do the domain rules reside? In pages in an application or in a domain model? Now, let's say that CustomerService needs an application. They need to work with customers. We already have a Customer component that we can reuse. Now, code reuse is great and all that, but frankly I'm much more conceerned with code maintenance. If something changes in the definition of what a customer is, such as a new behavior, I want to have only ONE place where such behavior is encapsulated.
Jeff: Oh, yes. I hate hunting down code for maintenance.
Hal: In applications built around domain models, there are typically three parts to the application. There's the domain model, of course. There are the views or display pages that the user sees and interacts with. Those are the obvious two. But there needs to be another layer -- something that can bridge the chasm between the view that knows nothing about the model and the model that knows nothing about the view. What is that?
Jeff: We need a controller of some kind.
Hal: Exactly. We've discovered the Model-View-Controller design pattern. Now, where are we going to get one of them there controller things? Well, I happen to know of two excellent ones: Fusebox and Mach-II.
Jeff: But in the cart example above, the application is interacting directly with the domain model.
Hal: Sure, through the Fusebox controller.
Jeff: Oh, I get it. There's a not-so-visible layer there. That's the controller, even though we don't have something labelled "Controller".
Hal: Yes, I left that out for the sake of brevity.
Jeff: Brevity may be the soul of wit, but programmers need details.
Hal: And the controller is Mach-II or Fusebox. Fusebox or Mach-II. Or you could create your own (although why would you?)
Jeff: So how do we decide which to use?
Hal: In an MVC app, the controller is absolutely necessary, but it's a pretty humble servant. From the customers POV, it's the View layer that really matters. From the architect's POV, it's the Model that really matters. Now, well-built controllers are very handy: they can save a lot of drudgery on the programmers part, but it's not particularly important what their internal architecture looks like. We're just not that interested in the controller, as compared to the view and the model. We can real value in having an OO domain model, but do we need an OO controller?
Jeff: Other than the benefits provided by having a recognized control system, we don't really care what goes on under the hood. Still the question remains: how do we choose which to use?
Hal: Well, if you're completely steeped in OO, you'll probably find Mach-II, the OO controller, is the most natural fit. On the other hand, you might decide that although YOU are OO-aware, some of your team may not be. While Fusebox doesn't require anyone to understand OO, Mach-II definitely does. So, if I were working on a team with Ben Edwards and Sean Corfield, both OO guys, I imagine we'd use Mach-II. If I was working on a team with other programmers (who may be as good or better than Ben or Sean, but simply don't do OO), I think I'd choose Fusebox.
Jeff: Let's clarify that a bit. If we don't care what's under the hood, why does Mach-II require us to have OO-aware programmers?
Hal: I want to make sure people understand that one isn't "better" than the other. It would be like asking, "Is German or Italian a better language?" Well, if you're with a group of German native speakers, I imagine you're going to find German the best choice."
Jeff: That makes sense. So not only is Mach-II OO code under the hood, but it's designed to "speak" OO in the application layer as well.
Hal: Yes, that's right, Jeff. Because Mach-II exposes more of its internal architecture than does Fusebox. As I said earlier, you could change Fusebox's architecture from procedural to OO and no one would notice. If you went from OO to procedural with Mach-II, everyone's code would break. The controller components Mach-II programmers create extend the Mach-II framework components.
Jeff: So, in OO-speak, Mach-II programmers create classes that extend the framework classes.
Jeff: So they necessarily need to understand OO.
Hal: Yes. When people struggle with Mach-II, they're typically struggling with OO.
Jeff: And the "which to choose" question distills down to the skillset of the development team, as opposed to the characteristics of the application.
Hal: Yes. That's exactly it, Jeff.
Jeff: Well, I sure hope our little discussion helps clear up that question for Fuseboxers. I know I've talked to some who feel like they're losing ground if they don't adopt Mach-II.
Hal: Well, as someone pretty intimately involved in Mach-II, I can assure them that they're not. Ultimately, the real need isn't to move from Fusebox to Mach-II, but to move from page-centric architectures to domain-centric ones.
Jeff: Agreed. Hey, we're going to talk about this stuff in the Fast Track to Fusebox class in April, right?
Hal: We certainly are.
Jeff: Great. I'm really looking forward to that. For anyone interested in attending, you can see details and register at