accessor/mutator functions

Dan Sommers me at privacy.net
Tue Mar 1 04:18:43 CET 2005


On Tue, 01 Mar 2005 02:27:03 GMT,
Andrew Dalke <dalke at dalkescientific.com> wrote:

> Me:
>>> What's wrong with the use of attributes in this case and how
>>> would you write your interface?

> Dan Sommers:
>> I think I'd add a change_temperature_to method that accepts the target
>> temperature and some sort of timing information, depending on how the
>> rest of the program and/or thread is structured.

> Hmmm.  I wonder if this is mostly a question of how the process
> decomposition occurs.  I think in objects ("thingys with state")
> whereas you think in tasks ("thingys that do stuff")?  I say that
> somewhat surprisingly in that I'm not a deep OO person - functions are
> fine with me and I don't like the Java/Ruby "everything is in a class"
> world view.

I'm not an OO guy, either.  Somewhere back in the mid 90's, I was
dragged, kicking and screaming, into OO from the world of Structured
Programming.

You're right about my notion of an object:  I think that if all you have
is state information, then you just have a C struct and there's no point
in doing OO.  I still write plenty of (smallish) programs like that.

>> It might turn into two or three methods, depending on whether I can
>> afford to block while waiting, or what kind of intermediate feedback
>> and/or error handling I want (or one method with some carefully
>> chosen default arguments).

> In the case I'm hypothesizing (haven't worked with a temperature
> controller in about 15 years) it's hard to put a layer above
> everything because there could be so many different protocols
> (chemical protocols, not I/O ones) with different rates.  Eg, it could
> be an exponential decay, or step-wise approximation thereof.

Yes, it would be difficult (and silly and a maintentance nightmare,
too!) to put every protocol into the temerature controller.  I think at
that point, I'd put the protocols in a separate "layer," and I'd have to
think carefully about that layer's interface to the temperature
controller.  My application would be that much farther from even having
to know the current temperature, let alone access it directly from the
TemperatureController object (although at some point, the application
would probably end up displaying that current temperature, so it's not
like everything is completely isolated from everything else).

>> I don't know how that device driver works, but it might look something
>> like this:
>> 
>> def change_temperature_to( self, target, seconds_between_checks ):
>> print 'target temperature:', target
>> tell_the_device_to_change( )
>> while 1:
>> current = read_the_temperature_from_the_device( )
>> print 'current temperature:', current
>> if abs( current - target ) < 0.1:
>> break
>> time.sleep( seconds_between_checks )

> Your "tell_the_device_to_change" is my "self.target" and your
> "read_the_temperature_from_the_device" is "self.current_temperature".
> In some sense it comes down to style.

My point was mostly that change_temerature_to would be a method of a
TemperatureController object.  "tell_the_device_to_change" is whatever
method/function you have behind setting self.target.  As you noted, I
think of the temperature controller as being able to manage its own
temperature rather than be a (thin) wrapper around a device driver.

> BTW, had I done this for real I would have two layers, one which is
> communications oriented ("send 'get current temperature' message to
> device") and my object model which uses the messaging interface
> underneath.

That sounds about right.

> I liked being able to say:

> print atom.symbol, "with charge", atom.charge, "has", \
>       len(atom.bonds), "bonds"

> for i, bond in enumerate(bonds):
>   print "bond", i, "has type", bond.bondtype

> To me this is a very natural way of querying the data and
> traversing the data structure.

> Now underneath the covers it looks like this:

>   atom.charge fails so use __getattr__(atom, "charge")
>   __getattr__ uses a dispatch table to get the underlying C function
>       which is "dt_getcharge"
>   return dt_getcharge(self.handle)

> where "handle" is the handle used by the C library.

> I figured though that this example might be more esoteric
> than my PID controller example, though in retrospect it
> looks like it might be a better justification.

I like that kind of abstraction:  the atom object hides the fact that
the charge comes out of another layer/library/object entirely.

Regards,
Dan

-- 
Dan Sommers
<http://www.tombstonezero.net/dan/>
μ₀ × ε₀ × c² = 1



More information about the Python-list mailing list