Object composition promotes code reuse. (T/F, why)
Asked Answered
C

5

5

I'm studying for an exam and am trying to figure this question out. The specific question is "Inheritance and object composition both promote code reuse. (T/F)", but I believe I understand the inheritance portion of the question.

I believe inheritance promotes code reuse because similar methods can be placed in an abstract base class such that the similar methods do not have to be identically implemented within multiple children classes. For example, if you have three kinds of shapes, and each shape's method "getName" simply returns a data member '_name', then why re-implement this method in each of the child classes when it can be implemented once in the abstract base class "shape".

However, my best understanding of object composition is the "has-a" relationship between objects/classes. For example, a student has a school, and a school has a number of students. This can be seen as object composition since they can't really exist without each other (a school without any students isn't exactly a school, is it? etc). But I see no way that these two objects "having" each other as a data member will promote code reuse.

Any help? Thanks!

Composer answered 2/8, 2011 at 1:28 Comment(8)
This question, to me, exemplifies much of what is wrong with CS education today.Squamulose
@Karl Knechtel: The specific exam question, or my understanding of the relevant content? Why?Composer
Both, and it is something that I am unable to explain very well but that you will hopefully understand in a good ten years or so, after you have the corresponding amount of experience...Squamulose
@Karl: So do the majority of the answers.Barbey
@Karl: Only one of the answers even mentions delegation. That's sad IMO.Barbey
What about maintainability. Code that goes the inheritance route too much turns into top-down class spaghetti that's so cross dependant as to be not reusable.Cleres
@Michael: That's another discussion entirely.Kiehl
This question appears to be off-topic because it is about a specific (badly worded) exam question.Daves
K
5

Object composition can promote code reuse because you can delegate implementation to a different class, and include that class as a member.

Instead of putting all your code in your outermost classes' methods, you can create smaller classes with smaller scopes, and smaller methods, and reuse those classes/methods throughout your code.

class Inner
{
public:
    void DoSomething();
};

class Outer1
{
public:
    void DoSomethingBig()
    {
        // We delegate part of the call to inner, allowing us to reuse its code
        inner.DoSomething();
        // Todo: Do something else interesting here
    }

private:
    Inner inner;
};

class Outer2
{
public:
    void DoSomethingElseThatIsBig()
    {
        // We used the implementation twice in different classes,
        // without copying and pasting the code.

        // This is the most basic possible case of reuse

        inner.DoSomething();

        // Todo: Do something else interesting here
    }


private:
    Inner inner;
};

As you mentioned in your question, this is one of the two most basic Object Oriented Programming principals, called a "has-a relationship". Inheritance is the other relationship, and is called an "is-a replationship".

You can also combine inheritance and composition in quite useful ways that will often multiply your code (and design) reuse potential. Any real world and well-architected application will constantly combine both of these concepts to gain as much reuse as possible. You'll find out about this when you learn about Design Patterns.

Edit:

Per Mike's request in the comments, a less abstract example:

// Assume the person class exists

#include<list>

class Bus
{
public:
    void Board(Person newOccupant);
    std::list<Person>& GetOccupants();

private:
    std::list<Person> occupants;
};

In this example, instead of re-implementing a linked list structure, you've delegated it to a list class. Every time you use that list class, you're re-using the code that implements the list.

In fact, since list semantics are so common, the C++ standard library gave you std::list, and you just had to reuse it.

Kiehl answered 2/8, 2011 at 1:37 Comment(4)
A good idea, but do you have any real examples that fit this?Aspidistra
@Mike: Do you think the answer would be easier to understand with a real-world example? I wrestled with it, because the code I have here is very brief, and solid real-world examples might require a bit more domain or programming knowledge. The first example that comes to mind is using a std::list under the covers of the implementation of some class, rather than having to rewrite list handling from scratch.Kiehl
Personally, I tend to find this sort of explanation given a lot but I haven't touched much code which has actually used composition in such a way. That's why I'm curious of what sorts of examples (even if they're abstracted to some extent) exist that actually use this in practice.Aspidistra
@Mike: If you think about it enough, it is used everywhere, in one form or another. Some more examples: I use this exact pattern for composing NUnit custom constraint classes, and a more abstract version of the pattern for calling web services (it is an interface in that case, not a concrete class). I ideally use this anywhere that I want the code-reuse benefits of inheritance, but where the Liskov Substitution Principle doesn't apply.Kiehl
S
3

1) The student knows about a school, but this is not really a HAS-A relationship; while you would want to keep track of what school the student attends, it would not be logical to describe the school as being part of the student.

2) More people occupy the school than just students. That's where the reuse comes in. You don't have to re-define the things that make up a school each time you describe a new type of school-attendee.

Squamulose answered 2/8, 2011 at 1:34 Comment(1)
This is more about relational concepts and combinations of inheritance/composition. It doesn't describe how composition alone can promote reuse (which it does). It is more descriptive of real usage of these concepts, though...Kiehl
L
3

I have to agree with @Karl Knechtel -- this is a pretty poor question. As he said, it's hard to explain why, but I'll give it a shot.

The first problem is that it uses a term without defining it -- and "code reuse" means a lot of different things to different people. To some people, cutting and pasting qualifies as code reuse. As little as I like it, I have to agree with them, to at least some degree. Other people define cod reuse in ways that rule out cutting and pasting as being code reuse (classing another copy of the same code as separate code, not reusing the same code). I can see that viewpoint too, though I tend to think their definition is intended more to serve a specific end than be really meaningful (i.e., "code reuse"->good, "cut-n-paste"->bad, therefore "cut-n-paste"!="code reuse"). Unfortunately, what we're looking at here is right on the border, where you need a very specific definition of what code reuse means before you can answer the question.

The definition used by your professor is likely to depend heavily upon the degree of enthusiasm he has for OOP -- especially during the '90s (or so) when OOP was just becoming mainstream, many people chose to define it in ways that only included the cool new OOP "stuff". To achieve the nirvana of code reuse, you had to not only sign up for their OOP religion, but really believe in it! Something as mundane as composition couldn't possibly qualify -- no matter how strangely they had to twist the language for that to be true.

As a second major point, after decades of use of OOP, a few people have done some fairly careful studies of what code got reused and what didn't. Most that I've seen have reached a fairly simple conclusion: it's quite difficult (i.e., essentially impossible) correlate coding style with reuse. Nearly any rule you attempt to make about what will or won't result in code reuse can and will be violated on a regular basis.

Third, and what I suspect tends to be foremost in many people's minds is the fact that asking the question at all makes it sound as if this is something that can/will affect a typical coder -- that you might want to choose between composition and inheritance (for example) based on which "promotes code reuse" more, or something on that order. The reality is that (just for example) you should choose between composition and inheritance primarily based upon which more accurately models the problem you're trying to solve and which does more to help you solve that problem.

Though I don't have any serious studies to support the contention, I would posit that the chances of that code being reused will depend heavily upon a couple of factors that are rarely even considered in most studies: 1) how similar of a problem somebody else needs to solve, and 2) whether they believe it will be easier to adapt your code to their problem than to write new code.

I should add that in some of the studies I've seen, there were factors found that seemed to affect code reuse. To the best of my recollection, the one that stuck out as being the most important/telling was not the code itself at all, but the documentation available for that code. Being able to use the code without basically reverse engineer it contributes a great deal toward its being reused. The second point was simply the quality of the code -- a number of the studies were done in places/situations where they were trying to promote code reuse. In a fair number of cases, people tried to reuse quite a bit more code than they really did, but had to give up on it simply because the code wasn't good enough -- everything from bugs to clumsy interfaces to poor portability prevented reuse.

Summary: I'll go on record as saying that code reuse has probably been the most overhyped, under-delivered promise in software engineering over at least the last couple of decades. Even at best, code reuse remains a fairly elusive goal. Trying to simplify it to the point of treating it as a true/false question based on two factors is oversimplifying the question to the point that it's not only meaningless, but utterly ridiculous. It appears to trivialize and demean nearly the entire practice of software engineering.

Lahdidah answered 2/8, 2011 at 4:52 Comment(3)
+1; I guess I never really thought that copy/pasted code could possibly be considered code reuse, but I guess it is it. You wrote it once, and used it multiple times, so by definition it is reuse. I guess it's really the DRY principal that covers copy/paste reuse...Kiehl
Also, while I think your discussion is very useful and important for the code reuse part of the question, and quite relevant here, I don't think it answers the professor's question well: Inheritance and object composition both promote code reuse. (T/F). Knowledge of both techniques, combined with simple logic, will show that both techniques can promote some forms of code reuse, which means the answer is true. Just because there are other techniques and other types of code reuse doesn't make the answer false.Kiehl
I just read this through again and don't know why I didn't upvote earlier. Thanks SO much for the detailed answer, it makes tons of sense.Composer
C
2

I have an object Car and an object Engine:

class Engine {
     int horsepower;
}

class Car {
     string make;
     Engine cars_engine;
}

A Car has an Engine; this is composition. However, I don't need to redefine Engine to put an engine in a car -- I simply say that a Car has an Engine. Thus, composition does indeed promote code reuse.

Corum answered 2/8, 2011 at 1:31 Comment(0)
B
2

Object composition does promote code re-use. Without object composition, if I understand your definition of it properly, every class could have only primitive data members, which would be beyond awful.

Consider the classes

class Vector3
{
    double x, y, z;
    double vectorNorm;
}

class Object
{

    Vector3 position;
    Vector3 velocity;
    Vector3 acceleration;
 }

Without object composition, you would be forced to have something like

class Object
{

    double positionX, positionY, positionZ, positionVectorNorm;
    double velocityX, velocityY, velocityZ, velocityVectorNorm;
    double accelerationX, accelerationY, accelerationZ, accelerationVectorNorm;
 }

This is just a very simple example, but I hope you can see how even the most basic object composition promotes code reuse. Now think about what would happen if Vector3 contained 30 data members. Does this answer your question?

Brentonbrentt answered 2/8, 2011 at 1:38 Comment(1)
This is actually a good example of how it's used. I've used this same pattern in my code before I never really thought of this as being composition.Aspidistra

© 2022 - 2024 — McMap. All rights reserved.