That Rotting Design

Note: This is a re-post, with slight modifications, from an entry in October 2007. And now, two years later, we’re just about there! For the abridged version of this post, focus on the text in bold. You can see the original version here.

Design Rot

We’ve all experienced that sinking feeling when maintaining a piece of crappy software. Has my change broken the system in some unintended way? What is the ramification of my change on other parts of the system? If you’re lucky, and the system has a robust suite of unit tests, they can offer some support in proving your work. In practice, however, few systems have thorough automated test coverage. Mostly we’re alone, left to verify our changes as best as possible. We might privately criticize the original developers for creating such garbage. It certainly lends a plausble excuse in explaining why the maintenance effort is so costly or time-consuming. Or it might serve as the basis upon which we recommend a re-write. But mostly, we should wonder how it happened.

For sure, most software doesn’t start out this way. Most software starts out clean, with a clear design strategy. But as the system grows over time, strange things begin to happen. Business rules change. Deadline pressures mount. Test coverage slips. Refactoring is a forgotten luxury. And the inherent flaws present in every initial design begin to surface. Reality has proven that few enterprise development teams have the time or resources to fix a broken design. More often, we are left to work within the constraints of the original design. As change continues, our compromises exacerbate the problem. The consequence of rotting design is seen throughout the enterprise on a daily basis. Most apparent is the affect on software maintenance. But rotting design leads to buggy software and performance degradation, as well. Over time, at least a portion of every enterprise software system experiences the problem of rotting design. A quote from Brook’s sums it well:

All repairs tend to destroy the structure, to increase the entropy and disorder of the system. Less and less effort is spent on fixing the original design flaws; more and more is spent on fixing flaws introduced by earlier fixes. As time passes, the system becomes less and less well-ordered. Sooner or later the fixing ceases to gain any ground. Each forward step is matched by a backward one. Although in principle usable forever, the system has worn out as a base for progress.

The most obvious question is, “How do we prevent rotting design?” Unfortunately, rotting design is not preventable, only reducable. Of the past ten years, the design patterns movement has provided insight to the qualities of good design. Dissecting design patterns reveals many important design principles that contribute to more resilient software design. Favor object composition over class inheritance, and program to an interface, not an implementation, are two examples. Of the 23 patterns in the GOF book, all adhere to these fundamental statements. Alone however, design patterns that emphasize class structure are not enough to help reduce rotting design.

Reducing Rot

Most patterns emphasize class design, and present techniques that can be used in specific contexts to minimize dependencies between classes. Teasing apart the underlying goal of most patterns shows us that each aim to manage the dependencies between classes through abstract coupling. Conceptually, classes with the fewest dependencies are highly reusable, extensible, and testable. The greatest influence in reducing design rot is minimizing unnecessary dependencies. Yet enterprise development involves creating many more entities beyond only classes. Teams must define the package structure in which those classes live, and the module structure in which they are deployed. Increasing the survivability of your design involves managing dependencies between all software entities – classes, packages, and modules.

But if minimal dependencies were the only traits of great design, developers would lean towards creating very heavy, self-contained software entities with a rich API. While these entities might have minimal dependencies, extreme attempts to minimize dependencies results in excessive redundancy across entities with each providing its own built-in implementation of common behavior. Ironically, avoiding redundant implementations, thereby maximizing reuse, requires that we delegate to external entities, increasing dependencies. Attempts to maximize reuse results in excessive dependencies and attempts to minimize dependencies results in excessive redundancy. Neither is ideal, and a gentle balance must be sought when defining the behavior, or granularity, of all software entities – classes, packages, and modules. For more on the use/reuse paradox, see Reuse: Is the Dream Dead?

Software design is in a constant quandary. Any single element key to crafting great designs, if taken to its individual extreme, results in directly the opposite – a brittle design. The essential complexity surrounding design is different for every software development effort. The ideal design for a software system is always the product of it’s current set of behavioral specifications. As behavior changes, so too must the granularity of the software entities and the dependencies between them. The most successful designs are not characterized by their initial brilliance, but instead through their ability to withstand the test, and evolve over the course, of time. As the complexity of software design is an essential complexity surrounding software development, our hopes lie with technologies and principles that help increase the ability of your design to survive. Such is the reason why agile architecture is so important.

A Promising Future

I’m hopeful that all software developers have experienced the pleasure of a design that, through the course of time, has withstood the test of time. Unfortunately, many enterprise development teams have too few of these experiences. Likewise, few enterprise development teams devote adequate effort to package and module design. It’s unreasonable to believe that even the most flexible class structure can survive should the higher level software entities containing those classes not exhibit similarily flexible qualities. The problems are rampant. Increased dependencies between packages and modules inhibit reusability, hinder maintenance, prevent extensibility, restrict testability, and limit a developer’s ability to understand the ramification of change.

Services offer some promise to remedy our failures with object-oriented development. Yet, while services may offer tangible business value, within each awaits a rotting design. There exists a world between class design and web services that deserves more exploration, and as an industry, we are beginning to notice. OSGi is a proven module system for the Java platform, while Jigsaw aims to modularize the JDK. JSR-294 aims to improve modularity on the Java platform. While some friction might exist between the constituencies involved, it’s only because they too recognize that something has been missing, and are passionate about fixing the problem. Of course, it doesn’t stop there. A plethora of application servers and tools are also including support for modularity using OSGi, which has grown into the defacto standard module system on the Java platform.

All aim to help manage the complexity, from design through deployment, of enterprise software development. With each, new practices, heuristics, and patterns will emerge that increase the ability of a design to grow and adapt.

6 thoughts on “That Rotting Design

  1. I like this article. I would go a little further. You wrote, “The greatest influence in reducing design rot is minimizing unnecessary dependencies.” I would say that the greatest such influence is making all dependencies explicit. I say this because implicit dependencies create spooky action at a distance, or rigidity, or however you’d like to describe “I change something here and it breaks over there.”

    When I make dependencies explicit, the unnecessary ones become so clear that I couldn’t, in good conscience, leave them there.

  2. You also left out code covered by automated tests. Tested code gives you a design that can survive over time because you can make changes without fear of breaking something. good TDD also forces you to think in terms of interfaces and independant components.

  3. If you’re wanting to plan a marriage or even if you only need to pick up that best wedding ceremony gift idea for your personal family or good friends, experiencing some ideas to help you out is a great way to make sure that you make very good options. Check out this report for some great wedding event ideas.

    Customs really are a excellent issue, but will not get rid of your self as a way to satisfy each wedding event tradition you might have actually heard. The most crucial part of the wedding event is that you are generating a responsibility together with the person you like. Everything should just become a entertaining strategy to commemorate that.

    Your wedding ceremony is actually a beautiful, soul-holding function, which can link you to definitely your companion forever. You are going to enjoy experiencing a bit of time straight right after the wedding ceremony to enjoy with the new spouse, so timetable within a thirty minutes, in some key location, to snuggle up and revel in your minute.

    If you are going to have a caterer on your wedding party, ask them provided you can demand which food products they can make. This way, you know that the meal will be to everyone’s choice. Also, question them if you could have a test of their meals, so that you know you are going to enjoy it.

    When you can afford to pay for a single, a wedding event coordinator can be a large time and stress saver. Not only will a advisor match your wedding and assist you to definitely make your perspective an actuality, but she can even be a fantastic source of information for concepts and opinions. She could help you save from working with every single small slight details and let you give attention to higher-stage preparing and having the ability to benefit from the approach.

    Your venue must not only assist your guests add up but furthermore it should make you wish to get wed there. When you have an aspiration or expect the style of your wedding event, make sure that your venue fills up that want. By carrying out the proper investigation and shelling out some time, you will make an atmosphere this is the foundation of your wedding.

    When you have an outdoors wedding event, have got a file backup prepare. Numerous marriage ceremonies have already been messed up by rainwater or any other climate problems. Have a quick replacement for a backyard location, be it to get the wedding ceremony with the reception hallway or have camp tents put in place in the event that. This will allow the wedding event to occur happily irrespective of what the weather conditions does.

    Hopefully, the following tips have provided you some assurance and aided enhance your self-confidence with your ability to plan your wedding event with good sense in addition to fashion. The better you know about how to plan a marriage correctly, the more power you’ll need to make certain each and every details is completely perfect.

Leave a Reply

Your email address will not be published.