Rick Denatale wrote:

> Cars don't behave like engines, they use the engine internally to
> provide their power source.  

You are right; the word 'behave' vs 'use' is the key. I could not resist 
letting the 'vroom' reach the Engine without any intervention from 
Vehicle; and I let expediency trounce principle. Your eloquent point is 
taken.

> vw_bug.engine.vroom violates the 'law' of Demeter, which says that
> it's bad style to reach through one object to get at another
> So I think that to start the car it should be something like
> ..
> vw_bug.start
> 
> And the start method would cause the engine to start, producing Vrooom
> as a side effect, depending on the particular engine which was
> installed by the factory.

Here we disagree; not on (what I prefer to call) the "principle of least 
knowledge", but on the example at hand. Removing the 'vroom' method from 
the user is a bad application of that principle; customers do not always 
'vroom' to start the car, but to assert something (that I hope I don't 
need to explain). It is enough to watch a city intersection for a few 
minutes at a traffic light to see that. Removing the 'vroom' is not an 
option.

[In fact, I liked the module Engine, exactly because of that: it removed 
the need to put knowledge of 'vroom' in the Vehicle! but enough on 
trying to justify my sin].

I agree that the problem 'vw_bug.engine.vroom' is that it breaks 
encapsulation.
It seems that we are left with having to put a method in Vehicle to 
'vroom', just to transmit the command to the engine..

============

Liam wrote:

> require 'forwardable'
>  ..
> class Vehicle
>   extend Forwardable
>   def_delegator :@engine, :vroom
>   attr_accessor :engine
>   def initialize(engine)
>     @engine=engine
>   end
> end
> 
> v=Vehicle.new(Engine.new)
> v.vroom
> v.engine=MustangEngine.new
> v.vroom

> As far as comparison to Java, this example uses duck typing.  As long as 
> it vrooms, you can use it as an engine for your vehicle.

Interesting: this solves the problem of explicitly writing a 'vroom' 
method in Vehicle just to pass it to the Engine. I am not totally 
comfortable with the thought of Car 'delegating to' (as opposed to 
'having') an Engine, but it is very elegant.

=========

Personally, I learnt/conclude this (in view of some vagueness in other 
comments that seem to say the Composition is not needed):

1) Thufir was right (aside on the details for how to 'vroom'), in seeing 
the Engine as a Composition problem for Vehicle. There is an instance 
variable @engine in Vehicle! (shame on me for attempting to remove it 
:-).

2) we can use 'Delegation' to avoid silly 'bridge methods' in Vehicle, 
to allow the user reach the Engine, when needed.

Thanks!

Raul


-- 
Posted via http://www.ruby-forum.com/.