o you want to save keystrokes? Do you want to ease maintenance? Do you want inline information about the code structures that you’re working with? How about statement completion? Are you interested in increasing the potential for code reuse? Do you want your applications to run faster and require less memory? Do you prefer to have users find bugs or do you prefer to find them yourself?
As I have become more and more experienced with .NET development, I’ve found that I strongly prefer to work with a rich domain model, not because I’m an ivory tower academic that relishes talking about the way objects model the real world (although they do!), how object-oriented design (OOD) better emulates real world activities (although it does!), or because I want to hide the details of my applications from people through encapsulation.
These are all important and beneficial aspects of OOD, but if they were the only benefits, I’d have to be a mad scientist to expect developers to take the extra effort, employ the extra critical thinking, and gain the extra learning that OOD and object-oriented programming (OOP) require. These are not, however, the only benefits. There are real, practical, and business-oriented benefits that OOD and OOP provide.
First, let’s talk about OOD (because design should, after all, come before implementation). Designing an object-oriented system enables architects to create a system that deals with complex business entities and problems in a manageable and rational fashion. Building custom domain (a.k.a. business) types is the most elegant and rich way to develop an application, and in many cases, it performs better than using a DataSet, even a strongly-typed DataSet. It is typically easier to maintain, and it provides greater potential for reuse.
That’s not to say there are not valid reasons for using DataSets – the built-in optimistic concurrency and full relational model can be truly handy when you need it, but for many, no most, server applications that I’ve worked on, these things are not necessary and thus the overhead they entail is not necessary.
Furthermore, using the DataSet, DataTable, or (worse) directly binding to a data reader in the UI layer ties you into a relational and procedural architecture instead of an object-oriented architecture. This means that you are tightly-coupled with your database structure and have much less potential for code reuse across UI layers.
If you change the name of a column, for instance, in a table that is returned in a Select statement, the potential impact for such a change to necessitate recoding in your UI (and even business logic) is much greater than if you abstract away the details of the database through a reusable domain object model. This is especially true in cases where you are not even using a strongly-typed DataSet?everywhere you access that column value using code such as (for example) myDataRow[“MyColumn”] could be affected.
Or what if you change the type of a column? If you are using a standard DataSet or DataReader and are casting the column values to a particular type that is not compatible with the new type you choose in the data source, your code will break, but it will only break at runtime. This means your users will find your bugs instead of you. If you are working with a strongly-typed domain object and change the type of one of its members, the compiler will tell you immediately everywhere that you are using it in an incompatible manner, letting you fix the bugs before your users ever know about them.
If you push the details of your data layer down below your domain object layer, the only impact such changes create is on the, usually, single place where you populate your domain objects from the database, which some refer to as the data access layer. Having a strongly-typed domain model decouples your database from the other layers of your application and provides a much more pleasant development experience.
Because you are dealing with typed data, tools like Visual Studio can provide information about your types inline while you’re coding (IntelliSense) and can offer to complete statements for you (AutoComplete), saving lots of development time. Even if you code in Notepad, it is easier and faster to type MyBlah.Foo than MyBlah[“Foo”].
But more important is that when you compile, if you misspelled something or (in C#) didn’t case correctly, the compiler will tell you. As a rule of thumb, the sooner you find out about a bug in the development process, the easier it is to fix. As mentioned, this approach can also save face for you and your company by reducing the potential for runtime bugs.
All these and more are reasons why building an application with a strongly-typed domain layer is preferable to skipping that and dealing with the down, dirty, and gory details of your database in your UI layer. Sure, when it comes to pure rapid application development, a two-layered, GUI-generated approach is probably going to win out. But if you want something that is more maintainable, more reusable, and just plain more fun (and at times more challenging) to work with, go with OOD.
So what do you think? Am I a mad scientist?