What we mean by "Component"

The Application Space (AppSpace) is about Component Oriented Programming. It wants to make easier composing software from local and distributed components, from synchronous and asynchronous components. But what is a component? Wikipedia´s definition is this:

A software component is a system element offering a predefined service or event, and
able to communicate with other components. Clemens Szyperski and David Messerschmitt
give the following five criteria for what a software component shall be to fulfill the definition:

    * Multiple-use
    * Non-context-specific
    * Composable with other components
    * Encapsulated i.e., non-investigable through its interfaces
    * A unit of independent deployment and versioning

A simpler definition can be: A component is an object written to a specification.

A quite well accepted definition of software components - which unfortunately haven´t found their way into mainstream programming. Most software developers are still "thinking just in objects", i.e. their main building blocks for applications are classes.

That´s an impediment for planning and building larger software systems. However, the Application Space is trying to make it easier on programmers to "think in components". We at Xcoordination therefore adopted a very simple and straightforward definition of components:
Our definition of "Component":
A component is a binary functional unit of code described by a separate machine readable contracts.

For the .NET platform - which we´re concerned with here - this is easily translated into:

A .NET component consists of two assemblies,
* one assembly defining the component´s (syntactic) contract,
* and one assembly implementing the contract.

This is how we recommend you interpret our definition of component for larger software projects. Components aggregate types into larger wholes like types aggregate fields and methods into larger wholes. Components are a means of physical abstraction. They embody responsibilities like classes and methods do - just "on a higher level".

For a start, though, it´s sufficient to just separate contract and implementation within the same assembly.

What´s a contract?

C# and VB require you to enclose statements in methods and to enclose methods in classes. (Yes, you can define structs too. But they are rarely used for more than aggregations of fields.) So you can think of contract implementations as classes.

But how can you define what a class is supposed to do, it´s syntactic contract? We recommend to use an interface. But if you like use a base class - preferrably an abstract one. Be careful though, any base class again is a means to define implementation details. So keep it as free of imperative code as possible.

Contracts are supposed to describe functionality, not implement it. They should be as declarative as possible, lest they need not be tested. Keeping them slim, i.e. free of implementation details also makes is quick to write them.

Here´s a sample contract:

interface IMathService
    int Add(int a, int b);
    int Mult(int a, int b);

And here´s a sample implementation of the contract:

class Simple Calculator : IMathService
    public int Add(int a, int b) { return a+b; }
    public int Mult(int a, int b) { return a*b; }

Together they constitute a simple component.

What follows from the definition

From the above simple definition of what a .NET component is some implications follow:
  • Since a component is binary it can be easily reused whereever it´s syntactic (and semantic) contract fit. There is no need to put reusability into the definition. If you should strive for reusability, though, is a completely differrent question we won´t tackle here. Suffice it to say, we deem reusability overrated.
  • Since a component is binary it´s of course a unit of deployment and versioning. If and when you version it, though, and whether you deploy each design time component as is on a production machine, again is a different question. Consider merging contracts and implementations of several components into larger "packets" for deployment using tools like ILmerge or NETZ.
  • If you follow our recommendation and use interfaces to describe a component´s contract the implementation truely will be a black box. It won´t be "investigatable". This is good encapsulation practice - and no need to put it into the component definition.
  • Since a component is described by a separate contract it´s easy to compose with other components. Separate contracts make components independent of any implementations. "Component meshes" thus can be wired-up by using DI containers.
  • If you truely isolate a contract from the implementation and put it in its own assembly you can implement all components in parallel. Each implementation just needs its own contract plus the contracts of any component it´s depending on. This is called Contract-first Design and can boost your productivity as well as increase your intensify your focus.

All in all we at Xcoordination deem component oriented development as fundamental for any non-trivial .NET software project. Use components as physical layers of abstraction above classes to make your code easier to understand and to keep your code more closely aligned with your architectural plan.

Last edited May 25, 2009 at 6:49 AM by ralfw, version 9


No comments yet.