Reduce, Reuse, Recycle

Reduce, Reuse, Recycle

Reuse is one of those concepts that periodically rears up to sing its seductive siren song. Like that in the legend, it is exceedingly attractive, whether in the form of object-orientation, design patterns, or services. Unfortunately, it also shares the quality of tempting the unwary onto the rocks to have their hopes (if not their ships) dashed.

The idea of lowering costs via writing something once, the “right way”, then reusing it everywhere, is a powerful one. The simplicity inherent in it is breathtaking. We even have a saying that illustrates the wisdom of reuse – “don’t reinvent the wheel”. And yet, as James Muren pointed out in a discussion on LinkedIn, we do just that every day. The wheels on rollerblades differ greatly from those on a bus. Each reuses the concept, yet it would be ludicrous to suggest that either could make do with the other’s implementation of that concept. This is not to say that reusable implementations (i.e. code reuse) are not possible, only that they are more tightly constrained than we might imagine at first thought.

Working within a given system, code reuse is merely the Don’t Repeat Yourself (DRY) principle in action. The use cases for the shared code are known. Breaking changes can be made with relatively limited consequences given that the clients are under the control of the same team as the shared component(s). Once components move outside of the team, much more in the way of planning and control is necessary and agility becomes more and more constrained.

Reusable code needs to possess a certain level of flexibility in order to be broadly useful. The more widely shared, the more flexible it must be. By the same token, the more widely used the code is, the more stability is required of the interface so as to maintain compatibility across versions. The price of flexibility is technical complexity. The price of stability is overhead and governance – administrative complexity. This administrative complexity not only affects the developing team, but the consuming one also in the form of another dependency to manage.

Last week, Tony DaSilva published a collection of quotes about code reuse from various big names (Steve McConnell, Larry Constantine, etc.), all of which stated the need for governance, planning and control in order to achieve reuse. In the post, he noted: “Planned? Top-down? Upfront? In this age of “agile“, these words border on blasphemy.” If blasphemy, it’s blasphemy with distinguished credentials.

In a blog post (the subject of the LinkedIn discussion I mentioned above) named “The Misuse of Reuse”, Roger Sessions touches on many of the problems noted above. Additionally, he notes security issues, infrastructure overhead, and the potential for a single point of failure that can come from poorly planned reuse. His most important point, however is this (emphasis mine):

Complexity trumps reuse. Reuse is not our goal, it is a possible path to our goal. And more often than not, it isn’t even a path, it is a distraction. Our real goal is not more reusable IT systems, it is simpler IT systems. Simpler systems are cheaper to build, easier to maintain, more secure, and more reliable. That is something you can bank on. Unlike reuse.

While I disagree that simplicity is our goal (value, in my opinion, is the goal; simplicity is just another tool to achieve that value), the highlighted portion is key. Reuse is not an end in itself, merely a technique. Where the technique does not achieve the goal, it should not be used. Rather than naively assuming that code reuse always lowers costs, it must be evaluated taking the costs and risks noted above into account. Reuse should only be pursued where the actual costs are outweighed by the benefits.

Following this to its logical conclusion, two categories emerge as best candidates for code reuse:

  • Components with a static feature set that are relatively generic (e.g. Java/.Net Framework classes, 3rd party UI controls)
  • Complex, uniform and specific processes, particularly where redundant implementations could be harmful (e.g. pricing services, application integrations)

It’s not an accident that the two examples given for generic components are commercially developed code intended for a wide audience. Designing and developing these types of components is more typical of a software vendor than an in-house development team. Corporate development teams would tend to have better results (subject to a context-specific evaluation) with the second category.

Code reuse, however, is not the only type of reuse available. Participants in the LinkedIn discussion above identified design patterns, models, business rules, requirements, processes and standards as potentially reusable artifacts. Remy Fannader has written extensively about the use of models as reusable artifacts. Two of his posts in particular, “The Cases for Reuse” and “The Economics of Reuse”, provide valuable insight into reuse of models and model elements as well as knowledge reuse across different architectural layers. As the example of the wheel points out, reuse of higher levels of abstraction may be more feasible.

Reuse of a concept as opposed to an implementation may allow you to avoid technical complexity. It definitely allows you to avoid administrative complexity. In an environment where a component’s signature is in flux, it makes little sense to try to reuse a concrete implementation. In this circumstance, DRY at the organizational level may be less of a virtue in that it will impede multiple teams ability to respond to change.

Reuse at a higher level of abstraction also allows for recycling instead of reuse. Breaking the concept into parts and transforming its implementation to fit new or different contexts may well yield better results than attempting to make one size fit all.

It would be a mistake to assume that reuse is either unattainable or completely without merit. The key question is whether the technique yields the value desired. As with any other architecturally significant decision, the most important question to ask yourself is “why”.

14 thoughts on “Reduce, Reuse, Recycle

  1. Admittedly, I have been there myself. To my defence I will say that I knew very little about agility in the early ’90s, when I attempted to develop a generic, reusable, data access layer for a particular ISAM database. To my knowledge, it never reached production – it was way too complex to be maintained. The idea was tempting, though – that record structures will be automatically mapped for the applications that use them.
    My pitfall back then was that I omitted to continually validate the design against the requirements. I thought I was doing a great service for the customer and for future customers.
    While I agree that simplicity is not a goal in its own right (can you develop a simple fully functional humanoid?), in the vast majority of what we do simplicity will be the right approach.
    Maybe because we are all members of complex adaptive systems, we tend to over complicate solutions in order to cater for scenarios that may not really exist?

    Like

    • I agree that simplicity is a virtue in most cases, just not an end in itself. The old saying “as simple as possible, but no more” seems like a good rule of thumb.

      I think in many cases we develop very complicated solutions for the best of reasons – pride in our work. Our desire to do the best job possible can sometimes lead us to deliver a Maserati where the customer wants a Ford. Since I’m in cliche mode, it’s the old saying about good intentions paving the road to hell.

      Like

  2. Reuse comes at various stages in various forms in different degrees yielding a range of benefits. The benefits are significant and recurrent. This requires a policy and commitment to systematically create and maintain a Repositary of VALIDATED artifacts.

    Wriet to kenablersys@yahoo.com for COSAR–Cooperative Software Artifacts Repository within and across companies / domains. Educational and Training institutes may also participate.

    Like

  3. Hi Gene,

    I agree with your premise and conclusion, but it’s the middle part that I wanted to comment on. The sense I got (and maybe it’s just how I read it) was that the middle part was slanted against reuse, with more emphasis on the negative. I agree that reuse is hard, but also feel that there are many places where it makes sense. In fact, I believe that there is a long-term trend, specifically in product development, but also affecting IT, that makes it increasingly important.

    Historically, many products and IT solutions had a “box mentality”. What I mean by “box mentality” is a standalone, loosely-coupled solution (i.e. blood pressure device, bar code scanner, etc.). Over time, connectivity has increased, powered by wireless networking, routers and the Internet. As a result, an increasing amount of value is derived from interoperability (e.g. EMR integration with medical devices, OnStar, etc.). When this occurs, solutions that formerly were loosely-coupled from their deployed environments now become much more tightly coupled. And to complicate matters further, these products and IT solutions are forced to deal with a wide variety of environments. For instance, there are over 80 different EMR products, and at least as many variations of the HL7 “standard.”

    As a general rule, product companies are impacted by the deployment differences of all their customers, while IT environments not so much. But in these days of mergers and acquisition, cross-system integration, mobile computing and Cloud migration, I’m not so sure that large IT departments are immune from this.

    In summary, here are the factors that I think drive this:

    1. Opportunistic reuse on a small, localized scale isn’t hard. It’s a natural component of refactoring.
    2. Systematic reuse on a larger, more global scale is quite difficult. I believe you made this point.
    3. Determining payback before embarking is critical. This was your conclusion, and I agree whole-heartedly.
    4. Even when systematic reuse is justified, it requires a paradigm shift to be successful:
    a. People pursue reuse to achieve ROI by leveraging commonality (outcome-driven)
    b. Those who are successful, succeed because they do a stellar job of managing variability.
    5. Managing variability at a systematic reuse requires broad and deep understanding of contexts.
    6. Each context is an outer system which benefits from a solution, plus its external environment. This includes:
    a. The goals of the stakeholders for that outer system
    b. The relative priorities of these goals
    c. The forces (external forces of nature or imposed constraints) which help or hinder the achievement of these goals
    d. The extent to which forces make it difficult to achieve important goals (a.k.a. challenges or pain points)

    Within a context, you have like-minded behavior (similar goals and priorities) affected by similar forces (conditions and situations). However, what makes systematic reuse so difficult is that across contexts:

    1. The goals may differ significantly, or may be overlapping sets
    2. Even when the goals are the same, their priorities may be quite different (resulting in different trade-off preferences)
    3. The forces which impact each context may differ (or occur at different times, in different sequences).

    Many engineering practices, both in IT and product development are very solution-driven: narrow focus, dominated by short-term concerns. Clearly, there are advantages to this approach, such as scope reduction, problem simplification and an expediting delivery. IMHO, this approach is the primary reason that it is difficult to achieve systematic reuse. Successful systematic reuse requires more of a problem-driven (synthesis) approach to discover contexts and what makes them similar and different.

    The SUV is the poster child for attempting systematic reuse the wrong way. High ground clearance and flexible suspension is great for off-road enthusiasts, but causes fatal roll-overs for urban and suburban drivers. OTOH, Google’s Android platform is a positive example of successful systematic reuse. Samsung, HTC, and Motorola have leveraged their investment in the Android platform into a rapid succession of new smartphone and tablet products.

    So, I agree. Just because it’s difficult doesn’t mean you should avoid reuse. And just because, others have succeeded doesn’t mean you should just charge ahead. You have to study the risks and rewards, and you have to perform the practices that lead to success. And part of this means starting with smaller, lower-risk efforts and developing the necessary skills. Downhill skiing is exciting and dangerous. Great downhill skiers don’t ski the double black diamond slope on their first run.

    Regards,
    Charlie

    Like

    • Charlie,

      No argument whatsoever – excellent comment.

      My intent was not to convey that reuse was bad, merely that it should be done deliberately where the benefits exceed the costs. As you point out, where it’s done right, reuse can be a huge benefit.

      Thanks,

      Gene

      Like

  4. Agreed. You cannot have just one wheel type, and then try to fit it to all different types of moving object.
    The problem often is however, not that the rollerblade assembler tries to reuse a bus wheel and fails, but that he or she is unwilling, unable or simply unaware that they can reuse the perfectly good rollerblade wheels that are already in the parts catalog. That’s the problem we have to solve. It is the “not invented here” syndrom, and “my wheels are better than your wheels” attitude that often prevents reuse whilst the already available wheels are perfectly adequate for the task

    Like

    • Indeed, either end of the spectrum is likely to be detrimental, depending on the circumstances. My point in this, as in most of my posts, is that one cannot rely on ‘x is universally good’ rules of thumb. Picking tools and techniques according to your needs is the only way to avoid strolling into a blind alley.

      Like

  5. Pingback: Canonical Data Models, ESBs, and a Reuse Trap | Form Follows Function

  6. Pingback: Dependency Management is Risk Management | Form Follows Function

  7. Pingback: Dependency Management is Risk Management | Iasa Global

  8. Pingback: More on Microservices – Boundaries, Governance, Reuse & Complexity | Form Follows Function

  9. “This administrative complexity not only affects the developing team, but the consuming one also in the form of another dependency to manage.”

    It also encourages mires space for political trench digging and power games, which halt, if not _kill_, development and agility.

    Liked by 1 person

  10. Pingback: Microservices, SOA, Reuse and Replaceability | Form Follows Function

  11. Pingback: Dependency Management is Risk Management | IasaGlobal

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.