views:

1664

answers:

16

Typically i dont want to know the specifics of the cons of OOPs, but it felt kind of weird when I had an argument at an interview I attended recently. The question that was posted to me was to tell me one disadvantage of OOP (Object Oriented Programming). At that time, I felt OOP to be the most matured level of programming after the procedural/functional models. So I replied to him that I dont see any negatives at all.

But the interviewer said there are few and I asked him to list one if he does not mind. He gave an example that I cant digest well, he said that OOP pattern does not strictly implement inheritance rules and cited the satellite/rocket example where the body parts will disintegrate periodically to remove weight during rocket launch and said that inheritance does not support this.

His example kind of felt very weird to me the reason being the application of inheritance to this example.

I understand that the example he gave hardly had any sense at all, but I had this doubt -

Can we unplug class hierarchies dynamically (I am kind of confident in Java its not possible) in an ideal Object Oriented Design?

+10  A: 

His example makes no sense. A rocket doesn't inherit from a body. It "has" a body. That's containment. So a some point you would "delete" the part attached to the rocket as it was jettisoned.

jmucchiello
Yeah, i felt so, but see my question at the end..
Bragboy
+1 His example just sounded like a text book composition example to me! I'd be curious to hear others interpretation though.
David Relihan
rocket.body = null;
luiscubal
+1  A: 

The classic is to prefer composition over inheritance. Inheritance is there to capture abstractions along a seam that your system varies along.

If you don't quite clearly capture that abstraction, then yes, you will get strange forces on your designs. But this is a problem of programming in world where the abstractions are not quite right for what you are trying to achieve. Not that they will ever be perfect.

Keith Nicholas
By definition they won't be perfect, or we wouldn't call them abstractions. :)
Jim Leonardo
+23  A: 

Just because you have a hammer, doesn't mean everything is a nail.

I've found that many people often confuse when to apply composition vs. inheritance when using OOP as a programming style. The example you cite from the interview question appears to be a case of this exact kind of confusion.

One thing I've learned with experience, is that while inheritance is a nice paradigm for expression "IS-A" relationships between entities in a design, it's often better to favor composition rather than inheritance.

But let's examine the crux of the interviewers question though: when is OOP a poort choice of paradigm?.

OOP works best with large-scale, multi-developer, multi-module projects. For "development in the small" - such as scripting or transformative processing, it can require a good deal of overhead without necessarily adding value. But even in these cases, unless you're writing throw-away code, I would argue that large solution often evolve from smaller ones, so establishing structure and separation of concerns early on can save you grief later.

Ultimately, OOP programming also requires a certain level of design rigor and planning, as well as an understanding of the core principles of object orientation. If you're unwilling to take the time to study and understand those principles ... well, perhaps then OOP programming is not for you.

Beyond that, certain kinds of problems also lend themselves to alternative programming styles. For example, transformative processing is quite ammendable to the functional style of programming - in which a results is computed and passed to successive transformation steps to produce a final result. Problems where you have to search or query a domain for certain matching information are ammenable to query languages (like SQL) in which you describe your intent declaratively rather than imperatively.

Being able to recognize which kind of problem you are solving goes a long way towards choosing which kind of language or tool to use. The right tools can make a job much easier ... the wrong one can make it harder - or impossible.

LBushkin
+3  A: 

I can kinda see the point he was driving at. I think the argument was basically centred around the disadvantage of inheritance - if you're not careful, or if you inherit too many times to keep extending functionality you can end up with a bloated mess of a class with a load of redundant features and lack of cohesion.

His analogy works if you consider that, once the rocket has burned the fuel in a segment, the segment becomes redundant and therefore dead-weight. The rocket can jettison the segment, but I don't think it's possible to exclude sections of a class you don't want to inherit (although correct me if I'm wrong, because it sounds useful).

Moonshield
Jmucchiello pointed this one out.. The rocket has a segment, not is a segment. It might have several segments. When one becomes useless, delete it, and move on. :)
baash05
+12  A: 

I'm not fully understanding his example.

However, it's important to understand that OOP is very effective for things that can be modeled naturally with it, and is very ineffective for other things (e.g., crosscutting concerns or aspects). That is one disadvantage of OOP. Another is that it often incurs some runtime cost due to dynamic dispatching.

In addition, it is very easy to abuse OOP to do nonsensible abstractions. Having a rocket inherit from a body is one example. My experience is that novice developers either don't trust and don't use inheritance, or that they are over-eager and use it incorrectly, when other behaviors (like aggregation) are more appropriate. Over time, experience and understanding of the mechanism improve.

I'm not sure what he meant by "OOP pattern does not strictly implement inheritance rules", since OOP is not a pattern. One potential issue is that one can write a subtype that can violate Liskov's principle of substitution, so that an overridding method does not behave "at least" like the overridden method. There is no way to automatically check for this so it is possible to write code that violates OOP principles.

As for your final question "Can we unplug class hierarchies in an ideal Object Oriented Design?", I'm not sure what you mean here. If you're asking about changing the hierarchy at runtime, and making it so that a subtyping relation no longer exists from some point in the execution, then yes. It is possible with certain languages such as Smalltalk. Some would argue that this is "More OOP". In smalltalk, the 'methods' supported by a type are determined at the point of method call based on the current hierarchy and the current contents of each class. While I love smalltalk, this is one feature that I'm not crazy about, since I prefer compile-time checking with less runtime surprises.

Uri
A problem you create only as you get better http://stackoverflow.com/questions/2101875/what-are-some-programming-questions-or-mistakes-you-get-wrong-only-as-you-get-b/2124134#2124134 :)
BlueRaja - Danny Pflughoeft
+6  A: 

Although I don't fully understand the example given, as it sounds like composition to me I will give a disadvantage of OOP

OO is hard to test

  • No direct access to read/write class variables/attributes - may need to introduce getters and seeters which breaks incapsulation.

  • Inheritance can change the behavior of a method in a subclass

  • Objects have state. It can be hard to generate these states as we depend on the public interface.

  • Classes with loh cohesion can be hard to test as this could mean that the class does more than is specified.

David Relihan
Testing is where you may want to be using a Dependency Injection system so you can easily mock the bits that the class under test depends on. And whitebox tests are always going to be highly coupled to what they test; that should not be thought of as a problem. (Blackbox tests OTOH should only ever need the public interface.)
Donal Fellows
+1  A: 

Read this excellent article on Why Extends are Evil. That said I cannot really say that it's a con of object-oriented-programming.

I guess your interviewer ideal of a space ship is a Black Obelisk from 2001: Space Odyssey.

Alexander Pogrebnyak
+1  A: 

The biggest disadvantage I can think of with OOP is lack of support for higher order functions. Although you can pass in an object containing a method, this is verbose and inefficient. It would be much better to be able to pass in a function directly to another function.

Robert
That is not a disadvantage of OOP. Rather, it is a limitation of *some* OOP languages. Other OOPLs *do* support higher order functions; e.g. Smalltalk-80.
Stephen C
@Stephen C: Actually, you could even go one step further and argue that languages that *do not* support HOFs are *not* OO. Why? In an object-oriented language, ideally everything should be an object. If everything is an object, this obviously means that functions must be objects. If functions are objects, they can be passed to and returned from methods. Presto: higher-order functions.
Jörg W Mittag
@Jorg - you could ... but I wouldn't, because this leads to endless pointless arguments about which of the many conflicting definitions of OO is "correct".
Stephen C
@Stephen C: Yes, you're right, of course. I'm not *really* suggesting to do that. I just wanted to point out that the idea that OOP and HOF are somehow fundamentally incompatible, as this answer seems to suggest, is really not true. After all, what is a function but an object with only one method, `call`? (Which, incidentally, is actually how functions are implemented in Scala and Python, and how they are faked in Java (anonymous inner classes implementing single-method interfaces)).
Jörg W Mittag
Jorg: Whenever someone says "Everything is an object", they never seem to define "everything". Data types? Methods? Symbols? Characters? Comments? Given any definition of "everything" I can imagine, I think there are both OO and non-OO languages that make that thing accessible. For example, while Ruby may not be my favorite language, I can't seriously claim that it's not OO just because its comments aren't objects.
Ken
+1  A: 

Concerning unneeded methods in parent classes: Aren't they a sign of bad architecture? I mean shouldn't you isolate in the planing stage functionalities needed by each class and then have a chain of classes derived one from another?

For example we have class A, B, C and D. Class A has methods classes B, C and D need. Class B has methods class D needs. So we could derive class D from B and B from A. On the other hand we will derive C from A because C doesn't need the stuff B has. So we basically solved problem of having unneeded stuff by adding one extra class in hierarchy. Of course if something like this wasn't caught in the planning stage and class B was used as base class, it would be more difficult to split class B into two classes, but with some extra effort the problem of unneeded baggage is solved.

AndrejaKo
+9  A: 

Although I agree with the interviewer's conclusion (OOP is flawed), his logic appears to be nonsense. It sounds like he's criticizing something he doesn't understand, because no competent OO programmer would make a rocket inherit from its thrusters.

People have made good criticisms against OOP, though. For example, Steve Yegge's Execution in the Kingdom of Nouns.

Chuck
+1 for that funny link.
meriton
+1 my favorite anti-java text.
tster
+1 "Execution in the Kingdom of Nouns" is a classic. It's also one of the best ways to explain OO to English grads. :)
S.Jones
+2  A: 

Might the rocket example have alluded to the fact that in many object oriented languages, an object's type is immutable? That is, if I have a Student object, and the person it represents finishes her studies and becomes an employee, I can not turn the Student object into an Employee object. I have to create a new one, lose object identity in the process, and consequently have to update all references pointing to the former student.

Of course, such a feature would interfere with static typing (the type invariant that an object's type is a subtype of the static type of any reference pointing to it). But in some contexts the flexibility might be worth that.

meriton
In prototype-based object-oriented languages, that's obviously a moot point. Yet even in class-based object-oriented languages, it's not always true: in Common Lisp, you can call `change-class` to change an object's class, without losing identity.
Ken
Once again, that's composition vs inheritance. A "has a" (person X has a course they are enrolled in) may be better than Student inheriting from Person.
wisty
+1  A: 

I'm sure I've never heard of a statically typed language like Java that is capable of morphing an object into another while leaving the object reference intact, but I'm sure you can fake it with delegates etc. That said, without some fundamentally good thought, it probably would be a mess.

I can't know how the interviewer presented the question or how you responded, but one of OOP's biggest short comings isn't really OOP itself. It's the poor usage of OOP and bad "IS-A" relationships people try to create. If the only reason you can come up with to create an inheritance hierarchy is reuse of code, it's a poor reason. AOP can be argued to be a better approach for that. (before you flame or down vote, please note I said "can be")

OOP is about the interface and type, not about the implementation. Knowing that an object can return a list of job candidates is all I need to know. Whether that comes from an RDBMS, column oriented db, web service, or even spreadsheet is immaterial. I know I can pass that object as a parameter to other methods and they can call "FetchJobCandidates" and know it will get job candidates. There are pitfalls along the way, but mostly if you think of classes based on what they expose to the rest of the world rather than what they do internally, you're on a better footing IMO.

Jim Leonardo
+1  A: 

Can we just say use this in OOP?

RocketShip.BodyPart1 = nothing or

RocketShip.BodyPart1.isDetached = false?

I believe it is not the OOP itself is the fault but it's the limitation(s) of the programming language used on how it is being implemented.

paul
+1  A: 

I think it's main disadvantage comes straight from its power. One of the most common things done in OOP is to replace parent classes with derived classes in some places, to specialise the behaviour of the code. Well, if not done carefully, it's easy to invalidate some of the assumptions made in the caller code; and that could be very difficult to spot while reviewing the code, because the types you're seeing declared are not the ones actually being used.

In brief: polymorphism can be made not explicit and thus easy to overlook weird behaviours in the derived classes.

fortran
+1  A: 

Take a look at these articles. There are various explanations of some of the disadvantages of OOP, particularly the hazards of forcing things into hierarchies, like in your interviewer's example.

finnw
+1  A: 

One way to model an object which changes its sub-class is to use the State pattern. Using your interview question and some help from Wikipedia, here's some Java code that shows how you could model the state transitions as the rocket goes through its various stages. I haven't shown the Command Module stages but they follow a similar pattern through lunar descent, lunar ascent, lunar orbit rendezvous and the return to Earth. You could probably find much more interesting behaviours to add to the ISpaceShipState interface.

public class SpaceShip {
    private ISpaceShipState m_state = new SaturnFiveState();

    public void setState(ISpaceShipState state) {
        m_state = state;
    }

    public void jettison() {
        m_state = m_state.transition();
    }

    public int getStageNumber() {
        return m_stage.getStageNumber();
    }

    public int getNumberOfRocketMotors() {
        return m_stage.getNumberOfRocketMotors();
    }

    public String getRocketMotorTypeName() {
        return m_stage.getRocketMotorTypeName();
    }
}

interface ISpaceShipState {
    public ISpaceShipState transition();
    public int             getStageNumber();
    public int             getNumberOfRocketMotors();
    public String          getRocketMotorTypeName();
}

public class SaturnFiveState implements ISpaceShipState {
    public ISpaceShipState transition() {
        return new SaturnFiveSecondStageState();
    }

    public int getStageNumber() {
        return 1;
    }

    public int getNumberOfRocketMotors() {
        return 5;
    }

    public String getRocketMotorTypeName() {
        return "F-1";
    }
}

public class SaturnFiveSecondStageState implements ISpaceShipState {
    public ISpaceShipState transition() {
        return new SaturnFiveThirdStageState();
    }

    public int getStageNumber() {
        return 2;
    }

    public int getNumberOfRocketMotors() {
        return 5;
    }

    public String getRocketMotorTypeName() {
        return "J-2";
    }
}

public class SaturnFiveThirdStageState implements ISpaceShipState {
    public ISpaceShipState transition() {
        return new SaturnFiveCommandModuleState();
    }

    public int getStageNumber() {
        return 3;
    }

    public int getNumberOfRocketMotors() {
        return 1;
    }

    public String getRocketMotorTypeName() {
        return "J-2";
    }
}

Can we unplug class hierarchies in dynamically (I am kind of confident in Java its not possible) in an ideal Object Oriented Design?

It is possible to simulate dynamic typing in Java using reflection, although the code is very clumsy compared to the same thing in a dynamically typed language.

richj