The Composition Design Pattern

You may have heard the expression “prefer composition over inheritance“.

But what does it really mean? What’s wrong with inheritance? Even the Wikipedia article on composition over inheritance is using classes and inheritance to explain composition. If composition is so much better than inheritance (at least sometimes), then why do we have to explain composition in terms of inheritance? And why do most modern programming languages and platforms support classes and inheritance syntactically but not composition? What would a programming language even look like if it had syntactic support for composition? Furthermore, what even is the design pattern for composition?

Many of the examples you see from cursory searches online simply show one class containing references to others and that’s about it. This kind of overly simple example seems to acknowledge the problem without really explaining the full solution and it’s completely framed in a context of inheritance. Simply introducing classes containing references to other classes doesn’t give us enough information to establish a pattern and it ends up raising more questions than it answers.

One really good example of composition can be found in Unity3D. Composition in Unity3D is a first class concept that runs very deeply into the built-in game engine that drives everything that Unity does. After studying it for a while I would like to use the patterns of composition found in Unity as a basis for our design pattern and our hypothetical programming language.

Aspects of the Composition Pattern

In a compositional system you therefore need at least two kinds of Types:

  • Object
  • Component

The Object in a compositional system is not the same as an Object in an inheritance based system. An Object in a minimal compositional system has the following attributes:

  • It may have a name
  • It may posses child objects
  • It may have a parent object
  • It may contain named components
  • It can send messages to components

A Component has the following attributes:

  • It has a reference to the Object it is contained by
  • It may have data
  • It can handle messages

Simple Example

If we were to design a minimal version of this system (in C#) it may look something like this:


interface IObject
{
string Name { get; }
IObject Parent { get; }
void Add(string name, IComponent component);
void Add(IObject child);
void Remove(IObject child);
IComponent GetComponent(string name);
IEnumerable<IObject> GetChildren();
void SendMessage(string message, params object[] parameters);
}
interface IComponent
{
IObject Object { get; }
}

view raw

Design.cs

hosted with ❤ by GitHub


// A naieve implementation of SendMessage
public void SendMessage(string message, params object[] parameters)
{
var types = parameters.Select(a => a == null ? typeof(object) : a.GetType()).ToArray();
foreach (var component in this.components.Values)
{
var method = component.GetType().GetMethod(message, types);
if (method != null)
{
// Call methods on the component via reflection
method.Invoke(component, parameters);
}
}
}

view raw

SendMessage.cs

hosted with ❤ by GitHub

For a more robust example I highly recommend studying Unity3D in detail. However the question I am asking is what would a system like this look like if it was not framed in the context of classes. How would it look if it were to have syntactic support in a language instead of simply implemented as a design pattern in terms of inheritance? I don’t fully know the answer to this question but I have been experimenting with some ideas and would like to have a discussion around them.


component c1 {
function receive(message: string) { // handles "receive" messages
print(message)
}
}
component c2 {
var running: bool
function run() { // Handles the "run" message
if(!running)
running = true
this->receive("hello world!") // Sends a message to "receive" with an argument
else
this->receive("error!")
}
}
// An object containing the above components
var x = {
c1 = new c1()
c2 = new c2()
}
// send a message to components on x named "run"
x->run() // > hello world!
x->run() // > error!

view raw

Components.js

hosted with ❤ by GitHub


var x = { } // an empty object
var y = {
value: "hi" // any value type, not a function
}
var z = Root { // a named object
}
var j = Root { // An object with children
First {
}
Second {
}
}
for(var child in j) {
print(child.name) // First, Second
}
j.First.foo() // Get child named "First" send it a message named "foo"

view raw

Objects.js

hosted with ❤ by GitHub

The first thing to realize with this system is that instead of designing Objects up front with static definitions like classes you can only instantiate them and you can only design their hierarchy.

Components are more interesting and do have a static definition. They contain state like a class which means they fulfill the OO principle of encapsulation. They may handle messages of any shape which also means they are polymorphic but they are not inheritable in this system. You may be tempted to add inheritance to components at this point but I believe that this is unnecessary and a mistake. The reason for this is that inheritance is basically just another kind of relationship but it is one that has a much higher degree of coupling between objects. There are a variety of reasons why this form of relationship can cause problems. One is the lack of abstraction and thus isolating the unit for test can become very complex and costly. Instead of using inheritance simply break out shared behavior and state into even more, smaller and more focused components.

A composition system like this is actually similar to the DOM you would find in a browser. The primary differences are that in this case it would not be tied specifically to a single domain (e.g. the domain of laying out and rendering documents) and instead of using an event system it uses message passing. In this way composition allows us to be extremely loosely coupled without requiring extra abstractions.

I can imagine systems where, instead of having a component keyword in the language, you compile entire files into components similar to the way you would compile an entire file into a module in a CommonJS system such as node.js. Your main app would essentially setup your starting objects the rest of your files would be Components. These ideas are very powerful I believe. The game industry has known about them and has been perfecting them for quite some time now, while the rest of the programming community appears to be largely unaware as far as I can tell. I would love to see some experimentation with these ideas in non game domains and find out what the community can come up with.

Author: justinmchase

I'm a Software Developer from Minnesota.

15 thoughts on “The Composition Design Pattern”

  1. I have a coworker who spent a lot of his career in the 90’s working with Smalltalk. What you’ve described lines up fairly closely with what he’s told me about how systems tended to be written in Smalltalk vs Java/.NET.

    1. Ditto with what Mike said, although I was going to reference Objective-C… but Objective-C’s messaging system was strongly influenced by Smalltalk.

  2. IM a MEF aDdiCT, I maKE SoftWaRE ThAT DOEsn’t EveN KNow wHAT IS DOIng, Until it find out at runtime, Composition is fundemented to extensiblation, anything else is my mind is brittle fragile and not even in the running for proper development best practices. whats great about MEF you can use POCOs and contract catalog options mean you can IAnthingIWant, so easy and thing else would be too much of a comprise, but any composition is better then none

  3. [ServiceContract]
    public interface IProvideKinectFrames
    {

    [OperationContract]
    void ComposeDependencies(ImageRes videoImageRes, ImageRes depthImageRes, bool EnableSkeletalTracking);
    [OperationContract]
    void SetPreviewCanvas(Canvas previewCanvas);
    [OperationContract]
    SkeletalData NextSkeletonData();

    [OperationContract]
    KinectImage NextVideoFrame();

    [OperationContract]
    KinectImage NextDepthFrame(int PrevHashCode);

    that me be true , but what other method allows composition contracts to use non-serializable objects?
    }

    1. Contracts and composition are orthogonal design patterns. Meaning, you can have one without the other, they are not really related. MFC happens to use both but that’s only a coincidence.

      For an example of composition download Unity3D (it has a free version) and give it a shot.

  4. One thing that occurs to me is that this very closely resembles some implementations of CQRS in application development. See: https://lostechies.com/jimmybogard/2014/09/09/tackling-cross-cutting-concerns-with-a-mediator-pipeline/ for an example.

    If you rename “Handler” to “Component”, imagine Command type names are your “message” parameter in “SendMessage” and the properties of the Command type are the parameters of the message and your IoC container serving up these Components are your object… well, it definitely looks extremely close, right? So maybe the rest of the programming community isn’t necessarily unaware, they just have called it something slightly different (and also, technically they have a single “God Object” that does everything by delegating to various components, so perhaps there’s some room for improvement).

    1. The power of message passing has definitely been recognized by many people, no denying that. I do think that composition is different from pipelines still. The library in the link you included is pretty interesting and a good pattern but I don’t think it is quite the same thing I am talking about.

    2. Well, I think I may have given too complex of an example. The “pipeline” isn’t the thing that relates to composition/components (it’s a “component”/handler itself, actually).

      Let’s take a simpler example posted as a gist:
      https://gist.github.com/Zshazz/b226372196aee8f1f7be

      So the main differences that I can see with the standard CQRS mediator/bus pattern is

      1. There’s usually only one mediator/bus per application.
      2. As a consequence of 1, there’s usually no “Parent” nor “Children” of a mediator/bus.
      3. “Usually” commands/queries are coded as strong types and have their “parameters” as properties on those types. Of course, that’s not always how it is … the origination of the pattern, CQS, is simply the idea that “commands” are methods that return nothing and are allowed to mutate state whereas “queries” are allowed to return things, but not mutate state. Typically, that isn’t strictly followed since often you want commands to return something saying whether it succeeded or failed (throwing exceptions I consider to be “returning something”, but it’s just a more surprising way of doing it) and queries might still do things like logging (which is mutation of state, technically) for auditing purposes or something. I have seen “Command Handlers” that are implemented almost entirely exactly as you’ve apparently described here for component (with just methods and using reflection like you’ve shown in SendMessage), but I can’t find an exact example of it right now.
      4. Typically, an IoC container exists outside of the mediator/bus (which is mostly analogous to your IObject) which is “better” in terms of the Single Responsibility Principle, but mostly an irrelevant detail. In principle, if we were looking at it from the perspective of having many objects in the system and we wanted them to have the ability mutate, it makes sense to have the container encapsulated and have “Add”/”Remove” exposed. I would still use another “object” to handle the instantiation/discovery of components simply because a lot of really good solutions are already built for that purpose anyway (though, in the case of your language, you’d have it built-in at the language level, which is also cool).

      5. I think CQRS mediator/bus implementations don’t handle multiple command handlers that respond to the same messages (that is, only 1 command handler per message type). That said, if they’re truly distinct enough components that you’d have two of them that respond to that same message, then that might be fine. In the above example, I went ahead and made that change because I don’t think that it’s that large of a departure (plus it replaces the null check in the case when there doesn’t exist a command handler for a message/command).

      But other than that, Command Handlers look like components, Mediators look like the objects you’ve described, and Commands look like the message + parameters that propagate through the object to all of its components.

      So I guess the point I’m trying to make is that the idea of using these component-based systems are already propagating outside of the games domain, but there’s some differences in the way it’s usually done, it’s named a bit differently, and it’s not done pervasively for all of the objects. Maybe it legitimizes your idea that a language that makes it easier to do might be a good idea, though.

    3. They author of that article you linked above did say at the end

      “All of this would be a bit easier if the underlying language supported this behavior. Since many don’t, we rely instead of translating these functional paradigms to OO patterns with IoC containers containing our glue.”

      Which I agree with as well 🙂

    4. I think I understand what you’re saying. Looking at the example you made it does appear to be very similar to the message passing part of what I’m saying, though with a lot of generics and types instead of dynamic with strings.

      The main difference I can see is that you’re using a container to find receivers whereas in the Unity composition system you actually have an object hierarchy. It’s a lot more like the DOM in html actually. Imagine an html DOM except of arbitrary objects. When you send a message it goes down the tree from the object it is sent to and any/all objects in that tree can handle the message. You can also send a message upward through the tree.

      But yes the message passing pattern is the most valuable part and what you are showing here sounds like a reasonable implementation of message passing. But the main thing it’s missing is that you’re still using inheritance to describe the object. For example the RunHandler accepts RunCommands. If you wanted to also accept StopCommand then you would, presumably need to inherit ICommandHandler on RunHandler and implement that as well.

      In Unity you would create and Object that “has a” run handler, not “is a” run handler. It may also have a StopHandler and basically it is the object that shares the state between the two components.

      Thanks for the ideas.

    5. Fully agreed on the main difference being an object hierarchy. I probably will start exploring using a hierarchy for a web app in some side projects (although for small side-projects, it probably won’t be a perfect fit, but it’s something interesting to think about regardless).

      “the main thing it’s missing is that you’re still using inheritance to describe the object” + “In Unity you would create and Object that “has a” run handler, not “is a” run handler.” -> Well, to be clear, the mediator part is what I consider to be the “IObject.” The mediator/object has no inherentance and, in fact, “has a” run handler/run component, although it’s more loose since it uses the IoC container to find its components. You add more components to the container as needed and the IObject will inspect the container to discover what components it has (in fact, using an IoC container allows the components to be lazily loaded as needed, which can sometimes be a benefit … furthermore, you could even configure an IoC container to recycle components as needed, which could be a boon in game development to avoid the GC when it’s not necessary … even more, components can register dependencies by simply adding them in the constructor and it’ll be up to the IOC container to resolve them, which is a nice incidental feature).

      “If you wanted to also accept StopCommand then you would, presumably need to inherit ICommandHandler on RunHandler and implement that as well.” Indeed, but that’s not really inheritance. Interfaces often describe a “can-do” relationship (although, certainly not always is that the intent, nor is it really helpful to always think of everything as “is-a” and “can-do”: http://stackoverflow.com/questions/255644/c-sharp-interface-implementation-relationship-is-just-can-do-relationship , but in the case, it does). So, if you wanted your RunHandler/RunComponent to accept StopCommands/StopMessages, then you would implement a ICommandHandler/IComponent interface saying that “The RunHandler/RunComponent can-do handling of stop commands/messages”. It’d be analogous to a component that accepts “public” messages and has it’s own internal messaging system/ private methods that the object can’t send them/ they don’t respond to outside of it’s own internally consistent state. If you wanted your Object to have a StopComponent that handles doing stopping and such, then that could still be a completely separate component, of course (not sure if your intent was a component that handles two different kinds of messages or an object that has two different components handling two different messages).

      I went ahead and revised the gist to reflect what I consider to be the differences in language (see the revisions on the right side to see the diff) between the two approaches. I still consider it to be different really only in the fact that with buses/mediators, we’re usually talking about an “effective” singleton/God Object which contains all components in a program (which is a semi-substantial difference, but I digress).

      Cheers & happy coding.

    6. Ok, I will buy that the IoC container is itself exemplifying the “has a” relationship by having a lot of objects inside of it. And that resolving types or objects via the IoC container would technically count for that reason and that adding message passing onto that gets you closer.

      But it is pretty different from how unity works and I think the differences are interesting to note. I’m not going to say that the IoC container is bad, per-se, but I do think it is inferior to the alternative.

      The whole point of an IoC container is to, essentially, break the Type dependencies created by the “new” operator. But you still have essentially the same techniques of using class hierarchies for modeling. With these techniques you end up with the familiar complex abstractions and so it doesn’t do much for breaking inheritance dependencies.

      I made a gist for you with a slightly more interesting but still very simple composition example:
      https://gist.github.com/justinmchase/7d4178b141b0e4982232

      Where “Node” == “Object”, since in C# Object is taken obviously.

      This allows you to model things in a pretty different way while, other than the construction of the initial node tree, letting you put all of your logic into isolated components. It’s kind of interesting to try to imagine how you might build something other than a 3D game or a 2D webpage with this model, I’m not sure. But I believe it does have general modelling capabilities so it would be interesting to explore it more.

      For, example I could imagine routing could be handled this way. And of course object hierarchies for ORM or data would naturally fit here. I haven’t had the time to fully explore non-game use cases yet.

    7. “Ok, I will buy that the IoC container is itself exemplifying the “has a” relationship by having a lot of objects inside of it”

      The mediator/bus part is the thing I think exemplifies the object “having a” bunch of components. The IoC container is filling the role of your List of components in the example you have shown to find its components. It’s inverted (that is, it’s injected into the object in the form of only a discovery mechanism, ConcreteObject.ComponentsThatCanHandleMessagesOf, which fulfills the “principle of least priviage”/principle of encapsulation a bit better IMO) instead of being built by and owned by the object, but it’s a minor detail (one which is derived from both SRP and ISP, and provides improved testability of your object). It’s really just to separate the concerns of building the components, which can be fairly complex in the domains this pattern is applied. I think if you were building objects using your system with 100+ components and you don’t want the objects to change behavior after they’re created, you might also (minimally) inject your IList of components into your object and allow someone else to handle the responsibility of collecting/selecting the needed components (think about: 100 lines of code to attach components to an object?). Personally, it’d be my preference that the behavior of objects remain immutable after their construction (although I can see why the sugar of the syntax gained by an “Add” method appeals to you in this case, but I see that as more of a language limitation than anything else), but to each their own. Heck, there’s a lot of people that think the state of things should be immutable, let alone the expected behavior. In a game you might want behavior to vary much more, so I’d chalk the preference on that to being domain-specific.

      “But it is pretty different from how unity works and I think the differences are interesting to note.”

      Different in how it works (at least my favored implementation, anyway), yes. I don’t think that’s in dispute. Different in what it does (other than the difference that there are many objects in the system you describe, but I think that point has been labored to death at this point), though?

      “I’m not going to say that the IoC container is bad, per-se, but I do think it is inferior to the alternative … But you still have essentially the same techniques of using class hierarchies for modeling”

      Well, the entire point of CQRS is precisely to not use class hierarchies for modeling the handling of commands/queries. I think you’re side-stepping the idea and inspecting the implementation too closely and making inferences based on the fact that an IoC container is utilized. The container certainly instills many benefits (optimized performance for larger component/depenency graphs, unambiguous component lifetime management, automatic dependency injection, less written code, component decoration, etc), but the pattern is fairly easily applied without a container (it’s just not typically done that way because the benefits of using an IoC container are so massive in a non-trivial project). That said, IoC containers give you a very convenient point of extensibility in CQRS. Often people will use the decorator pattern to surround command handlers/components with behavior augmentations and IoC containers will just apply the decorators with no fuss automatically once they’re registered.

      Consider an example of a movement component on a player that accepts messages of “Move forward” and “Jump”… with a “movement status effect component” decorator, you could augment the message going into the movement component that makes it so that the movement component “sees” a reduced movement request from what the player/object is telling it, under the circumstance that the object has a status ailment applied. And that behavior is added simply by registering the movement status effect component with the IoC container, and it will figure out how to wire that up properly (which might be nice if you have a “Flying movement” component and a “Ground movement” component on the player and you don’t want to bother manually decorating those components). Very cool & automagic. But unnecessary features to follow the pattern, mind you.

      In these simple examples, I can see why you might think a container is excessive, but in any non-trivial project you’re bound to have more complex components potentially requiring dependencies (and implicitly using global state for your dependencies like “Console.WriteLine” in your examples becomes a huge pain-point if you decide you want to start testing your components independent of other components/objects, despite initially seeming much simpler) and maybe have components requiring cross-cutting concerns such as behavior that should be applied to several different components as a pre/post-process step (such as my example of a “status effect” component that applies behavior onto other components).

      Heck, you don’t even have to utilize strongly-typed messages/handlers (like I’ve said before, I’m certain I’ve seen implementations of CQRS that utilize almost precisely the same “Method.Invoke” implementation you’re using, but I think that implementation fell out of favor once dynamic was added to C#, and then that implementation has faded away in favor of using strongly-typed messages, and now that’s all I can find in Google). That said, strongly-typed messages also impart quite a lot of benefits, such as unambiguous meaning (the string “Jump” has a contextually overloaded meaning: if you’re talking about a computer program, you’re talking about one type of jumping, and if you’re talking about a person you’re talking about a completely different kind of “Jump”, and if you’re talking about a space ship, there’s yet a different kind of “Jump” entirely … of the faster-than-light variety, or maybe you’re talking about the “Jump” that happens in a network game if the connection is interrupted for half-a-second), some compile-time checking, intellisense, removes the necessity of utilizing reflection (which I’m generally OK with, but generally it’s viewed as something complex/magical enough to be avoided if alternatives exist), and better performance (I measured, but both are probably “fast enough” that anything else going on is probably going to dwarf the time still) and possibly more reasons that escape me at the moment. I personally wouldn’t give up strongly typed messages unless there was a really compelling reason. The only benefit that I can see that string messages have are that they could be built up using concatenation or something, but I would be afraid to do that since it would almost certainly obfuscate what is going on to the reader of the code.

      But still, let’s strip away the IoC container and simpify it further. I’ll just use an IReadOnlyCollection and .OfType to handle dispatching commands to handlers and surely you’ll see that we’re talking about the exact same thing here:

      https://gist.github.com/Zshazz/90dfcd952e1cfd933bc1

      I think I’ve mentioned the significant difference, the lack of the tree of objects, but everything else looks like tomatoe-tomatah style irrelevant differences to me. I still think both sides have come up with what is effectively the same solution, just from two different directions (where components are usually more powerfully constructed on the web-dev side and objects are many on the Unity/game-dev side). Cross pollination has an opportunity to advance both sides, I believe.

    8. I think that we’re just talking past each other at this point. I see your idea, I originally started learning C# on Unity, so I know and understand how that works as well. My point was that application development using CQRS + handlers and such is nothing more than a special case of that idea (namely, the special case being that you only have one object as opposed to a hierarchy) and, thus, I was sharing that the “programming community appears to be largely unaware” isn’t completely true; it’s just called something different and is just a special case (that the application itself/sole mediator is the one object) of what you’re sharing. It has a different history and it’s usually only one part of a larger system, but we’re already seeing the idea of many simple components (with emphasis that components do not have complex inheritance hierarchies) handling few messages propagating outside of the games domain. All that’s left is to have these systems scale vertically (add more objects to the tree) instead of just horizontally (add more components to the object).

      I’ve approached trying to share that idea with you in many directions, but it looks like I’m doing a bad job of showing that.

      So, it’s kind of like when person 1 sees something and person 2 sees something and person 1 says “Hey, that’s quite a nice circle isn’t it?” Person 2 responds, confused, “but that’s no circle, that’s a rectangle!” Person 1 says “It has no sides, it couldn’t be a rectangle!” … And after 5 hours, person 3 comes in and says “Actually, it’s a cylinder, you’re both at 90 degree angles from it.” I’m trying to be person 3 here.

      Hope you have a wonderful week!

Leave a Reply to David S. (@gotamaprime)Cancel reply

Discover more from justinmchase

Subscribe now to keep reading and get access to the full archive.

Continue reading