EVERY application has a natural domain model – level 200
I’m in the camp that loves OO. I want smart objects for
everything. I don’t like data-centric programming. I don’t
like thowing raw data around in DataSets. I create custom objects
for everything in my applications. I was reflecting on a very
simple application, and I realized that every application has a natural
domain model. I’ve had conversations where a developer has said,
“Our application is different. It’s not an enterprise
application. Domain-driven design doesn’t apply.” I’ve come
up with a really simple example to illustrate my point.
Suppose you have an application that only maintains social security
numbers. That’s it. It doesn’t store person information, just
social security numbers. In fact, your entire database is one
table with one char(9) field. One might just go ahead and
keep the social security numbers in a string. Would that
work? Yes, but consider the natural domain object for this:
public class SocialSecurityNumber
{
private string _rawNumber;
public SocialSecurityNumber(string number)
{
_rawNumber = number;
}
public string GetWithoutDashes()
{
return; //the ssn without dashes.
}
public override string ToString()
{
//format ssn nicely and output.
return; //the nice output.
}
public override bool Equals(object obj)
{
return true; //or false if they don’t match.
//Use some intelligence to compare for sameness.
}
}
You could store the information in a string, but then that is a magic
string floating around your application, and every class _just_ has to
know that it must be a social security number. There is no strong
typing to enforce that there are exactly 9 numerals in the
string. What about dashes? with this SocialSecurityNumber
class, you have your domain model, and now you can enforce all the
rules about the number easily. Maybe you want to always store it
in the database without dashes but want to display it on the UI with
dashes. Instead of string manipulation elsewhere, encapsulate
that logic directly inside the domain object. If you use this
object throughout your system, it’s clear that constraints will always
be enforced, and you never have double check that a social security
number is really there – the compiler picks up that burden for you as
well as runtime strong type checking.
Consider your current applications. Do you have a prominent
string, bool, or int? Would it be helpful if that piece of
information could carry around describing and validating
information? Consider creating a domain object to house that
single piece of information and enforce rules about it. I think
it’ll make the application a lot simpler.
Agreed.
Two things though: Not all applications serve a transactional business need. Not that you implied this, just that some readers might say “this doesn’t apply to me, we only do reporting”. Most likely you still have transactional needs, eg: logging, authorization, etc. Even if you don’t, a domain model isn’t the opposite of reporting.
By the same token though, if you’re just plunking data on a page, then in many cases a DataTable may just be the right thing for the job. It’s very important to understand that there is a conceptual model just the same, even if you choose not to implement it though. Ignoring that, and treating it with any less respect, will just lead to sloppy, difficult code down the line in my experience.
Good points – but one thing I see all the time that I just couldn’t let pass – don’t use nvarchar for something that won’t every be in unicode, and ESPECIALLY, DO NOT use var* for any data that will have a fixed width, or vary only slightly. Var* datatypes have some overhead.
Sorry, I’ve just been dealing with a poorly designed data model that I inherited, and that nvarchar(9) reallly struck a nerve…
Thanks Eric. I’ve changed that to a char(9) field.
Since your ficticious example is an app that only maintains socials then it makes sense.
It doesn’t make sense in any real world app. The SSN would then be a member of the person or user object and I wouldn’t recommend creating a separate object for ssn as that would clearly be overkill because you could make your same argument for practically any column in any table– how about zip code for example (55555-2321).
Steve,
I agree with you about the Person object. If I need to maintain a “Person”, then that would be a domain object, and ssn would be an attribute. I had had a person entity, it would not be beneficial to pipe the data around in a DataTable with no encapsulation. The Person object, in that case, would be protecting its own data. My point was that every application has a natural domain model, no matter how simple the application is.
I could not agree more. I spend so much time trying to help team members make implicit concepts explicit. Helping to sesh out the domain model is THE GOAL. The alternative is that you get the processing logic spread over and over again throughout the application to make cohesive the implicit idea that should be centralized in a domain object.
-Chris