Chapter 11
Modelling Software Components and Services
This chapter looks at two quite different approaches to the idea of reusing software that has been developed by others. The concept of the software component has been around for many years—indeed, the concept of reusable blocks of software was put forward at the inaugural Software Engineering conference in 1968 by Doug McIlroy. Building on this concept, Component-Based Software Engineering (CBSE) has had the goal of enabling a software developer to be able to make use of pre-existing reusable ‘chunks’ of software in order to create (or ‘compose’) an application. In many ways the service paradigm represents an evolution of this idea. While it largely aims to do the same thing, the means of realising it is very different. Here the software itself is provided by third parties, and is hosted and executed elsewhere (typically in the cloud) rather than being embedded within the application, enabling easy substitution of different providers.
Each of these technologies poses challenges regarding both about how to design the reusable elements themselves as well as how to design an application to make use of existing resources. For the moment though, we concentrate on the forms those resources can take and how to model them, leaving the question of how to design applications around them until a later chapter. However, since reuse is so important for both, we begin by discussing its role and influence.
11.1Reuse
For other domains in which design performs an important role, the idea of reuse is fairly well established and takes a range of forms. It is sometimes associated with the abstract reuse of design ideas and experiences, rather than of physical elements, and we will look at this aspect in Chapter 15 when we examine how the concept of a pattern can be employed.
Where the manufacturing cycle is important, then it is also associated with the interchangeability of physical components, not least because creating ‘product lines’ can help reduce the cost of the individual product1. Mechanical engineering in its many forms makes extensive use of components, as do the electrical engineering and construction industries. In all of these, the use of standardised units helps with manufacture and maintenance. Their use also changes the nature of the design process by introducing the notion of composition.
Organisational and other processes themselves can be reused too. We can see this in the way that production lines in factories can be re-organised and re-purposed to create new products.
Successful reuse of pre-existing elements is commonly based upon two important characteristics.
The first is that the role of a reusable component is associated with some well-defined functionality. Most physical components have very well-defined roles (switch, pump, door handle, starter motor, etc.) making it possible for the designer to select suitable items from a catalogue.
Secondly, the components themselves usually have well-defined interfaces, enabling ready composition with other components that meet the same standard, as well as easy substitution of one manufacturer's component with one from another maker. This can also help with identification of suitable ones in a catalogue. In manufacturing this can mean that there may be several manufacturers who are able to provide a particular component (‘second sourcing’), providing users with confidence that they will be able to obtain adequate supplies.
These are not accidental properties, but rather, they are ones that arise from economic factors. These factors include the need to minimise the cost of fabricating an item; pressure to maintain a marketplace position; and the end-user's need to protect their supply chain (here the end-user will be the manufacturer who is making use of a given component in their own product). The adoption of interface standards may be motivated in a number of ways: one manufacturer may be so dominant that their interface becomes widely accepted; an industry (or professional body) may take on the role of defining the necessary standards (as has happened widely with electrical connectors); or a group of manufacturers may come together to agree on a common standard.
Reuse can be facilitated by the availability of catalogues of components. However, the way that such catalogues are used during the design process appears to be less well understood. Pugh (1991) provides an example of this in the domain of electronic engineering, in quoting from Cooke (1984).
Similarly, in Pahl & Beitz (1996), a textbook that is widely cited as a repository of engineering design knowledge, the discussion of ‘design catalogues’ is almost entirely confined to consideration of how such a catalogue will be constructed rather than how it might be used.

If we turn our attention to the reuse of software, we find that, despite the lack of a manufacturing phase, reuse of software components has had a long history of success in some areas. An often-cited example is the set of mathematical and statistical functions provided in the NAG (Numerical Algorithms Group) library that was first released in 1971. The set of functions and the programming languages supported has gradually expanded over the years, and the routines it provides do of course meet our two criteria above, having well-defined functionality and well-defined interfaces. Other examples include user interface packages such as tk and tools such as MATLAB® that provide an environment of ‘components’. Component models such as CORBA (Common Object Request Broker Architecture) have assisted further by defining interface standards to enable local and distributed components, possibly written using different programming languages, to work together.
However, because software is so easily adapted and modified, it would also be true to say that examples of wide reuse, in the sense of embodying one software product within another, are relatively rare. Where they do occur then there may be special factors that constrain this freedom. (Network protocols provide a good example of this—there is little point in producing unique network protocols if you want your software to work with other applications.)
Indeed, although the benefits of reuse are often extolled by software engineers (and vendors of software), for example, when considering the benefits of an architectural form such as the object model, attempts to incorporate it more fully into software development practices have not been widely successful. In the rest of this chapter we describe two approaches to software development that focus on reuse, and examine the issues associated with their creation and use.
11.2Modelling software components
The idea of component-based software engineering (CBSE) began to attract greater attention in the 1990s, and in some ways the concept of a component formed an evolution of the idea of the object. And, as with objects, ideas about precisely what constitutes a component could be difficult to pin down. Indeed, when writing an introduction to a special journal section on CBSE, Brown & Wallnau (1998) observed (slightly tongues-in-cheeks), that:
Note though, the use of the word ‘practice’, as it could certainly be argued that one of the motivations of research into CBSE was to seek something that could be more tractably ‘engineered’ and composed together than objects.
One of the challenges of codifying CBSE was to determine just what a component is. An early definition from Brown & Short (1997) very concisely described a component as:
Note too that this definition made no explicit assumptions about architectural style—so that a component could be realised as anything from an object to an operating system. The emphasis here is upon reuse (needing a clearly specified interface) and upon the idea of independent delivery. This second aspect is important since it implies that a component should not be aware of its context, especially in terms of any embedded dependencies or the expectation of the presence of some shared resource. There is also the implication that a component needs to be integrated with other components in order to provide the overall system functionality. In other words, it is a part, rather than a whole.
The pioneering text on software components by Szyperski (1998) provided a rather more extensive definition of what a component was considered to be.
While addressing the same properties as the more abstract definition provided by Brown and Short, this added the concept of black box reuse, required if it was to be used by third parties.
A slightly more evolved definition was that provided in Heineman & Councill (2001), where a software component was defined as:
This definition is interesting because it separates out two further supporting concepts, which are those of:
the component model that incorporates ‘specific interaction and composition standards’; and
the composition standard, that ‘defines how components can be composed’ to create a larger structure.
Both of these are important concepts in terms of considering how we can design with components, and also how components themselves should be designed in order to be usable. Indirectly, they also raise the question of architectural style, and the extent to which the process of composition may need to be confined to applications using an architectural style that conforms to the ‘standard’ being used.
None of these definitions are really contradictory. Where they differ is in the level of abstraction required to express the ideas, and which of the many aspects of a component they emphasise. It is worth noting that there may also be business factors that influence the component model and its acceptance (Brereton & Budgen 2000) (a more business-focused view of CBSE is also presented in Brown (2000)).
And as we will see when addressing the second topic of this chapter, the evolution of these definitions has distinct parallels with the emergence of the idea of a software service.
11.2.1Component characteristics
Of course, not only have ideas about the nature of a component evolved since the concept was first envisaged in 1968, the forms of components have too. As Crnkovic, Stafford & Szyperski (2011) observe:
In discussing the idea of reuse, the two characteristics that were identified as being essential for a component of any form were:
well-defined functionality
well-defined interfaces
A further characteristic, which is probably implicit for non-software forms of component, but which needs to be explicitly stated for software components (because of the nature of software) is that of independence. This avoidance of any context-specific dependencies follows on from the ideas above. In practice of course, some dependencies are difficult to avoid, particularly where these related to issues such as architectural style, but where these do exist, they need to be made fully explicit. Figure 11.1 illustrates this set of characteristics.

Figure 11.1: Characteristics of a software component
If we look at other domains, we might note that there are often implicit context-specific dependencies. For example, the starter motor for a car will depend upon the availability of an electrical supply with a specific voltage and power rating. However, software dependencies can be more subtle, and so to ensure that a software component can be treated as a black box as far as is reasonably possible, such dependencies need to be made explicit in the specification. (As an example of the need for this, and of the difficulty of ensuring it is comprehensively achieved, see the analysis of the $500 million failure of the Ariane 5 rocket in 1996 that is provided in Jézéquel & Meyer (1997).)
We might note here that the UML component diagram is a very specific interpretation of the concept and of little use in a CBSE context. Indeed, perhaps because the concept of a component lacks any association with a specific architectural style, there are no diagrammatical forms that have been widely used for modelling CBSE implementations.
However, that said, many aspects of component use can be modelled using existing notations. In particular, issues related to functional and behavioural modelling can often be modelled using the forms commonly used with objects, such as activity diagrams, statecharts and sequence diagrams. What is not so readily modelled is the constructional viewpoint, although for many purposes, components can be modelled by adapting existing forms of class diagram.
11.2.2Component frameworks
Commonality of architectural style does not guarantee that components of different origins can be easily integrated to create an application. This issue, termed architectural mismatch was first identified in the context of seeking to compose an application by making use of existing objects (Garlan, Allen & Ockerbloom 1995). Attempts to create new applications from objects that had been created by different sources revealed that these made different, and incompatible, assumptions about the way that the object model was organised. When the original analysis was revisited in (Garlan, Allan & Ockerbloom 2009), the authors concluded that the reuse of components still formed a challenge, and indeed, that while the expanded computing landscape had reduced some of the earlier problems, it also introduced new ones.
What sort of assumptions created the problems? In the original (1995) study there were four general categories of assumptions that could result in mismatch. These were:
the nature of the (other) components, including the control model;
the nature of the connectors and the protocols used;
the global architectural structure; and
the construction process.
There were also three aspects regarding the ways that components interact where assumptions could produce mismatch: the infrastructure; the application itself; and interactions between peer components. None of these were issues that are strictly matters of design, although they might constrain design choices.
The later study identified some changes that had altered the situation; greater use of reusable infrastructure; use of standard interfaces such as web browsers; extensive use of open source software; and more sophisticated development environments. They also noted the emergence of architecturally specialised design domains. However, this more distributed context introduced such issues as trust between components; dynamic reconfiguration of systems; system evolution; and technical debt in the form of being locked into a specific architecture.
The idea of the framework as a means of imposing a common component model has formed an important element in the evolution of CBSE and of components themselves. It has also helped to address many of the issues identified above. While early ideas, such as those illustrated in Figure 11.1 assumed that components would be integrated to form monolithic software applications, the use of frameworks has allowed for more loosely coupled and distributed use of components, while also providing the necessary protocols for interaction between components. Figure 11.2 illustrates this evolution.

Figure 11.2: From monolithic construction to frameworks
So, what is a component framework? It can be summarised as being a set of formal definitions for the interfaces between components, where the definitions establish a set of protocols through which components will interact and cooperate within the given framework. In turn, these protocols may include ‘naming conventions’ used for the methods in an object that provide particular functions, the requirement to provide particular functions, and the operational procedures required for a component to declare itself available for use, and for others to request its services.
There are many frameworks (of course). We have already mentioned CORBA, which is maintained by the OMG (Object Management Group) that we encountered in the last chapter in the context of UML. CORBA has mapping to many implementation languages and the ‘client’ of an object can access that object only through the protocols of its published interface. There are a number of frameworks provided by commercial vendors, such as Microsoft's. NET and of course the open source frameworks, such as Apache Spark. There are also many frameworks aimed particularly at Web applications, with J2EE providing an important Java-based example.
For the purposes of this chapter, the details of particular frameworks are of less importance, what matters is that they exist—and that the choice of a framework has therefore become one of the design activities. And like other design activities, this is one that can involve complex trade-offs between many different factors—and inevitably, the choice creates a long-term technical debt.
11.2.3Designing components
The design of the actual components can be considered as having two goals. The first of these is to achieve the three general component characteristics identified earlier, in order to ensure that a component can be “deployed independently”. These require that a component:
possesses well-defined functionality;
provides a set of well-defined interfaces;
clearly specifies any explicit dependencies.
And over and above that is the second goal, of conforming to the standards of a particular component framework. This aspect is likely to be supported by a range of tools (depending on the choice of framework), even down to the naming convention for any identifiers that are to be used for externally-visible methods.
Returning to the question of functionality (a major motivation for creating components), designing components to be reusable does imply that the designer should strive to make the component as general as is reasonably possible. This is not an argument to use an excess of ‘bells & whistles’ or a ‘swiss army knife’ approach, indeed quite the opposite. Making a component do one job and do it well was an important philosophical underpinning for the Unix operating system when it was developed in the 1970s. Using simple tools that connected together readily via standard mechanisms helped users create their own applications with only limited effort (or even programming knowledge). And as Unix continues to underpin much of our computing infrastructure, we can reasonably assume this was a good principle to adopt elsewhere.
The paper by Crnkovic & Larsson (2002) provides an interesting case study on component use. The authors examine the evolution of two components within the application being studied (a control system package used for industrial applications). While not specifically concerned with component development, this still examines how key component characteristics affect the two particular aspects being studied: evolution of components across platforms and replacement of proprietary components with industry-standard ones. And, although the two components have relatively low-level roles (one can be considered as middleware, while the other is a class library), the general experiences may well have wider generality.
Some of the particular issues that the case study identifies from the viewpoint of designing individual components are as follows.
The benefit of using larger components that are easy to reuse, in preference to smaller ones that could be developed in-house.
The high cost of maintaining backward compatibility with early installations (this arose largely because the application being studied was a ‘product line’ so creating additional technical debt).
The need to separate out those features of a component that depend upon platform interactions in order to assist with ease of change.
It is worth noting here that components can be relatively costly to create. In Szyperski (1998) it is suggested that developing a reusable component could require 3–4 times the resources needed for a ‘non-component’ implementation. However, since some of these additional costs arise from external factors such as evolutionary changes to the component framework, it is difficult to predict the additional overhead involved in using a component. However, it is worth noting that unless there really is good scope to make reuse of components, or an application can be largely created using existing components with only a few additional specialised ones being built, developing components may not make economic sense. (A good example of where extensive use is made of existing components is the common practice with web applications of making use of component frameworks to build a user interface.)
11.2.4COTS
COTS stands for “Commercial Off The Shelf”. Use of COTS components can be regarded as representing an extreme, in the sense that the end user (designer) or integrator has no control whatever over their form and properties, and no knowledge about their workings. So a COTS element is one that is quite expressly black box in its nature.
However, in a software context, this view is probably something of an extreme position. As Carney & Long (2000) point out, what is usually termed COTS software spans something of a range of forms, some of which are capable of some degree of parameterisation, and with the extent of any modification often depending upon the financial and political ‘clout’ of the customer.
The main issue with the use of COTS is really concerned with the integration of such components, and so we leave further discussion of the use of such components for Chapter 16.
11.3Modelling software services
As described in the preceding section, and illustrated in Figure 11.2, concepts about how software components could be composed evolved with developments in technology. Early ideas about CBSE were centred upon using tightly coupled integration to form a monolithic application image that would execute on a local computer. With time, this evolved to employing much more loosely coupled forms, using frameworks for interconnection, with the components possibly being distributed across a wide network. And although there was always some expectation that components could be provided by third parties, with the NAG library being a good example, the use of more loosely coupled environments introduced greater emphasis upon related issues of trust and dynamic reconfiguration.
The concept of a software service can be viewed as representing the next step in that evolution of reusable software components. Indeed, one way of thinking about services is as remote components that are very loosely coupled, so that the application making use of them does not need to know anything about how they are realised. This progression is illustrated in Figure 11.3. Here the service sources are shown as miniature ‘clouds’, and indeed, the idea of software services has been an important underpinning for the concept of a cloud.

Figure 11.3: The evolution from components to services
Service technologies, in one form and another, emerged around the millennium, and the different practices of using services to create applications have resulted in a variety of descriptive terms such as Software as a Service, Service-Oriented Architecture (SOA), web services, as well as a large range of acronyms that describe the protocols used to support the various activities involved (Turner, Budgen & Brereton 2003). Services are usually accessed and delivered across the web, often by third-party providers.

Service models focus upon separating the possession and ownership of software from its use. By delivering software's functionality as a set of distributed services that can if necessary be configured and bound at the time of delivery (ultra-late binding), provides a highly flexible strategy. Of course, the end user still needs to have some form of application that incorporates a set of business rules, but this can be fairly minimalist and only needs to specify what services are needed, not how they are to be provided. Figure 11.4 shows two forms of service model. Model a) is one where this is organised on a supply-led basis, using a pre-determined range of services from a remote provider (a step on from distributed components, but still using a fixed profile). Model b) shows how this can be organised on a demand-led basis, involving an additional integration layer.

Figure 11.4: Supply-led and demand-led service models
Basic service description, discovery, delivery and composition are largely organised using XML-based protocols.
SOAP (Simple Object Access Protocol) provides a message format for communicating with, and invoking, web-based services. (REST is also used, but historically, SOAP was the main protocol employed with web services.)
WSDL (Web Services Description Language) is used to describe a service in terms of its acceptable data types, methods, message format, transport protocol and end-point uniform resource identifier (URI).
While these are largely sufficient for supply-led configuration, the additional elements needed for managing demand-led service use require a set of additional protocols to scope out the additional information required.
Figure 11.5 shows the basic mechanics of service use. The service consumer makes a request for a service. This may be a request for a specific service from a particular provider, but if not, the request goes to some element that provides for dynamic composition or orchestration of services (as in the diagram). This then negotiates with one or more possible providers, depending on the business rules that are specified, and then selects a particular service provider, which is then bound to the service user for this transaction. The actual service is then provided through the protocols embodied in that particular service description.

Figure 11.5: The elements of service use
This is of course a fairly simple single transaction, and providing for a user's need may well require that several services are composed together in order to perform a specific task. Note also that the same symbol has been used for both the service consumer and the service provider to emphasise that a consumer can itself also be a provider.
Modelling both the realisation of a service, and also its use is clearly a fairly challenging issue. There are no specific service modelling notations, and like components in general, most modelling appears to be performed by using existing notations. Those provided by the UML can be useful (with the benefit of having drawing tools available if required), as are DFDs (Anjum & Budgen 2017).
A particularly distinctive element in the process of service composition is the presence of the business rules. Although these are normally a factor to be considered when designing applications, they are usually implicitly embodied in the design process (essentially forming an element of the design specification). However, when using software services, the business rules need to be made explicit, since ensuring that the application conforms to these needs to be a part of the dynamic composition process. Modelling these rules can add a further challenging element when using a service model.
11.4Empirical knowledge about modelling components and services
The corpus of empirical studies related to both components and services is limited. As with objects, attempting to perform meaningful empirical studies during the emergent period for a technology, when the element being studied is not particularly well-defined is rather challenging. So, not surprisingly, the available primary studies tend to be a mix of case studies, surveys and experience reports.
11.4.1Empirical knowledge about components
The systematic mapping study by Vale, Crnkovic, de Almeida, da Mota Silviera Neto, Cavalcanti & de Lemos Meira (2016) looks at studies related to CBSE over the period 1984-2012. The authors analysed some 1231 primary studies and examined the profile of research that these revealed for that period. Not surprisingly perhaps, they observed a decline in publication rates in the 2010s, since as they noted “CBSE has been integrated into other approaches, such as service-oriented development, software product lines, and model-based engineering”.
They noted that the main objectives for adopting CBSE tended to be non-functional ones such as increasing productivity, saving on cost, improving quality etc. They noted that there were “few studies that measure the effort involved in building for reuse” and suggest that industry experience is that “building reusable components on average requires three to five times more effort than building the same function but not building for reuse” (similar to Szyperski's estimates).
While the literature identified more than 50 component models, with the four most frequently addressed including CORBA. They also identified a wide range of domains in which CBSE has been applied and observed that the provision of support for these “explains the large number of component models”, with these differing chiefly in term of being realised to meet the needs of a domain, rather than in terms of basic principles.
11.4.2Empirical knowledge about services
Few systematic reviews on the use of software services are available, and those that are, tend to be looking at rather specific research issues rather than at questions about the effectiveness of services.
Key take-home points about modelling components and services
Modelling the attributes of software components and services uses a range of different forms, but to date modelling has tended to use existing notations rather than develop any that are specific to these technologies.
Reuse. This forms a major motivation for the adoption of components, whether close or loosely coupled.
Component characteristics. Components are characterised by having well-defined functionality, accessed through well-defined interfaces, and with any dependencies being made explicit. Ideally, a component has very few (if any) dependencies, so aiding its composition within applications.
Component frameworks. The use of frameworks helps address the need to publish the interfaces of components, as well as aid loose coupling between components, and the choice of a framework is an important architectural decision.
Software services. Can be viewed as an evolution of components, whereby the services themselves may be provided by third parties and are very loosely coupled to the application, allowing for late binding to particular providers.