Reuse: Is the Dream Dead?

Reuse is software development’s unattainable panacea. The ability to compose systems from reusable elements has long been our achille’s heel.  We want reuse so badly, yet our failures are spectacular. Almost all major technology trends of the past 20 years touts reuse as the saving grace. Vendors have sold billions of dollars in software through the broken promise of increased reusability.

What happened? Reuse was supposed to save software development. In the early 90’s, object-orientation promised to save us. It didn’t, so we moved on. In the late 90’s, component-based development promised to save us. It didn’t, and we moved on. Shortly after the turn of the millenium, SOA promised to save us. It didn’t, and we’re moving on. Why is reuse so damn hard?

The problem stems from the following rather simple statement, which is depicted in the diagram (click it to view in full size):

Maximizing reuse complicates use. (1)

In general, the more reusable we choose to make a software component, the more difficult that same software component is to use. In the extreme, an infinitely reusable component is infinitely difficult to use. Dealing with the tension between reuse and use is a complex issue, and often, we fail. Largely, the problem has to do with dependencies.

NOTE: I use the term component pretty loosely here. In general, the software development community has done a poor job defining the term “component”. Let’s just assume that when I say “component”, I’m talking about a chunk of software. No more, no less.

The Reuse Disclaimer

I recognize that we’ve done a fair job in achieving reuse at certain levels, and we’re much farther along the reuse curve than we were 20 years ago. Today, we have a plethora of frameworks to choose from that aid development. Web frameworks, ORM frameworks, and security frameworks to name just a few. But most of these frameworks are horizontal, not vertical. They address problems related to infrastructure and plumbing code, not business problems. And I want to focus explicitly on vertical reuse, because that’s the unattainable panacea we’ve been struggling with for so long. That’s the broken promise. Why have we struggled to create reusable business components?

Granularity

Granularity is the extent to which a system is broken down into parts. Coarse-grained components tend to be richer in behavior than fine-grained components. Because coarse-grained components do more, they tend to be bigger than fine-grained components. To maximize reuse, we try composing coarse-grained components from fine-grained components. Of course, this results in a lot of dependencies between components, making them more difficult to use. In general, we can say the following:

Coarse-grained components are easier to use, but fine-grained components are more reusable.

Time for an example. Let’s say we’re creating a component that processes health insurance claims. Let’s keep the business process relatively simple here to maintain our sanity. There are four steps in the process. First, the system is fed the claim information. Second, the system checks to make sure it’s not a duplicate submission. Third, the system reprices the claim based on HMO and PPO agreements. Fourth, the system remits payment. A coarse-grained component would perform all four of these steps.

In doing this, we’ve made it easy to use since we only need to invoke one operation to complete the whole process. But it’s also more difficult to reuse only a portion of this process, such as the remit payment code. The logical solution is to create four fine-grained components (one for each step in the process) and one coarse-grained component composed of the four others that pulls everything together. The fine-grained components make things more reusable, but are also more difficult to use since we have to do more to pull them all together to perform a unit of work.

Weight

Weight is the extent to which a component depends on it’s environment. A heavyweight component depends on it’s operating environment, while a lightweight component avoids these dependencies. When creating a component that runs in multiple environments, we’re forced to move the environment specific dependencies (ie. context dependencies) from code to configuration. This makes the component more reusable, but it’s also a bit more difficult to use since the component must be configured for each environment.

Designing and configuring a lightweight component is more difficult than simply dropping in a component programmed to operate in that environment. In general, we can say the following:

Lightweight components are more reusable, but heavyweight components are easier to use.

Let’s elaborate using the example above, where the solution was to create one coarse-grained component composed of four fine-grained components. If each of these components only needs to run within a single application in a single operating environment, we can encapsulate all of this environmental code into each component, making each heavyweight. But if we want to reuse these components across applications and operating environments, then we have to move this code outside of the component and ensure it can be configured for each environment in which we want it to operate.

Reuse or Use

The challenge we run into when attempting to create a highly reusable component is to manage the tension between reusability and useability. In our example above, breaking out the coarse-grained component into fine-grained components makes it more difficult to use each of the resulting fine-grained components. Likewise, creating a lightweight components makes using the component more difficult since the component must be configured each time the component is used.

Fine-grained components have more component dependencies and lightweight components have more context dependencies. Each makes a component more reusable, but also more difficult to use. The key is to strike a balance, and that is a topic for another day not too far away.

(1) This statement is a derivation of Clemens Szyperski’s statement in Component Software: Beyond Object-Oriented Programming – “Maximize reuse minimizes use.”

23 thoughts on “Reuse: Is the Dream Dead?

  1. It’s hard because of this persisting myth that computer programs are a sequence of instructions written in not-so-clever languages.

    We have known this for decades. While we continue to entertain the idea that programming is for dummies, then reuse will forever be hard.

  2. I think the Re-use / Ease of use graph does not need to look like that. I find that during re-use the component/object needs to be configured before it can be used. If in the process of re-use ‘useful’ default configuration was provided then it would be easy to initially use the component/object and then the user could gradually learn to use the rest of the features or config options.

  3. It’s true. Reuse comes with a price. This price is the one we have to know before invest effort on making a component more reusable, or before start using it. As an example, if using a component in a particular app costs more than creating a customized one (including configuration, deployment, maintenance, etc.) then re-using it is not the best choice.

  4. Another problem of Reuse is a modular reusable component can be clearly identified only after you have design/developed and used it and there is a use case which is similar to the functionality of the component.

    May be a Assembly oriented methodology may increase reusability as the dependency between components is assembled instead of coded as currently.

  5. Was there a typo at the end of the article

    “Coarsed-grained components have more component dependencies and Heavyweight components have more context dependencies”.

  6. My fault, never mind. The statement is absolutely true when we use fine grained component (more component dependencies to manage) and lightweight components (more context dependencies to maintain in config). As it says its more reusable but difficult to use.

  7. Nice way of looking at the problem. Indeed, coarse-grained components are hard to reuse because they try to solve too many problems in the context of the coarse overall point of view. But I’m not sure if they’re necessarily easier to “use”. Being coarse, and thus complex, they may have solved the problem in the wrong way. And since they’re not reusable, they cannot be changed easily to fit a slightly different problem domain. Since time can change the original problem setup, they often cannot even be reused/used for their “original” purpose. I.e. a coarse solution that is developed in a project over four years cannot be finished, because it cannot be reused after those four years.

    If the dream is dead, then software engineering will face a dark future :-)

Leave a Reply

Your email address will not be published.