tags:

views:

53

answers:

4

Consider the following analogy: If we have a class: "Car" we might expect it to have an instance of "Engine" in it. As in: "The car HAS-A engine". Similarly, in the "Engine" class we would expect an instance of "Starting System" or "Cooling System" which each have their appropriate sub-components.

By the nature of encapsulation, is it not true that the car "HAS-A" "radiator hose" in it as well as the engine?

Therefore, is it appropriate OO to do something like this:

public class Car {
   private Engine _engine;

   public Engine getEngine() {
      return _engine;
   }

   // is it ok to use 'convenience' methods of inner classes?
   // are the following 2 methods "wrong" from an OO point of view?
   public RadiatorHose getRadiatorHose() {
      return getCoolingSystem().getRadiatorHose();
   }

   public CoolingSystem getCoolingSystem() {
       return _engine.getCoolingSystem();
   }
}

public class Engine {
    private CoolingSystem _coolingSystem;

    public CoolingSystem getCoolingSystem() {
        return _coolingSystem;
    }
}

public class CoolingSystem {
    private RadiatorHose _radiatorHose;

    public RadiatorHose getRadiatorHose() {
        return _radiatorHose;
    }
}

public class RadiatorHose {//...
}
+2  A: 

By reaching inside other encapsulated classes you are asking for trouble. The whole point of encapsulation is that you shouldn't need to know how the function is implemented, rather what it does and how to access it.
If I were to change some way in which cooling system and radiator hose interacted, engine shouldn't be affected at all. In the case where you put forth though this would cause issues. This really isn't correct OOP, and will cause problems in the future.

Daisetsu
+3  A: 

Check up on the Law of Demeter.

Jonathan Leffler
A: 

As a rule of thumb, you can first use the nature language to describe the relations among the components, which are lately represented as classes, and then use certain diagrams to present these relations. If two components are connected in your diagrams, they should have certain connection in your program. In your case, you can determine whether "engine" is an instance of "car", and "cooling system" is an instance of "engine" by observing whether there are connections among these components in your diagram. (This process is actually the intuition of OO modeling language such as UML.)

As a matter of fact, I don't see anything wrong in your code. I'm not a car person, so I might be wrong of understanding the system. But if the engine of a real car needs a cooling system, I think what you're doing is correct. Yes, the "engine" class does call the property of "cooling system" class, but because the "engine" uses the public method to invoke the "cooling system", it's the right way. Again, I don't know the real car system, so I might be wrong on this particular design.

Paul
+2  A: 

Here is a really good (and quite short) paper on the law of demeter called the The Paperboy, The Wallet, and The Law Of Demeter:

http://www.ccs.neu.edu/research/demeter/demeter-method/LawOfDemeter/paper-boy/demeter.pdf

When, you've read this you should read this short article which details how many people misinterpret the law of demeter. By doing this, the article acts as a really good explanation. It is aptly called "The Law of Demeter Is Not A Dot Counting Exercise"!!!!

http://haacked.com/archive/2009/07/14/law-of-demeter-dot-counting.aspx

David Relihan
I just finished the PDF and was almost through with the article already - but this could be helpful to someone else. +1
javamonkey79