The Myth of Reusability
Don't be fooled. Reusability is not free.
You are building an inventory system for a large chain of car dealerships. You know that cars have a lot in common with one another. Cars all have wheels. Cars all have an engine. Cars all have a unique identifier known as a VIN. Etc. So, rather than designing a new data model for every possible type of car, you come up with a base class that contains these commonalities, something like this:
public class Car
{
public string VIN;
public Engine Engine;
public Color Color;
public List Wheels;
public decimal MSRP;
}
As the project progresses, you end up with quite a few different classes based off of this base car class: PickupTruck, Sedan, Suv, Limo, etc. The project turns out to be a major success, so they ask you to help design their new sales system. Not surprisingly, the sales system has a few things it needs to add to your base car definition, mainly SoldToCustomer and SalesPrice. So, we modify our base class to contain the extra fields that our sales system needs. The sales system doesn't really care about the type of engine or the type of wheels, but it gets that additional information for free.
After the sales system comes the web site. Next you build the CRM system and the EDI interface with the manufactures. With each revision, the car object continues to grow. Each system really doesn't need more than a handful of the properties, but it gets them free: reusability at its finest.
Then, one day, it happens. It's time to rewrite the inventory system. The actual event may vary from company to company, but it always comes. Maybe it's a merger. Maybe it's a new programming language. Maybe everyone comes to the conclusion that the core of the system just blows. After all, when you built the inventory system, you were young and inexperienced. You've learned a lot since then.
It is at this point that you realize that all these systems didn't really get their extra functionality for free. The base car object now has 50 or so various properties on it, and you really don't know which ones the inventory system actually uses. You may be 90% sure about half of them--but you sure as hell wouldn't bet your paycheck on it. You didn't build the CRM system or the EDI interfaces, you had moved to management by then. To make matters worse, half the guys you worked with to build the inventory system are off doing other things now. Of course, even if you could narrow down which properties the inventory system was using, it wouldn't really matter. All of the other applications depend on the inventory system. They share the database. They share the classes. They share the tests. You can't possibility rewrite the inventory system without rewriting everything else. Oh... Shit.
As it turns out, the billing system never ended up needing to know about the type of wheels or the engine. Neither did the CRM system or the EDI. About all they ever used in those other systems was the VIN and the Color... and a hell of a lot of workarounds were coded because of that. You actually ended up having to create objects like CarSummary that weren't really derived from car, just so that you could display a list of these things without waiting 30 seconds for it to pull back the data. CarSummary didn't include wheels or engines, just the basic data about a car that every one of the systems used... well, except the inventory system, which used lazy loading instead... and the reports which bypass everything and go straight to the DB.
The more you think about it, the more you realize how much of a pain in the ass this is going to be. Of course, it should have been obvious. You should have noticed it when you had to bring the inventory system down to roll out a new version of the CRM system. You should have noticed it when you started coding all those caching workarounds for the web site. You should have noticed it when EDI changes inadvertently broke that screen on the inventory system... but you didn't. Now you're going to have to tell your boss that swapping out the inventory system is a 3-5 year project. Of course, that's quite perplexing to him, since it only took 8 months to roll out the inventory system the first time around. If these new tools are so much better, why is it going to take 4-6x longer to build the new system? And what is the new system really going to do to justify all that cost?
This situation could have been avoided.
The technical term for the cause of this cluster-fuck is "coupling." I would hope that most developers have at least a cursory idea of what coupling is--enough of an understanding to know it has bad connotations. But usually we think of coupling in terms of obviously bad design decisions. The truth is that coupling is also found in systems that are designed quite well. In fact, you can't have reusability without some form of coupling. The consequence of coupling is that it assumes stability. When you couple two classes, you are agreeing to rewrite or rework one of those classes when the other changes. As a result, you need to minimize or eliminate coupling between portions of code that have independent concerns, so that you can deal with those concerns without worrying about everything else at the same time.
How do we do this? To start with, we need to stop trying to reuse every possible bit of code. Always remember: reuse is not free, the cost of reuse is coupling. There are situations where reuse makes a lot of sense, but it generally makes the most sense within an isolated space. For example, user interface libraries are generally a good candidate. But take a look at the code that is shared. The shared code has to do with drawing, element ordering, controls, bindings, etc. all of these are user interface related. The data grid may be used to interact with a lot of SQL data, but a properly designed data grid generally doesn't have code to directly interact with SQL, because that is outside of the user interface domain.
We'll talk about specifics soon, but first remember this: when you build the inventory system, focus on building an inventory system. When you build the CRM system, focus on building a CRM system. When you build the EDI interfaces, focus on building EDI interfaces. All these systems don't need to share the same database. All these systems don't need to contain the same objects. These systems will need to communicate, but the communication should be explicit and isolated from the core of the system. Then, when the time comes to rewrite the inventory system, you have a much simpler, much smaller chunk of code to replace, and you'll know where to find it.