Welcome

You have reached the blog of Keith Elder. Thank you for visiting! Feel free to click the twitter icon to the right and follow me on twitter.

How To Not Screw Up Your Application Object Model – Don’t Go All OOP On Me!

Posted by Keith Elder | Posted in .Net, CSLA.Net, Programming | Posted on 02-05-2008

I have no idea where this post is going to go but I have several things that have come up in discussion lately with developers that I need to get out.  The conversations I’ve been having are around building applications and using the CSLA.Net business object framework.  This article doesn’t focus on CSLA.Net so even if you aren’t using it, these principals still apply.  This post stems from conversations with developers that are spending a lot of time creating beautiful object models.  I’ve seen developers spend a lot of time on perfecting the object model of an application based on sound OOP practices and techniques.  Once the object model is applied to the application it doesn’t work and the developers are scratching their heads asking themselves why.   I’ll explain a common scenario that I’m running into, how to avoid it, and how I think you should think about your object model for your applications.  Definitely fun bathroom reading, so let’s get going!

Throw Away The Object Model In Your Head

As object oriented programming developers on the .Net and or Java platforms we’ve always been taught and trained to think in object models and object graphs.  For example if I asked experienced object oriented programming developers to create an object model for a Veterinary Clinic they would start immediately thinking in terms of physical objects like, dogs, cats, birds, etc.  The reason is because we have been beat to death with OOP principles.  As an exercise I opened up Visual Studio and threw out the very first object model that came to mind based on a Veterinary Clinic.  Here’s what I came up with thinking about the object model from a pure educational standpoint.  I’d kept going but I wanted it to fit onto one screen.

image

Without knowing anything about the business of a vet clinic and relying only on my experience in owning pets this is the first thing I came up with.  My thought process was vets take care of pets, there are all types of pets, and pets belong to an owner.  Some pets are birds, some are dogs, cats, snakes, lizards, etc.  My college professor would be very proud of my object model I am sure.  He’d feel all warm and fuzzy seeing that I broke down my objects all the way down to dogs then the subclass of spaniels and then cocker spaniels (of which I own three).  On paper this looks great but it is an extremely bad object model.  Don’t do this!  The problem is developers try to apply these perfect object models to their applications.  This is the worst thing a developer can do when building an application.  Well, not the worst, but it sure is a really bad start and a lot of wasted time.

After doing this little exercise I have to admit I felt very dirty.  Seriously.  Why?  Because none of these objects fit into the what the Veterinary Clinic really needs and I honestly just wasted my time proving a point trying to stop you from wasting your time.  Stay with me and I’ll show you. 

A Real Example

I have a friend that is a vet.  After writing this really bad object model down I gave him a call and asked him if he had any software he used to run his clinic.  He said absolutely and he couldn’t run his business without it.  Great, a real world example!

I asked him to tell me about one of the screens they use the most in their application.  He then described what he called the “Account Locator” which after further questioning turned out to be a fancy name for a “Search” screen to lookup clients or accounts in the system.  I took a few mental notes during our conversation and after hanging up made this mock application based on his description. 

image

The scenario is employees running the main desk at the clinic need to get to accounts quickly and this is why this screen  is used so much.  The scenario is if someone calls the clinic to schedule an appointment, the first thing someone has to do is lookup their account.  The grid below displays some useful information to help the employee find the right account.  It also allows the employee to make the client feel like they are well known.  The example my friend gave is once an account is located the employee immediately knows the pet(s) name, the last time they came in and the type of the pet. 

This scenario now brings me back full circle to the object model I initially built.  Here’s the million dollar question: 

What good is a gigantic object model in this scenario?  Answer:  Nothing! 

The elaborate object model I built out based on my first impression of what objects I’d needed to create are basically useless. 

Why?  For starters, look at where the information from the object model (which shouldn’t have been written in the first place) has to come from just to make this screen work. 

image

Data is traveling from all sorts of different objects and I didn’t even account for all of the fields.  Are you starting to see why building elaborate object models for an application first doesn’t work?  If you don’t know how the data is going to be used you can’t build an object model. 

This is the main point.  Focus on the business requirements and don’t get all caught up in OOP principles just because it is fun.  And it is fun to be honest.  I love discussing object models but the point is you should be discussing the business requirements!

Do We Really Need An Object Then?

The question I get after showing someone the above example is, “Do we really need an object then since we are just fetching data?”.  When people ask me this what they mean is if they are just searching data and returning data, why all the emphasis on building objects in the first place?

The answer to that is lengthy but I’ll try to hit the high points.  Let’s start with the act of a user entering data into the three fields to search.  This is technically an object.  It is an AccountSearch object.  It isn’t a very hard object to create, it just has three properties.  Here are the things a developer has to think about though.

  1. Searching by just pet name will return too many results.  The developer must force that users enter the pet name and the owner last name.
  2. If a user enters a phone number only, that is ok.
  3. If they enter all three fields that is ok.
  4. The phone number must be formatted correctly to match how it is stored in the database.
  5. The pet name and the owner last name much match a certain criteria (example % isn’t in anyone’s name).
  6. Who is allowed to use this object?  Can just anyone in the world use it?  Probably not.  Therefore there are security concerns as well. 
  7. How is the object bound to these fields?
  8. Is the object in a broken state (error?).
  9. Was the object modified? (in other words you can’t search on something if there is nothing there)
  10. Is the object in a valid state?

All of this needs to be thought about and leaving any one of these off can cause lots of problems within the application.  Therefore, this is why we’d have an object that handled all of this logic.  And this is why we call them “business objects”.  In this case it is a single object that encapsulates all of these scenarios.  Take the first letter in the CSLA.Net Business Framework.  The first letter stands for “Component”.  This is where the name comes from because as you can see we are dealing with a single component that accounts for all of this.

How Many Objects Are On This Screen?

Now that we’ve established our initial object model was a complete waste of time, let’s look at what we should do with this example.  Looking at my prototype example, how many business objects do you think are on that example screen?  If you said three, you’d be correct! 

image

  1. AccountSearch.cs – This object encompasses the search functionality I elaborated on previously. 
  2. AccountSearchResult.cs – This object is a Read-0nly object that simply holds the data for each row.
  3. AccountSearchResultList.cs – This object is a Read-Only-Collection of AccountSearchResult objects. 

Even though the AccountSearchResult object is just a read only object it still needs to be an object.  For example, what if the business required us to change this screen and add another column that only admins could see?  Maybe the column in this case would be a column that held the Owner’s social security number.  In this scenario, the AccountSearchResult object needs to know how to handle this situation and it should know based on the user viewing it that it is not suppose to show that property.  More times than not a developers first reaction is to put this into the UI because it is easy and they aren’t using something like CSLA.Net that provides this functionality out of the box.  Writing that business logic in the user interface doesn’t do any other developer any good if another UI is built like a web UI for example.  Again, that object needs to know how to handle this.  Think component!

What about reusability?

The next question I get after explaining this is:

Are you telling me that every screen the app has, there is a different object?

My answer is any data that is “touching the glass” of the application is encapsulated in some type of object.  In more complex scenarios that may in fact be a full blown object graph with a parent and child objects, etc.  I’m not saying don’t think of any object model but typically more complex object models are what I call core objects to an application.  In this vet application an Owner object would be a core object that would have children of pets, addresses, invoices, bills, follow ups, appointments, etc.  BUT…. ONLY IF THAT IS HOW IT IS VIEWED IN THE APPLICATION!  The difference is you have to think of the YAGNI principle which is if you ain’t gonna need it, don’t put it in your object model.  Build the object model based on the expected behavior. 

Obviously when we build objects we like to re-use them and in some cases you can.  For example why wouldn’t you be able to reuse something like an Address object?  In most cases an address is just an address.  There are cases where even something as simple as an address needs to be in a separate business object though because of the business concerns around it.  For example imagine you were building objects for a realty company.  The address of the client vs the address of the subject property being sold are COMPLETELY different objects with different business rules around them.  This is exactly what I’m talking about.

When building your application you have to think about how an object is used.  For example, take our search screen example above.  What if we were told to build a search screen with the same search fields that returned a slightly different result set.  This is the crossroads where a developer has to really think and make a decision.  Basically there are two choices.

  1. Re-use the existing result object and modify it to account for both scenarios.
  2. Build a brand new object.

There isn’t a hard and fast answer I can give you as which way you should go.  My default answer is make them different objects since later on you can easily update one without impacting the other as new changes come in.  However you may decide to keep everything in one object based on the amount of time you have.  A general rule of thumb to follow is if 80%-90% of the data and logic in the objects can be re-used, then you may decide to just update the one object.  As you approach a lower percentage of re-use you are just causing yourself problems and need to separate those concerns.

The best way to think about this is let’s say you were building a screen that returned just plain old data (not even thinking objects anymore).  And on that screen you had 5 pieces of data.  Your data query might be something like: 

select col1, col2, col3, col4, col5 from MyTable where col1 like ‘%foo%’

If someone asked you to take out the second column in a certain scenario, would you leave the query alone or rewrite it as:

select col1, col3, col4, col5 from MyTable where col1 like ‘%foo%’

I would HOPE you wouldn’t return the second column if your application didn’t need it!  Building different objects for different purposes is the same thing.  Sometimes you might choose to not modify that query.  But as more columns are changed you’d be crazy not to think about the extra payload you are putting on the database, the network, and latency being built into your application.  It is a fine line to walk but as I said, if I have another screen in my application, I’m going to automatically make another object that encompasses that object for that one given scenario.  Remember, it isn’t just as simple as returning data.  If it were, there wouldn’t be something called business logic!

For further clarification let me say this.  If both objects in my application use the same business logic I am not going to duplicate that logic in each object.  That is silly and doesn’t scale.  That logic should be moved to a common library so it can be referenced from both objects.

Takeaway

The big takeaway from this litany of verbal spillage is when you design applications you have to know how the end-user is going to use the application and what the business requirements are.  Sitting down and building an elaborate object model, while really fun and educational, it is a big waste of time.  Don’t do it.  Sit down and ask questions so the behavior and business requirements can be accounted for.  Whether you are using CSLA.Net or not the same thoughts must go into building the application.  I hope this helps cements these concepts because I know there is a large amount of disconnect with this out there among developers who think everything is a perfect object graph like they learned it in school. 

Technorati tags: , ,

Comments (12)

Scratch,

Thanks for understanding the main point of post and taking the time to respond to Dan. I think you raise the same points I would have if I would’ve replied to Dan R.

-Keith

@Dan,

I complelte 100% disagree with you on what you are saying. Pretty much all the way up and down the pipe here.

First, don’t not get bent out of shape about the object model, as Keith said he built it to prove a point and it was the first thing that hit his mind. Thus your first paragraph I’m just ignoring because that wasn’t the point.

Second, these are NOT data-driven domain objects. These are BUSINESS OBJECTS. There is a huge difference. A “view” of an object built out of an elaborate domain model is useless, doesn’t perform, and has no way of wrapping the business concerns. Why? For starters in your example, why would I want to have to carry around all of the baggage of the complete object model that I don’t need? It isn’t about building the model and then querying it, that is a HUGE mistake to build an application like that. What it is about is about building out the business object, putting the validation, security, and business rules surrounding that object. There is more to it than creating a view from an object model which is worthless when you have to account for all of the other things.

With your method you don’t even have an object that contains any business logic. If you are wrapping everything up into one gigantic model and doing things like pet.owner.FirstName what is happening to the other fields in those objects? Think about the overhead that had to occur to just get 5 peices of data from that huge object model. The point is DON’T DO THAT! If you are going to do what you are talking about then just use LINQ to SQL or something. Even then the problem is that doesn’t work because you wind up putting business logic all in the UI and not seperating those concerns. Your way Dan you aren’t creating a real business object and you are bloating your application because you are loading a hell of a lot more than you actually need, even if you use an O/R tool. The best thing you could do is re-read this post, build an object like Keith is outlining here, and put an O/R tool under the object at least. I would highly suggest you look at CSLA.Net. A lot of us use it for these very reasons because it focuses on the business object itself.

Think about it, you are carrying around a whole object model in memory to just get a few fields….. WTF! This is the whole point of what Keith was trying to say in this and for some reason you missed it. Not sure why. Maybe because that’s how you’ve always done things?

It’s completely unclear to me why you thought it was clever to make this domain model anything other than Pet, Address, and Owner. The only issue here is that you have unnecessary (and extremely poorly thought out) extensions to those 3 main objects. If anything, you are lacking a Doctor object with the requisite data needed to describe a doctor. And a field in the Pet object called “primaryDoctor” with a link to the pet’s “normal” doctor.

It’s also completely unclear to me why you think that data going into the UI from all 3 implies this is a bad domain model.

Typically, you create a “view” object (not to be confused with a domain object) out of the objects you have. However, in your case it is completely unnecessary and I have no idea why you are so down on the model. So, the path to making this screen work is:

1) Query the database, creating Pet, Owner, and Address objects and relating them. In a good framework, this takes very few lines of code and is one of the more important components for documenting O/R mappings.

2) Build a “view” — “clean” freaks will create a brand new view object and copy the data from the “model” and into the “view”, but I typically expose the model directly in a read-only fashion for use by the UI. The building of the view in this case is simply the placing of a lits of Pet objects into the request.

3) Render the view — the UI can refer to, for example, pet.name, pet.owner.firstName, pet.doctor.name, etc.

Looking to “data-driven” domain objects as a way to describe the lameness of OO is extremely misleading and a poor argument for your case.

Had your domain model included actual BEHAVIOR, you would have seen more usefulness. In this application, however, it does not appear that the domain is useful for anything other than data delivery.

For example, if one of the application’s goals were to analyze the health of the pet, your domain model would begin to matter a lot more.

I liked the way your post was presented. I certainly agree with your assessment that an academic domain model built without seeing the application space will tend to be useless, but I disagree wholeheartedly with the remainder of your arguments and your conclusions.

@Evan

I don’t think we have widly different opinions. It is simply me doing up a bad example, stating it is bad, saying don’t do it, and then showing how to do it (mainly within the CSLA.Net context).

We are still friends 🙂

I replied to Arnon’s post and I think he totally missed the point. Let’s NOT get caught up on the bad object model example I provided, that’s not the point of this post.

If it makes you feel better, take this good domain model and apply it to this scenario, it doesn’t work either.

http://www.ormapper.net/Examples/Default.aspx

Cheers.

-Keith

Keith, I make a distinction between a domain model and an application model. I’m more likely to manipulate domain objects behind the interface of the application model, so the UI mapping issues you describe would be handled in the object model. Still a great rant. 😉

++Alan

First let me say that I've met Keith personally, and he's a really cool guy. Cool enough in fact

You and I have wildly different definitions of OOP (or at least how it’s applied). I’ll agree that your example model would be a very poor solution. I’ll also agree that building anything resembling that is a giant waste of time.

I don’t buy the idea that OOP is a waste of time (insinuated by the title).

In case you can’t tell, I’m having a mixed reaction to this post. It’s a bit long, and some parts I greatly agree with, and others I feel are mostly you beating on a straw man (for good or bad).

I’m going to have to agree with Arnon’s assessment (another friend of mine):
http://www.rgoarchitects.com/nblog/2008/05/04/OOPsAnExampleOfMisusingTheTermOOP.aspx

This is very interesting to me. Your experience is really valuable and this is a great post, thanks.

.NET Bad Word Filter With Regular Expressions Hidden Undocumented Feature of Visual Studio 2008 – Dynamic

‘verbal spillage’ great term the article was worth it just for that.

http://kontrawize.blogs.com/kontrawize/2006/02/objectoriented_.html

In my not so humble opinion OOP/D is almost always taught incorrectly in schools. It is about Behavior, not Data. This can be seen in your model where your spaniel has no different data than a dog. Because the only actual type needed based on different behaviors is “Pet”.

Awesome post man.

Spending a good deal of my time writing SOA methods, I spend a good deal of time thinking about the object I return – and I have to agree here 100%. Object Oriented Design is really another form of Data Driven Design, and it’s a sure way to add a mess of complex code to your app just to support the ideal “clean model”.

I think it’s okay to give yourself permission to have objects for every part that “touches the glass” and plan on doing some refactoring later – when you have a good idea of what’s really needed. The times I do go for (mainly abstract) base classes are when I’m more concerned about sharing a set of functionality rather than properties – i.e. some custom serialization support.

Write a comment