reuse and component management

Text to do


'Reuse' is a misleading term. Cutting a chunk out of an existing program and adapting it to fit in another doesn't gain us much. Most of the work done on any software is done after its first installation; so we only gain substantial benefit if we use the same component in more than one software product. That way, enhancements and fixes done on it will benefit all the products in which it is used.  This is what Component Based Development is about: the idea that we will develop a library of components that will be used, in different combinations, in more than one software product.

But CBD isn't the only kind of reuse: the reusable artefacts don't have to be executable components in the COM or EJB sense. Within a reuse library we could find frameworks, tools, source code packages, design patterns, requirements models ...: any piece of work that can be separated and have limited dependencies on others.

reuse management

Managing reuse starts with separating Products which you deliver to your customers, from Assets which you use to generate the Products. The library has to be resourced separately from the products: it should be treated as a capital asset, and effort should be spent on enhancing it. Planning and organising the library is not a clerical job: it determines what products can be produced in the future, and is the job of the Chief Architect.

There are three important distinct views of the library:

  • The repository: the space in which the Assets are stored, with suitable search facilities. Some repositories are actual databases. Others are tangible only as catalogues of items available from diverse distributed sources. Or it may be that every Product includes a complete copy of the whole lot, configured differently for each customer.
  • The technical framework: the means whereby the Assets are combined to make Products. For example, they might be executable COM components coupled via a registry; or they might be C++ classes that have to be linked together; perhaps they all 'plug in' to a central application. Once linked, they have to interact coherently, so there will be some protocol definitions that they all adhere to. Some assets, such as design patterns, will have only an informal framework. There may be several such frameworks in one library.
  • The composition tool. A coherent library of components can be thought of as a language, and your Products are statements of the language. For example your library might form a kit of basic parts from which a variety of air traffic control systems can be constructed. To satisfy a particular customer, you choose and configure parts from the kit, and set their parameters, just as you write a statement in a formal language. The kit forms a language for describing ATC solutions.
    It's optional how literally you take this view. However, there are many cases in which it is useful to construct an actual language — whether textual or graphical — to help build products. As examples, think of workflow systems; and visual editors for GUIs.

Populating the library

There are two sensible approaches to deciding what goes in the library.

  • Product Line Architecture (or 'Family Planning'). The aim is to build a family of products, and we know in advance what the main variants will be (rather like car designers). We therefore design a framework in which the variants can be created by substituting one component for another.
    This works well where there is already lots of experience in the target field, and we know what variants we're going to have.
  • Evolution. After designing two specific products, we realise that they have a lot in common; maybe one was done by adaptation of the other. We do some extra work to see how a common framework with some variable parts could have satisfied both customers. The third product is delivered using the new assets; we maybe retro-fit to the first products so that they are easier to maintain in future. As each new order appears, there are inevitably refactorings that we need to do to the assets, but these gradually drop to a steady level.

Here are some faux pas not implicated in either of these strategies:

  • No adaptation. Components taken from the library should go into the products without adaptation. As soon as you change them, they've got a maintenance track of their own and you've lost much of the benefit of reuse. If a product designer thinks a component does almost but not quite what's required, a change proposal should be fed back to the library. However, it is accepted that usually, part of the design of each product will involve some 'glue' and some enhancement of library assets.
  • You ain't gonna need it. We don't put things in the library just because they might possibly be nice.  Nor do we over-generalise the assets, parameterising everything in sight. They will slow performance, introduce more bugs, and take your time up. We generalise only as much as:
    • we can see a definite need for, in immediately forseeable products; or
    • it doesn't cost too much and is just part of good separation of concerns.

Generalisation of material to go in a library is hard; and many cycles of improvement should be allowed for. It isn't worth generalising a piece of code into a component, or a design idea into a pattern, unless you think it will be used at least five times.

Maintaining the library

The maintenance of the library, whatever form it takes ('component kit' in this slide), needs to be resourced separately from any product, since no individual product project has the motivation to devote time to the benefit of other products.

One of the benefits of any form of 'reuse' is that we can deliver products rapidly: they are assembled from existing components. This means earlier feedback from the users, more opportunity to adjust what has been delivered to suit their shifting requirements. A corollary is that less 'ceremony' is necessary or appopriate: a less long-drawn out design process, less documentation, less thrashing out of detailed requirements before moving. (We can find out the requirements by putting a working prototype in front of them, just as fast as we could write the detailed spec by paper-heavy methods.) Typically, this rapid-feedback process is done incrementally, delivering [prototypes of] the central features first. (RUP, DSDM, eXtreme Programming are examples of this style.)

The same relationship exists between the product-builders and the component designers. The big difference is that more ceremony must be applied to the design of assets. A reusable asset will be used more (one hopes), so the economics makes sense. But a component has to be designed without knowing exactly which other components it will be coupled to, so specifying its behaviour, and specifying what it expects of others, is important; test harnesses should be devised as part of the component package, so that component builders can easily make sure a configuration is working properly.

One of the component designers' main inputs will be material that was initially designed for one product, and has been identified as worth generalising. (In fact, its designer should also take part in the generalisation -- the figures here represent roles rather than people.)  Generalisation is not an easy task. Several cycles of subsequent enhancement should be expected.

What's in an Asset?

Library assets include:

  • standards and guidelines
  • Patterns
  • modelling frameworks
  • software frameworks
  • source code packages (dangerous! encourages adaptation)
  • executable components
  • interface and protocol definitions
  • common domain model on which other models are built
  • tools, platforms, infrastructure

Each asset should have:

  • controlled name, version and variants -- no changes after publication
  • controlled compatibility relationship to previous versions
  • defined and not too many dependencies on other assets
  • catalogue entry with useful search terms (so that designers can find it)
  • documentation for users — succinct but sufficient, particularly in respect of how to specialise or parameterise it
  • documentation for maintainers — ditto
  • robust interface: few and documented assumptions about the characteristics of whatever it might be plugged into or used in conjunction with
  • test harnesses or built-in checking  (for software, and for interface definitions) — so that product builders can easily check that the configuration they build is working properly.

Robustness and verification are one of the biggest benefits in reuse, and also one of the biggest challenges. They're a benefit because a component that has been used in many contexts is very likely to work properly; they're a challenge because, when you design a component, you don't know what other components it will be working alongside (in contrast to merely modular development). A component's designer therefore has to be extra careful that it will work in all the situations allowed by the documentation --- even in contexts not dreamed of when it was designed. This requires careful verification, and is one of the reasons for the 'high ceremony' of component design.

Product Line Design

The two separate development loops mentioned above take care only of the Evolutionary approach to library planning. The Product Line aspect — in practice, all libraries have some mixture of the two — needs to be dealt with by a longer feedback path that looks at shifts in the product market. It plans what components should be designed, to enable construction of the products that will be in future demand.

The coherent design of the library contents as a kit from which a family of products can be designed is called 'Product Line Architecture' or 'Component Kit Architecture'. Again, it needs to be a separately resourced activity.

In practice, there aren't always just two separate layers, components and products. Within a small product, there may be several assets used in many places in the product, which may have several variants. The product may itself be part of a larger family and draw on a larger common library. Elements in that library may themselves be built from a more basic kit. So the picture in this slide is fractal: it can be interpreted at many different scales, and each of the activities can itself be composed of smaller such loops.

Reuse Teams

One successful organisation of reuse involves a reuse team, many of whose members are seconded to product teams. These people take care to think about how the assets can be used within their products; and think about how requirements can be fed back to the asset library, and what locally-devised material might be generalised for the library.

There is also an Architectural staff attached to the library. Their roles include: a clerk to keep track of the contents; framework and technological underpinnings experts with a keen understanding of the mechanics of specialisation and composition; an Architect who coordinates overall about what should be in the library (including designers' guidelines and patterns, not just software components); and a market analyst who understands the requirements on the product family as a whole (takes care of that outer feedback loop).

Some folk are particularly good at the lower or higher-ceremony styles of work, and some are better at relating to end-users. (The product designers should get to see a lot of the end-users.) The rest should be moved occasionally. When something in a product is identified as good for generalisation, move its designer onto the reuse team to give them space to make a good robust component of it.

complete solutions for component design
(consultancy, courses, workshops, mentoring, seminars, development)

email us  or  telephone   UK: 01625 850 839    International: +44 1625 850 839