Ben Giddings wrote:

> Sean O'Dell wrote:
> 
>> To manipulate a string, the Text object needs *no* input from the 
>> Image object.  It's job is to manage a string.  That's all it does.
>>
>> The Image object, however, needs to know about MANY different object 
>> types because it receives them as input for determine how to 
>> manipulate the image.  It manages an image buffer.  That's all it does.
>>
>>  From that, I can only envision image.draw(text) as the most logical 
>> pattern.
> 
> 
> If you step back and try to think about these things in the real, 
> physical world, every object would need to have a method for interacting 
> with every other object, but to different extents.
> 
> Take a rock, paper, and a pair of scissors.  ;)
> 
> When the scissors and rock interact, they are both affected by the 
> interaction, the rock could be marked by the scissors, or perhaps even 
> chipped; the scissors could be broken by the rock.  When the paper and 
> scissors interact, it is almost exclusively the paper that is affected, 
> but after cutting thousands of pieces of paper, the scissors will be 
> slightly dulled.
> 
> This is simply Newtonian physics.  For every action there is an equal 
> and opposite reaction.

I don't think atomic physics is a good paradigm for programming, it's 
too "wishful".  It sounds like you mean OO programming should be such 
that all you have to do is make an object, describe its basic properties 
and then send it off into your program, so it can find its natural place 
and natural purpose.

> Typically in OO programming it is convenient to assume that only one of 
> two objects is affected by their interaction.
> 
> The "Image" object in the example is similar to real-world paper, you 
> draw on it, cut it, etc.  In interactions with other things, it is 
> _fragile_ and easily affected.  A "Pen" or "Pencil" in a typical drawing 
> program is similar to a real-world pen or pencil.  When it interacts 
> with "Paper" (or Image objects), it is mostly the paper that is 
> affected, not the pen.  On the other hand, in the real world pencils do 
> get dull and pens do get empty, but mostly in OO design we are using 
> idealized representations of pens and pencils which don't get dull or 
> empty.
 >
> If we don't care about pencils getting dull or pens getting empty, we 
> can simplify our software.  For this reason, when we're drawing on an 
> Image objects in software it often makes more sense for the Image to be 
> the receiver of the message, not the sender, and for the code 
> implementing changes to be in the Image, not in the Pen.
> 
> Sometimes having the affected object be the receiver can have some 
> strange effects though.  paper_obj.draw(pen_obj) may make more sense as 
> a programmer, but it is strange that a it seems to be the paper drawing, 
> and not the pen.  In this case, it might make more sense to make it 
> paper_obj.getDrawnOnBy(pen_obj) but that's both long-winded and 
> odd-looking.

I do a fair amount GUI programming, so your example is one I can take on 
personally.

The Image object in our previous example had two jobs, actually. 
Enclose the image buffer and manipulate the image buffer.  It's purely a 
matter of taste if you wish to break it out.  You could say:

Writer.write(image, string)

Which would work just as well.  You have moved the job of writing to 
Writer and now Image does nothing more than encapsulate an image buffer. 
  The Image object now needs to export methods that the Writer object 
can use to perform its job.

Now, I think, it's closer to being "perfect".  I, personally, am not 
offended when an object does a little more than it should, so long as 
that functionality is not wastefully repeated elsewhere or grows beyond 
a method or two.  At some point, it should go into its own object.

> Unlike the pen and paper example, there are situations when two objects 
> both have to be affected by an interaction.  Take a person withdrawing 
> money from an ATM  The person is affected by his/her money count going 
> up, the ATM is affected by its money count going down.  In this case, 
> both objects are strongly affected by the interaction.  Although in 
> reality this is one atomic transaction, it is normally done as two 
> transactions, and some external means is used to make sure that both 
> sides of the transaction happen.
> 
> Which makes more sense here?
> 
> customer.getMoneyFrom(atm)
> atm.giveMoneyTo(customer)

Actually, neither.

The ATM knows nothing about the Customer object, it knows requests and 
issuing money.  The Customer object knows about the ATM, requesting 
money and receiving money.  I would write it like this:

customer.requestMoneyFrom(ATM);
customer.receiveMoney(ATM.moneyHangingOut);

Just be careful never to do this:

customer.requestMoneyFrom(ATM);
customer.forget(WHATHESDOING);
customer.walk(BACKTOTHECAR | WHILESCRATCHINGHIMSELFABSENTLY);

> I think your answer to the question depends on how you've designed your 
> objects.
> 
>  From what I can see, the way methods are typically assigned to objects, 
> typically it is the object which is most affected by the interaction 
> which has the method attached to it.  In the situation where a string is 
> being printed, the string is typically unaffected by that interaction, 
> however the output stream is affected, so the "print" method is attached 
> to the output stream.  When both objects are affected the rules are more 
> arbitrary, as I said before, it depends on how you've designed your 
> objects.  Failing that, the rule seems to be that the interaction is 
> described in a sentence in the most natural subject->verb->object way, 
> and the subject of the sentence becomes the object to which the method 
> is attached.

"Most affected" seems arbitrary.  I think just keeping the objects doing 
what they do is the simplest way to look at it.

The ATM and the Customer are not objects in a vacuum.  They have 
purpose.  The ATM's job is to hold money until a proper request is made 
and then dispense the money.  The Customer's job is to walk, eat, sleep, 
work, drive and visit ATMs to request and receive money.

> Luckily, most of the time when we're programming, we're dealing with 
> things at an abstract enough level that we can have objects which are 
> not affected when they interact with other objects.  When we print a 
> string, only the output is affected, and not the string, so only the 
> output needs to have a method.

I think "is the job of" is more appropriate than "is affected by". 
Printing doesn't just happen.  The Output object provides that 
functionality.  We're wrapping the concept of printing to a console into 
an Output object.

	Sean O'Dell