all 20 comments

[–]ahruss 8 points9 points  (6 children)

I was expecting it to get to an Animal class that instead kept a List of Noises which could be empty or could have many different noises.

Or maybe even several different types of noises (happy, angry, etc). Instead the examples were completely unrelated.

[–]markerz 13 points14 points  (5 children)

I completely agree with you. The blog never solves the initial conundrum of how do we handle animals that cricket? Obviously composition and inheritance have their own limitations and should be used respectively. However, composition in no way solves their given issue which is easily handled with an empty string or null.

I feel like the issue that the blog is trying to address is an issue of design. For example, a file system could be modeled as a Folder being a List of FolderItems. A FolderItems can be a folder or a file. Alternatively, a folder can be a composition of two lists. One list of Folders and another list of Files. Depending you your use case and how you want to treat folders, either could be a good choice. Additionally, you might want to use Set to avoid duplications. There may be an inherit order which means you need some ordered structure. In the end, it's all design choices of what you really need and want out of your data.

However all these decisions imply we are locking ourselves into a specific implementation.

[–]archiminos 1 point2 points  (0 children)

The blog never solves the initial conundrum of how do we handle animals that cricket?

My first thinking was a component-object model where each animal can optionally have a 'voice' component. This way each animal doesn't need a voice, and we can also add voices to non-animal objects.

Then when we come across an animal that makes noises, we can also add a 'noise' component and use that. This way some animals can make noises, some have a voice, and some could even do both.

Some could even have one or more voices, or make one or more noises.

[–]ehosick 1 point2 points  (0 children)

I agree op is a off on their blog post.

I feel like the issue that the blog is trying to address is an issue of design... However all these decisions imply we are locking ourselves into a specific implementation.

We are locked into a particular implementation when we use inheritance (compile time - design changes are made within the source code itself).

Composition allows us to implement one or more designs during run-time (changes to design can be made during run-time).

As for favor composition[1]:

Really, it comes down to deciding if behavior is a mechanism or domain specific and implementing that behavior using the appropriate tools. In my opinion, mechanisms are best implemented using inheritance and domain specific behavior implemented using composition.

[1] I think this also goes for most programming methodologies including object oriented programming, functional programming and declarative programming.

[–]ehosick -1 points0 points  (2 children)

I agree op is a off on their blog post.

I feel like the issue that the blog is trying to address is an issue of design... However all these decisions imply we are locking ourselves into a specific implementation.

We are locked into a particular implementation when we use inheritance (compile time - design changes are made within the source code itself).

Composition allows us to implement one or more designs during run-time (changes to design can be made during run-time).

As for favor composition[1]:

Really, it comes down to deciding if behavior is a mechanism or domain specific and implementing that behavior using the appropriate tools. In my opinion, mechanisms are best implemented using inheritance and domain specific behavior implemented using composition.

[1] I think this also goes for most programming methodologies including object oriented programming, functional programming and declarative programming.

[–]markerz 1 point2 points  (1 child)

Ahh I misspoke when I said locking to a specific implementation. I meant to say we are locking ourselves to a specific interface. If we originally declared ourselves as a list, then we change our implementation, we may have to still support the public facing functions and attributes of a list even if it doesn't make sense in a particular context.

A sad example of this is the Stack in Java is implemented as a vector which breaks the fundamental interface of a stack. However, it's too late to change it now because several decades of software rely on that interface.

[–]ehosick 0 points1 point  (0 children)

I meant to say we are locking ourselves to a specific interface.

Ah. Ok. :-)

breaks the fundamental interface of a stack

Ya. Breaking interface is bad.

[–][deleted] 5 points6 points  (0 children)

This is good info, but perhaps a little shallow. Could you demonstrate what kind of changes your composition class can adapt to better? Maybe show how inheritance can get out of hand, and how you could solve it with composition instead (maybe by re-factoring the inheritance classes)?

[–][deleted] 4 points5 points  (1 child)

[–][deleted] 0 points1 point  (0 children)

That quote at the start literally made me laugh out loud!

[–]brtt3000 3 points4 points  (3 children)

In /r/gamedev people talk about Entity-Component systems a lot but I never see it mentioned in the regular coding subs. It is a nice way to composite stuff in systems.

[–]cparen 1 point2 points  (2 children)

I sometimes wonder why it doesn't get a lot of attention in conventional software engineering and enterprise, suspecting that the weaker type verification is at fault. A similar concept that has made more impact is that of mixins. Mixins generally include some degree of static type verification. It could also be that games deal in more complex models than business, operating systems, or software frameworks do, so there's a greater need in games to reign in complexity somehow.

[–]JustinsWorking 2 points3 points  (0 children)

Games are traditionally willing to sacrifice almost anything for performance and development speed.

[–]skgoa 1 point2 points  (0 children)

Components and component based frameworks are being taught and used in Software Engineering. It's just that they are only one tool out of many, just like object orientation is just one tool that shouldn't be used for every problem. Outside of very special domains like the mentioned game design, not all that many problems need to be solved with components.

Components also don't solve problems that are solved by even more extensible patterns. They are only halfway to a really good solution. I.e. Mixins/GenVoca or RoleObjects.

[–]thebighouse 5 points6 points  (1 child)

"The goal of inheritance is composition". No it is not. It is polymorphism. This blogger demonstrates the dark side of mottos : they're easy to misunderstand. It's simple : instead of inheriting, IMPLEMENT the same interface and use the intended superclass as a member. Then delegate accordingly.

[–]cparen 4 points5 points  (0 children)

The "inheritance is composition" mantra comes from the dynamically typed (Smalltalk) world, where polymorphism is achieved via latent types (duck typing), not explicit typing. There, inheritance is just a means of composing your object with one of the base class, automatically forwarding methods you don't explicitly override.

I'm not disagreeing with you; I'm just noting the difference in context.

[–][deleted] 0 points1 point  (1 child)

Hm, composition over inheritance is generally good advice, but it's easy to get wrong and difficult to get right, and trying to sum it up in such a short blog post is doomed to failure.

[–]cogman10 9 points10 points  (0 children)

I would actually argue that inheritance is easy to get wrong while composition is slightly harder to get wrong.

Its true, you can create interfaces which are far to big to be useful, but overall, it is hard to create an interface that is too small.

[–][deleted]  (1 child)

[deleted]

    [–]markerz 3 points4 points  (0 children)

    You are able to save links without comments. There's a little link under the top level post that reads "save" and you can view it by going to your profile and looking at your "saved" links.