Previous article

Next article

A Taxonomy of Components

Markus Voelter, Independent Consultant, Germany


PDF Icon
PDF Version


The notion of a component is not really well defined for practical purposes. This is, because the term is used to denote many different things. So, instead of defining the term once and for all, we present a taxonomy that shows the different features of a component.


There exist several definitions for the term component, one of them by Clemens Szyperski:

“A software component is a unit of composition with contractually specified interfaces and explicit context dependencies only. A software component can be deployed independently and is subject to composition by third parties.” [SZY]

We will use it as a starting point for our further discussion: Let’s consider some parts of this definition in detail:

  • “a unit of composition”: Calling a component a unit of composition actually means that the purpose of components is to be composed with other components. A component-based application is thus assembled from a set of collaborating components.
  • “contractually specified interfaces”: To be able to compose components into applications, each component must provide one or more interfaces. These interfaces form a contract between the component and its environment. The interface clearly defines which services the component provides. It thus defines its responsibility.
  • “explicit context dependencies only”: Usually, software depends on a specific context, such as available database connections or other system resources being available. One particularly interesting context is the set of other components that must be available for a specific component to collaborate with. To support the composability of components, such dependencies be explicitly specified.
  • “can be deployed independently”: A component is self-contained. Changes to the implementation of a component do not require changes (or a reinstallation) to other components. Of course, this is only true as long as the interface remains compatible.
  • “third parties”: The people who assemble applications from components are not necessarily the same as those who created a component. Components are intended to be reused - the goal is a kind of component marketplace where people buy components and use them to compose their own applications.

This definition of the term component is very generic and thus it is not surprising that the term is used to describe rather different concepts: subsystems, DLLs, JavaBeans, ActiveX controls, .NET assemblies, Enterprise JavaBeans, COM+ components, CORBA components and more. The purpose of this article is to try to clarify these different views by providing a taxonomy for components. We therefore don't try to give one concise, closed definition. Instead, we will show the different features and characteristics a component must or can have, thereby classifying the different kinds of components as they are used today.


The following discussion centers around a feature diagram for the concept „component“. Feature diagrams are a notation that is used as part of feature-oriented domain analysis (see [FODA]), a technique used for analysing the different products to be covered by a software product-line. This approach, as well as the diagram notation, is extensively explained in [GP]. For those who don't know the notation, rest assured that the article is written in a way that will clarify the diagram semantics on the fly. The diagram we use as a basis for our discussion is depicted in the illustration.

Fig 1: A feature diagram for components

In this diagram, the features (denotes by the boxes) of the concept component are described, which is located at the top of the diagram. The boxes directly connected to component are the direct subfeatures of a component. The little circles at the edges connecting the features define the semantics of the edge. A filled circle means „mandatory“. Thus, every component has a feature service interface, is of a certain kind, requires certain resources, and plays a certain role, and it is deployable. Optionally (denoted by the outlined circle at the edge), it provides meta information. Let's elaborate on these issues.


As already stated in Szyperski's definition, a component „is a unit of composition with contractually specified interfaces“. It is thus necessary that a component specifies the services it provides to clients (which can also be other components). Typically, these services are specified in terms of operations including their parameters and types in a service interface. Ideally, this interface also specifies the semantics of the operations. There are several ways how this can be done: the most popular ways are based on design-by-contract [DBC] (i.e. pre- and postconditions for operations) or state machines (which specifies the legal invocation sequences and possibly timing constraints). In most component-based systems, the service interface does not specify any semantics however, only the provided operations and their signatures.

Because a component is intended to be (re-)used as a building block during the assembly of complete applications, it is necessary that it specifies the resources it requires to run. Typical resources are database connections, message queues or the service interfaces of other components that the current component uses to have some services fulfilled. Ideally, the resources should be specified in a way that allows the environment to detect whether an application – a collaboration of components – can run, or whether resources are missing. Enterprise JavaBeans [SCP], for example, specify these resources as part of the XML deployment descriptor, the Small Components prototype [SMC], a component framework for small devices, uses a normal Java interface, together with some naming conventions, to specify a component's resources.

The next feature to be discussed is the role a component plays. As the feature diagram shows, a component can play one of several roles (a one-of-many selection is denoted in the diagram by the outlined-filled arc connecting the three subfeatures of role). The most typical are:

  • A component can represent an entity such as a person, an employee or a text edit field. It has state, which can be persistent.
  • It can represent a service. This means it is typically stateless. An example would be a component that provides an operation to calculate the VAT for a specific product or do some mathematical calculations, or a wrapper around some physical device or legacy system.
  • A process component is one that encapsulates a process like the filling of a shopping cart or a complex workflow. It is typically stateful, usually it is not persistent.

A component also is of a specific kind. This is a very important concept because people typically confuse these two kinds of components and end up in endless discussions. Components can either be technical or logical. A logical component is simply a package of related functionality. It can be some kind of subsystem, a DLL or a complete, standalone application that runs as part of a larger system. Logical components are mainly a way to keep the complexity of a system under control, and to organize version control or project management issues. Often, the other features (like service interface, resources, role, and meta information) are specified informally – not necessarily tool-readable. There are basically three kinds of logical components. Domain components provide business logic; data components provide access (and optionally, validation and conversion) to data; user components are part of the client application and typically provide user interface functionality and/or access to domain or data components. There is also the notion of a business component – an aggregation of data, domain, and user components that embody a complete subsystem.

On the other side there are technical components. These are technical building blocks to assemble applications. Here, the concepts explained above (service interface, role, resources, meta information) are specified „formally“, they can be evaluated and understood by a tool. Such a tool is usually called a container. The container provides a runtime environment for the component. The component cannot live (i.e. run) outside a container. Their single purpose in life is to be used inside a container. Why is this so? The reason is, that we want to apply the concept of separation of concerns: we want to keep different aspects of an application separated into different technical artifacts. A container handles the so-called technical concerns for the components. What these technical concerns are, depends on the application domain in which the component architecture is used. In business systems the technical concerns are things like transactions, security, failover or load-balancing. The container handles these technical concerns for the components – the component developer does not need to implement them manually in his code. To allow the container to host a technical component and handle the technical concerns for it, the component has to provide a technical interface, with which the container can access all hosted components in a uniform way, for example to configure them, start them, stop them, query them for their state or whatever (see [SCP] for details).

Components optionally provide meta information, which means that they can provide information describing themselves. The specification of resources is often part of that meta information. Meta information can be available for runtime or build time, or both. Build time meta information is important for application assembly tools, tools that support the assembly of applications from components. Runtime meta information can be used by clients to gain insight into the features a component can provide to them.
Today, there are two main uses for technical components. They are either used in client applications, or, in multi-tier systems, on the server. The container for client components is typically an IDE where the components are configured at development-time. These client components can either be visible or invisible. Server components usually encapsulate business logic in mutli-tier systems. The container is typically a part of an application server.

There is an important relationship between logical and technical components: in many cases, logical components are aggregations of technical components – i.e. technical components are used as building blocks for logical components.

As a last point, components are separately deployable. In a component-based application, it is possible to replace a component with a new one, as long as it provide the same, or a compatible service interface, usually at runtime. The significantly simplifies deployment, maintenance and operation.


Let's look into some concrete examples for the concepts we explained above. Let's start with client-side componens. The most popular examples are ActiveX controls and JavaBeans. Both are typically used as building blocks in IDEs, usually they are visible. They are used as text fields, timers, or more complex widgets, or provide access to databases, etc. ActiveX controls as well as JavaBeans provide meta information at build-time and at runtime. In case of JavaBeans for example, the meta information can be accessed either by Java's reflection or by querying the associated BeanInfo class. In multi-tier systems, these components are used as user components, in client/server or standalone applications they are used as user, domain and data components.

In case of server-side components, there are three mainstream examples: Enterprise JavaBeans (EJB), Microsoft's COM+ and CORBA Components. They are used in enterprise business applications. All reside in a container which takes care of transactions, security, load-balancing, failover and other features. Again, they provide meta information, mainly for use at build time (or deployment time). In case of EJB, this is an XML file called a deployment descriptor, in case of COM+ these are attributes stored in the COM+ registry. In all cases, the components provide a technical interface for the container (called SessionBean or EntityBean in case of EJB). The container uses it to control the (not always trivial) lifecycle of component instances. These components also specify the resources they need in order to allow the container to povide them to the components. In the CORBA Component Model, for example, they are specified as part of the configuration XML file. These server components are never used as client components, because the containers are rather complex and not available at the client site. Usually, they are used as domain components, sometimes also as data components. There are different specifications for service, process and entity components. They typically differ in their lifecycle and in the services the container provides for them. For example, the EJB container provides concurreny synchronization for Entity Beans, but it does not provide this feature for SessionBeans.

Windows DLLs are thus not really technical components. While the exported operations can account for the interface, but the don't really provide meta information. They also don't specify the resources they require. There is also no container that provides services for them. A technical interface is also not available of course. Their purpose is a way to enhance reuse, and to allow the dynamic loading of application functionality. .NET assemblies are roughly in the same category, althoug they do feature a sophisticated metadata facility. Standard metadata (which types are in the assembly, which modules, and which additional resources) is added by the respective compiler and it is even possible for the developer to add additional metadata items to types, operations and fields using .NET attributes.


The goal of this article was to define the term component as it is used today in the industry. Of course, this is also just the opinion of some people, those with whom I discussed the ideas during the writing of this article. If you have another opinion or any comments, I'd be glad to hear from you at



[DBC] ISE; An Introduction to Design by Contract.

[FODA] SEI; Feature-Oriented Domain Engineering,

[GP] Ulrich Eisenecker, Krzysztof Czarnecki; Generative Programming, Addison-Wesley 2000

[SCP] Markus Voelter, Alexander Schmid, Eberhard Wolff; Server Component Patterns, Wiley and Sons, 2002

[SMC] Small Components Project,

[SZY] Clemens Szyperski; Component Software - Beyond Object-Oriented Programming, Addison-Wesley, 1999

About the author


space Markus Völter works as an an independent consultant for software technology and engineering. He focuses on the architecture of large, distributed systems. Markus is the author of several magazine articles and patterns, a regular speaker at conferences and co-author of Wiley's Server Component Patterns. He can be reached at or at

Cite this article as follows: Markus Völter: “A Taxonomy for Components”, in Journal of Object Technology, vol. 2, no. 4, July-August 2003, pp. 119-125.

Previous article

Next article