Difference Between Composition and Delegation

Hi everyone,

I am currently learning Python and on the topic of delegation. Having now studied the topic of composition a tad bit prior to delegation, these two topics seem a bit similar. At the fundamental level, what is the main difference?

Both generally have the same setup:

self.some_attribute = SomeOtherClass(param_1, param_2, param_n)

They are two distinct things commonly used together.

Composition is the part where you use other objects to build up the state of a larger object. (Some draw a finer distinction, and say that “composition” means that the “other objects” aren’t useful or meaningful on their own but only as part of the whole, whereas “aggregation” can include pieces that would also be separately useful. However, this distinction doesn’t really help understand designs.)

Delegation is the part where you use the behavior of the other objects to implement the behavior of the larger object. Specifically, it refers to the cases where one specific “smaller object” can implement the entire behavior by itself, so the implementation for the larger object’s method just says to call the smaller object’s method.

class Creature:
    def __init__(self, head, torso, limbs):
        # This is the composition part
        self.head, self.torso, self.limbs = head, torso, limbs

    def step(self):
        for limb in self.limbs:
            # This is the delegation part
            limb.step()
3 Likes

Hmm. Ok, so composition is when adding on to an existing object. Say, a robot when you would like to add a special arm or special leg, etc.

Delegation is when you want a particular action to be executed.

So, one is for building or adding on to (composition), and the other is for wanting something to get done (delegation). i.e., composition - noun, delegation = verb?

Am I interpreting this correctly?

I think of composition vs. Inheritance as the alternatives.

With inheritance an existing class is extended by derivation,
This works well when you are specialising an existing object.

Composition on the other hand has a network of objects interact with each other to get a job done. This works well when there are relationships between parts of an application.
For example you may have an object that knows all about logging for your app. Each other object in the app only needs a reference to the logging object and call call its public API.

I found that building complex GUI apps with inheritance is very hard/impossible. Where as with composition the app design is possible and clean.

Delegation can be used with both design styles as @kknechtel explained.

3 Likes

Thank you for responding to my query.

I understand inheritance. It has a is a relationship, and the following set up:

SomeClass(InheritedClass): # Where InheritedClass is the super-class and SomeClass the sub class

whereas composition has a has a relationship. But I just want to distinguish explicitly definition wise the fundamental difference between composition and delegation as they appear very similar as demonstrated by their setup. Before moving on with my studies, I want to make sure I fully understand this as subsequent chapters will be referencing these topics with the expectation of applying them in design cases.

You may find that many software design terms have imprecise or subjective meanings, so the exact definition will change from source to source, or may be different in different contexts.

That said, my understanding matches @kknechtel‘s explanation, which I think is very good.

I also think your intuition about when to use each (noun vs verb) is pretty good, especially for delegation. Delegation is always about behavior (verb). I more often hear composition used to refer to data (noun), but as @barry-scott said the term “composition” can also be used more generally to describe how a class is built up from smaller parts. (Instead of extending a parent.)

Perhaps one could say delegation is a kind of composition, or that composition is used to implement delegation.

2 Likes

Thank you @flyinghyrax.

Ok, this makes sense as per their similar set-up.

Synergy - effect greater than the sum of their individual parts - which is what your responses have been.
Much appreciated!

Thank you to all for responding to my query. After reading your responses carefully, I think that I have a better understanding of composition and delegation than I had coming in.

:raised_hands: :blush:

One small follow up question.

How is it determined when to use delegation vs having a dedicated method in the parent class?
In other words, how does one weigh the use of one over the other? With a dedicated method, the implementation appears much simpler vs creating a new distinct class with added internal methods.

Can someone please offer insight.

Usually delegation would be employed when you want to be implementing an API expected by another part of the program, or by someone else. As an example, say you wanted to implement some sort of custom mapping class. One way to do it is via inheritance from dict, then calling super() in your overridden methods. But you could also just have a dict as an attribute, and implement a bunch of the operations by just doing the same thing on the internal dictionary.

Another reason might be to make it explicit that the operation is public and should be used by outside code. That’s somewhat related to a principle called the “Law of Demeter”. That basically states that if you have an object it’s fine to access methods of it, but you shouldn’t reach through that and access methods on things it contains. The idea is that by accessing such internals, the caller needs to know more details about the object which makes it harder to change in the future. Entirely up to you how much you want to follow that though, since it would mean adding a lot more delegation/wrapper methods.

Usually, when I hear API, my ears perk up and I tend to think in terms of library objects which are used by many users (you may import them if not located on the same module). Likewise, a class designed for the purpose of delegation behavior is used by many classes (objects)? Is this one way of looking at it? In other words, a method that can be used by many classes is wrapped up in its own class. Is this about right or one way of thinking about it?

What I was meaning by “API” is just a set of methods that something expects to be present on an object it’s given. It could be a known API that lots of users exist for (like a mapping, or a file object), or it could just be something one function expects. It’s not really that a class would be designed to be delegated to - usually if you control both the caller and the class you might just change one or the other to directly call the method. This sort of thing is done when there’s a mismatch between the two.

1 Like

I think that I am going to have to do a bit more research on the subject to fully understand how to decide the best approach.

Thank you for your responses.

Greatly appreciated.

What made delegation click for me was working on iOS apps with Apple’s UIKit library. It uses the delegate pattern extensively. I will try to make a general example based on that to (hopefully) build on what @TeamSpen210 has said.

The library provides a class that implements, say, swiping left and right between pages. That class has all the code that handles the swipes, the UI that shows a marker for the current page, things like that. The library class knows how to display pages.

But it doesn’t know what to display for each page. That is up to the app that is using the library. What is needed is a way for the page display class to “ask” the app what to display.

The library class publishes a list of methods that cover all the questions it has to ask in order to work. There might be a method for getting the total number of pages, a method for getting the current page content, etc. The library class gets implemented so that some other class has to have those methods - it delegates those operations to your app. To use the library class, you the app developer create a class that implements all the methods the library class asked for. Then to the library calls your methods to “fill in the blanks” it needs.

So in this case, the delegate pattern is used so that the library implements all the parts of the UI that follow common patterns - scrolling lists, navigation, tabs, etc. - but leaves “holes” where something specific needs to go, or where and event happens that the library won’t know how to handle by itself. Then developers that use the library “plug in” their classes into the spaces.

How this relates to what @TeamSpen210 was saying, is that it’s a situation where the delegate and the class that uses the delegate are developed separately. There’s a clear separation between the logic that is always the same (the library class) and the parts that need to be able to change (the delegate). The API is the boundary between the two parts. The library defines the API, the delegate implements it.

Another thing I feel is important when talking about design patterns - when exactly to use a particular pattern can be very subjective. Often there can be more than one “right” answer. What to use might depend on how a library is most easily used, or what has already been done by a team in a codebase, or what is common in a particular programming language.

Patterns can be very helpful for solving common problems, and for establishing terms for people to discuss different design options. But there aren’t many “hard rules”, and it can just take practice and/or working with some existing code to get a feel for what works best in different situations.

Just my 2¢. The best thing is to get into as many examples as you can, for instance by reading other peoples code from projects you like or by trying different libraries. You’ll start to see the patterns jump out, even if the corresponding documentation uses a different name for a pattern than what you’d expect.

1 Like

This is a bit confusing to me. The first quote implies delegating actions to the library class. The second quote appears to state that the library class delegates actions to do to the app class. The way I would interpret delegation for this particular instance as per the first paragraph is via the following sketch.

delegate_sketch

I also notice that different people might use different terminology. For example, I was watching a youtube video (should have saved the link, …). But if I apply it to this scenario, the app would be the container and the class library would be the contained.

Thank you for the supplementary discussion. Yes, this is something that I need to get more practice on for it to make more sense. I understand the mechanics of it. But I need the experience to understand it more in terms of when to apply it versus applying methods in the native class.

Thank you a bunch.

Yes, exactly! The app delegates generic UI tasks (which are the same for all apps) to the library, and the library in turn delegates reacting to user events (which differs between apps) back to the app. This is called “separation of concerns”.

Delegation can occur in both directions and between more than two objects.

1 Like

Thank you for your feedback and introducing me to the computer science concept of Separation of Concerns. Did a quick google search on this term and came upon this article:

Which in turn includes the following quote:

The principle is simple: don’t write your program as one solid block, instead, break up the code into chunks that are finalized tiny pieces of the system each able to complete a simple distinct job.

So, in a nutshell, this in a way answers my initial question as to how to decide whether to implement the method that does the work as a native method or to wrap it up in a separate class and implement the action through delegation.

Much appreciated. :handshake: :wink:

1 Like

FWIW, usually, development works the other way around. You start out making the “parent” class by itself, and then realize that some portion of its contents would make sense as a separate entity. So you refactor to group those attributes as an instance of a new class; give that class its logical functionality; and then see how it can be used to simplify the original class.

But I’d like to make a more general observation here. A lot of programmers seem to fall into a trap where they think they can become better programmers by studying what all the jargon means, how existing designs work, etc. But this is, for the most part, backwards. The reason to learn what the words mean, is so that you can properly communicate and be understood about what you have already yourself produced. Becoming a better programmer comes partly from studying existing designs, but mostly from critical thinking about what you already have, having an unrelenting desire to improve that… and experience.

4 Likes

Agreed. Programming is an art. All art has goals, all art is improved by science, by study, by terminology, by feedback. But at least for me, the allure, the thing that keeps me excited, is the beauty and creativity.

3 Likes

Absolutely! Well stated. I agree one hundred percent.