Another newbie question

Mike Meyer mwm at mired.org
Sat Dec 10 13:33:25 EST 2005


Steven D'Aprano <steve at REMOVETHIScyber.com.au> writes:
>> In particular,
>> you can get most of your meaningless methods out of a properly
>> designed Coordinate API. For example, add/sub_x/y_ord can all be
>> handled with move(delta_x = 0, delta_y = 0).
>
> Here is my example again:
>
> [quote]
> Then, somewhere in my application, I need twice the 
> value of the y ordinate. I would simply say:
>
> value = 2*pt.y
> [end quote]
>
> I didn't say I wanted a coordinate pair where the y ordinate was double
> that of the original coordinate pair. I wanted twice the y ordinate, which
> is a single real number, not a coordinate pair.
  
Here you're not manipulating the attribute to change the class -
you're just using the value of the attribute. That's what they're
there for.

>> And you've once again missed the point. The reason you don't
>> manipulate the attributes directly is because it violates
>> encapsulation, and tightens the coupling between your class and the
>> classes it uses. It means you see the implementation details of the
>> classes you are using, meaning that if that changes, your class has to
>> be changed to match.
> Yes. And this is a potential problem for some classes. The wise programmer
> will recognise which classes have implementations likely to change, and
> code defensively by using sufficient abstraction and encapsulation to
> avoid later problems.

Except only the omniscennt programmer can do that perfectly. The
experienced programmers knows that requiments change over the lifetime
of a project, including things that the customer swears on a stack of
holy books will never change.

> Do you lie awake at nights worrying that in Python 2.6 sys.stdout will be
> renamed to sys.standard_output, and that it will no longer have a write()
> method? According to the "law" of Demeter, you should, and the writers of
> the sys module should have abstracted the fact that stdout is a file away
> by providing a sys.write_to_stdout() function.
> That is precisely the sort of behaviour which I maintain is unnecessary.

And that's not the kind of behavior I'm talking about here, nor is it
the kind of behavior that the LoD is designed to help you with (those
are two different things).

>>> The bad side of the Guideline of Demeter is that following it requires
>>> you to fill your class with trivial, unnecessary getter and setter
>>> methods, plus methods for arithmetic operations, and so on.
>> 
>> No, it requires you to actually *think* about your API, instead of
>> just allowing every class to poke around inside your implementation.
>
> But I *want* other classes to poke around inside my implementation.
> That's a virtue, not a vice. My API says:
>
> "In addition to the full set of methods which operate on the coordinate as
> a whole, you can operate on the individual ordinates via instance.x and
> instance.y which are floats."

That's an API which makes changing the object more difficult. It may
be the best API for the case at hand, but you should be aware of the
downsides.

> Your API says:

Actually, this is *your* API.

> "In addition to the full set of methods which operate on the coordinate as
> a whole, you can operate on the individual ordinates via methods add_x,
> add_y, mult_x, mult_y, sub_x, sub_y, rsub_x, rsub_y, div_x, div_y, rdiv_x,
> rdiv_y, exp_x, exp_y, rexp_x, rexp_y...; the APIs of these methods are: ... "

That would be a piss-poor API design.  Any designer who knows what they
are doing should be able to turn out a better API than that given a
reasonable set of real-world requirements.

> My class is written, tested and complete before you've even decided on
> your API. And you don't even really get the benefit of abstraction: I have
> two public attributes (x and y) that I can't change without breaking other
> people's code, you've got sixteen-plus methods that you can't change
> without breaking other people's code.
> The end result is that your code is *less* abstract than mine: your code
> has to specify everything about ordinates: they can be added, they can be
> subtracted, they can be multiplied, they can be printed, and so on. That's
> far more concrete and far less abstract than mine, which simply says
> ordinates are floats, and leave the implementation of floats up to Python.

Again, this is *your* API, not mine. You're forcing an ugly, obvious
API instead of assuming the designer has some smidgen of ability. I've
already pointed out one trivial way to deal with this, and there are
others.

       <mike
-- 
Mike Meyer <mwm at mired.org>			http://www.mired.org/home/mwm/
Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.



More information about the Python-list mailing list