7 Designing components
Writing in Byte John Udell tells us that 'Objects are dead!' and will be replaced by components. But he wrote this in May 1994, whereas objects didn't really hit the mainstream of information technology until around 1996/7. In fact, most CBD offerings that were around in 1994 didn't survive for very long after that: think of OpenDoc, OpenStep, Hyperdesk, etc. Probably the only significant survivor was the humble VBX. Currently, there are several understandings of what the term 'component' means. Some commentators just use it to mean any module. Others mean a deliverable object or framework: a unit of deployment. Still others mean a binary that can create instances (of multiple classes). Writers on object-oriented analysis tend to mean a set of interfaces with offers and requires constraints. The requires constraints are often called outbound interfaces. Daniels (2000) questions this and shows that while these aspects of a component must be defined, they do not form part of the component's contract. Szyperski (1998) defines a component as 'a binary unit of independent production, acquisition and deployment' and later 'A unit of composition with contractually specified interfaces and explicit context dependencies only'. We prefer: a unit of executable deployment that plays a part in a composition.
In many ways, VB is still the paradigm for component-based development. Components were needed initially because OOPLs were restricted to one address space. Objects compiled by different compilers (even in the same language) could not communicate with each other. Thus arose distribution technologies such as RPCs, DCOM, CORBA, and so on. In every case interfaces were defined separately from implementation, making OOP only one option for the actual coding of the objects.
In the late 1990s ERP vendors that surfed on the crest of the year 2000 and Euro conversion issues did well because their customers needed quick, all-embracing solutions. When that period ended their market was threatened by a return to more flexible systems that were better tailored to companies' requirements. One vendor was even quoted as saying that a large customer should change its processes to fit the package because the way they worked was not 'industry standard'. This arrogance would no longer be tolerable after 2000 and the vendors were seen to rush headlong to 'componentize' their offerings; i.e. introduce greater customizability into them.
A lot of the talk about components being different from (better than) objects was based on a flawed idea of what a business object was in the first place. Many developers assumed that the concept of an object was coextensive with the semantics of a C++ class or instance. Others based their understanding on the semantics of Smalltalk objects or Eiffel classes or instances. Even those who used UML classes or instances failed to supply enough semantic richness to the concept: typically ignoring the presence of rules and invariants and not thinking of packages as wrappers. Furthermore, an object will only work if all its required services (servers) are present. This was the standpoint of methods such as SOMA from as early as 1993. SOMA always allowed message-server pairs as part of class specifications. These are equivalent to what Microsoft COM terminology calls outbound interfaces.
From one point of view, outbound interfaces violate encapsulation, because the component depends on collaborators that may change and so affect it. For example, the client of an order management service should not have to know that this component depends on a product management one; an alternative implementation might bundle everything up into one object. For this reason John Daniels (2000) argues that collaborations do not form part of an object's contract in the normal sense. He distinguishes usage contracts from implementation contracts. The latter do include dependencies, as they must to be of use to the application assembler. That more research is needed in this area is revealed by one of Daniels' own examples. Consider a financial trading system that collaborates with a real-time price feed. The user of the system should not care, on the above argument, whether the feed is provided by a well-known and reputable firm, such as Reuters, or by Price, Floggett & Runne Inc. But of course the user cares deeply about the reliability of the information and would differentiate sharply between these two suppliers. This example suggests that we should always capture the effects of collaborations as invariants or rulesets in the usage contracts, if not the collaborators themselves. The rules in this case would amount to a statement about the reputability of the information provider.
Current component-based development offerings include CORBA/OMA, Java Beans/EJB, COM/DCOM/ActiveX/COM+, TI Composer and the more academically based Component Pascal/Oberon. What these approaches all have in common is an emphasis on composition/forwarding, compound documents, transfer protocols (e.g. JAR files), event connectors (single or multi-cast), metadata and some persistence mechanism. Differentiators between the approaches include their approaches to interface versioning, memory management, adherence to standards (binary/binding/etc.), language dependence and platform support.
From a supplier's point of view components are usually larger than classes and may be implemented in multiple languages. They can include their own metadata and be assembled without programming (!). They need to specify what they require to run. These statements could almost be a specification for COM+ or CORBA. Such component systems are not invulnerable to criticism. The size of a component is often inversely proportional to its match to any given requirement. Also, components may have to be tested late; an extreme case being things that cannot be tested until the users downloads them (although applets are not really components in the sense we mean here). There is a tension between architectural standards and requirements, which can limit the options for business process change. Finally there is the problem of shared understanding between developers and users. Szyperski discusses at length the different decision criteria used by each of infrastructure vendors and component vendors. He says nothing about the consequences for users. Can we deduce that users don't care about how components are developed? They certainly care about how they are assembled into applications.
Object modelling is about not separating processes from data. It is about encapsulation: separating interfaces from implementation. It is about polymorphism: inheritance and pluggability. It is about design by contract: constraints and rules. OO principles must be consistently applied to object-oriented programming, object-oriented analysis, business process modelling, distributed object design and components. However, there is a difference between conceptual models and programming models. In conceptual modelling both components and classes have identity. Therefore components are objects. Inheritance is as fundamental as encapsulation for the conceptual modeller. In programming models on the other hand components and classes do not have identity (class methods are handled by instances of factory classes). Thus components are not objects, class inheritance (or delegation) is dangerous and pluggability is the thing. So is there a rôle for inheritance? CBD plays down 'implementation inheritance' but not interface inheritance, but at the conceptual level this distinction makes no sense anyway.
When it comes to linking requirements models to analysis models, we can either 'dumb down' to a model that looks like the programming model (as most UML-based methods tend to do) or introduce a translation process between the models. The trade-off concerns the degree to which users and developers can share a common understanding.