accessor/mutator functions

M

mirandacascade

When I look at how classes are set up in other languages (e.g. C++), I
often observe the following patterns:
1) for each data member, the class will have an accessor member
function (a Get<whatever> function)
2) for each data member, the class will have a mutator member function
(a Set<whatver> function)
3) data members are never referenced directly; they are always
referenced with the accessor and mutator functions

My questions are:
a) Are the three things above considered pythonic?
b) What are the tradeoffs of using getattr() and setattr() rather than
creating accessor and mutator functions for each data member?
 
M

Michael Spencer

When I look at how classes are set up in other languages (e.g. C++), I
often observe the following patterns:
1) for each data member, the class will have an accessor member
function (a Get<whatever> function)
2) for each data member, the class will have a mutator member function
(a Set<whatver> function)
3) data members are never referenced directly; they are always
referenced with the accessor and mutator functions

My questions are:
a) Are the three things above considered pythonic?
No

b) What are the tradeoffs of using getattr() and setattr() rather than
creating accessor and mutator functions for each data member?

Use property descriptors instead:
http://www.python.org/2.2.1/descrintro.html#property
http://users.rcn.com/python/download/Descriptor.htm#properties

Michael
 
S

Simon Wittber

My questions are:
a) Are the three things above considered pythonic?

Python uses a function called 'property to achieve the same effect.
This example is taken from the documentation:

class C(object):
def __init__(self):
self.__x = 0
def getx(self):
return self.__x
def setx(self, x):
if x < 0: x = 0
self.__x = x
x = property(getx, setx)


In the above example, "C().x" would invoke and return the result of
..getx (the accessor), and "C().x = 10" would invoke .setx (the
mutator).

Are they considered Pythonic? Well, It depends on how they are used.
If you are using properties to perform some kind of type checking...
then the answer is probably No.

I've found that they are quite useful for implementing lazy evaluation
of attributes, which I would consider quite Pythonic.

Sw.
 
M

mirandacascade

If the class had two attributes--x and y--would the code look like
something lik this:

class C(object):
def __init__(self):
self.__x = 0
self.__y = 0
def getx(self):
return self.__x
def setx(self, x):
if x < 0: x = 0
self.__x = x
def gety(self):
return self.__y
def sety(self, y):
if y < 0: y = 0
self.__y = y
x = property(getx, setx)
y = property(gety, sety)

?

Because if so, does the term 'lazy evaluation' refer to the fact that
instead of:

C().getx()
C().gety()
C().setx(10)
C().sety(10)

one would substitute:

C().x
C().y
C().x = 10
C().y = 10

?
 
D

Diez B. Roggisch

Because if so, does the term 'lazy evaluation' refer to the fact that
instead of:

No, it is a common technical term. It means that a value is computed the
time it is requested for the first time.

Like this:

class Foo(object):

def __init__(self):
self.__bar = None

def getBar(self):
if self.__bar is None:
self.__bar = some_lengthy_computation()
return self.__bar


That you can make bar a property of Foo is unrelated to this.

Another reason to use properties is if the value is always or at least
frequently a freshly computed one.
 
T

Terry Reedy

When I look at how classes are set up in other languages (e.g. C++), I
often observe the following patterns:
1) for each data member, the class will have an accessor member
function (a Get<whatever> function)
2) for each data member, the class will have a mutator member function
(a Set<whatver> function)
3) data members are never referenced directly; they are always
referenced with the accessor and mutator functions

My questions are:
a) Are the three things above considered pythonic?

As others have said, 'no', as in 'unnecessary because we have a better way
to accomplish the same purpose without doubling the attribute namespace'.
The purpose of the pattern is to hide the specific implementation of a
class (which attributes are static and which dynamic) and to allow that
implementation to change without changing programs that use the class.
Consider a complex class with interdependent .real, .imag, .rad, and .theta
attributes and the possible behind-the-scene implementations for what is
kept static and how they are kept synchronized. The need for get/set to
accomplish this in C++ arises from the fact that attribute names are
resolved at compile time, so that x.a syntax can only be used for simple
static attributes and access. Python, on the other hand, has means to
'magically' map what looks like direct attribute access into a function
call. First there was __get/setattr__ (which is awkward for multiple
dynamic attributes) and now properties with get/set/del for individual
dynamic attributes.
 
M

Michael Spencer

If the class had two attributes--x and y--would the code look like
something lik this:

class C(object):
def __init__(self):
self.__x = 0
self.__y = 0
def getx(self):
return self.__x
def setx(self, x):
if x < 0: x = 0
self.__x = x
def gety(self):
return self.__y
def sety(self, y):
if y < 0: y = 0
self.__y = y
x = property(getx, setx)
y = property(gety, sety)

It could do - that works. One feature of this solution is that it leaves the
accessor/mutator functions in the namespace. That may be a good or a bad thing.
If bad, you could simply delete them after the property call (which is
probably better written as close as possible to the functions)

i.e., class C(object):
def __init__(self):
self.__x = 0
self.__y = 0
def getx(self):
return self.__x
def setx(self, x):
if x < 0: x = 0
self.__x = x
x = property(getx, setx)
del getx, setx
def gety(self):
return self.__y
def sety(self, y):
if y < 0: y = 0
self.__y = y
y = property(gety, sety)
del gety, sety

There are also recipes in the cookbook for defining property "suites" more elegantly

Note, that it is also easy to "roll your own" descriptor, which may be
worthwhile if you have a lot of similar properties, for example (not tested
beyond what you see):

from weakref import WeakKeyDictionary

class Property(object):
def __init__(self, adapter):
"""adapter is a single argument function that will be
applied to the value before setting it"""
self.objdict = WeakKeyDictionary()
self.adapter = adapter
def __get__(self, obj, cls):
if isinstance(obj, cls):
return self.objdict[obj]
else:
return self
def __set__(self, obj, value):
self.objdict[obj] = self.adapter(value)

class C(object):
x = Property(lambda val: max(val, 0))
y = Property(lambda val: val%2)
z = Property(abs)


Michael
 
N

Nick Craig-Wood

Michael Spencer said:

Actually I would say just access the attribute directly for both get
and set, until it needs to do something special in which case use
property().

The reason why people fill their code up with boiler plate get/set
methods is to give them the flexibility to change the implementation
without having to change any of the users. In python you just swap
from direct attribute access to using property().

Also note that with property() you can make an attribute read only (by
defining only the get method) which is often the encapsulation you
really want - and that is something you can't do in C++.
 
D

Dan Sommers

Actually I would say just access the attribute directly for both get
and set, until it needs to do something special in which case use
property().
The reason why people fill their code up with boiler plate get/set
methods is to give them the flexibility to change the implementation
without having to change any of the users. In python you just swap
from direct attribute access to using property().

The reason their code is so inflexible is that they've filled their
classes with boiler plate get/set methods.

Why do users of classes need such access anyway? If my class performs
useful functions and returns useful results, no user of my class should
care about its attributes. If I "have to" allow access to my attributes
in order that my users be happy, then I did something else wrong when I
designed the class and its public interface in the first place.

I usually aim for this: if users of the public interface of my class
can figure out that I changed the implementation, then I've exposed too
much. Sure there are exceptions, but that's my basic thought process.

Sorry about the rant.

Regards,
Dan
 
C

Carl Banks

When I look at how classes are set up in other languages (e.g. C++), I
often observe the following patterns:
1) for each data member, the class will have an accessor member
function (a Get<whatever> function)
2) for each data member, the class will have a mutator member function
(a Set<whatver> function)
3) data members are never referenced directly; they are always
referenced with the accessor and mutator functions

My questions are:
a) Are the three things above considered pythonic?

No. It's not good programming practice in C++, either.

If you have a class that's nothing but a big data structure, you ought
to use it as a data structure. Writing accessor and mutator methods
for its fields is just doing a lot of work to accomplish nothing.

If you want to provide access to a certain occasional field, but you're
concerned about keeping the interface backwards-compatible, go ahead
and use them. But try to observe the following rules of thumb:

1. Don't provide accessor or mutator function to every single member of
every single class you write. Only provide accessor/mutator functions
if the accessor/mutator methods are a sensible and useful part of the
class's interface.

2. Don't think of these methods as accessors or mutators. Instead,
think
of them as methods that access or mutate a certain abstract property of
the object that happens to be represented by a single member.

And, keep in mind that, since Python doesn't really have private data,
you don't have to worry about adding these functions to make debugging
easier.

b) What are the tradeoffs of using getattr() and setattr() rather than
creating accessor and mutator functions for each data member?

Don't use getattr and setattr unless you have to construct the name of
the attribute at run time. That's what they're for.
 
A

Andrew Dalke

The reason their code is so inflexible is that they've filled their
classes with boiler plate get/set methods.

Why do users of classes need such access anyway? If my class performs
useful functions and returns useful results, no user of my class should
care about its attributes. If I "have to" allow access to my attributes
in order that my users be happy, then I did something else wrong when I
designed the class and its public interface in the first place.

Consider an interface to a temperature controller. It will
have several properties:

- current temperature (read only)
- target temperature (read/write)
- various tuning parameters that affect the rate of change,
stability, etc.; eg, lookup details on a PID controller

These are properties of the temperature controller object.
In Python these properties are traditionally mapped to attributes.
Under languages that don't have a __getattr__/"property" mechanism
for separating interface from implementation these are implemented
via get/set accessor methods.

It is very often useful to change the temperature setting of
a controller over time. Eg, a chemical protocol might say
"warm from 50 to 80 over a period of 30 minutes, 1 degree
per minute".

In Python that might be written as:

temp_controller = TemperatureController("/dev/com3")
temp_controller.target = 50
print "Bringing reactor to", temp_controller.target
while 1:
print "Current temperature is", temp_controller.current
if abs(temp_controller.current - temp_controller.target) < 0.1:
break
time.sleep(30)

raw_input("Insert sample and press the <enter> key: ")

for temp in range(51, 81):
print "Raising reactor temperature to", temp
temp_controller.target = temp
time.sleep(60)
if abs(temp_controller.current - temp) > 0.1:
print "Variance too high!", temp_controller.current

print "DONE!"


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

Andrew
(e-mail address removed)
 
D

Dan Sommers

Consider an interface to a temperature controller. It will
have several properties:
- current temperature (read only)
- target temperature (read/write)
- various tuning parameters that affect the rate of change,
stability, etc.; eg, lookup details on a PID controller
These are properties of the temperature controller object.
In Python these properties are traditionally mapped to attributes.
Under languages that don't have a __getattr__/"property" mechanism
for separating interface from implementation these are implemented
via get/set accessor methods.
It is very often useful to change the temperature setting of
a controller over time. Eg, a chemical protocol might say
"warm from 50 to 80 over a period of 30 minutes, 1 degree
per minute".
In Python that might be written as:
temp_controller = TemperatureController("/dev/com3")
temp_controller.target = 50
print "Bringing reactor to", temp_controller.target
while 1:
print "Current temperature is", temp_controller.current
if abs(temp_controller.current - temp_controller.target) < 0.1:
break
time.sleep(30)
raw_input("Insert sample and press the <enter> key: ")
for temp in range(51, 81):
print "Raising reactor temperature to", temp
temp_controller.target = temp
time.sleep(60)
if abs(temp_controller.current - temp) > 0.1:
print "Variance too high!", temp_controller.current
print "DONE!"

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

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. 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). 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 )

Obviously, that code is untested! ;-)

In the case of simply reading the current temperature, and not knowing
what's inside that device driver, I'd still lean away from exposing a
current temperature attribute directly. I think part of my thinking
comes from my old Pascal days, when it made me cringe to think that
"x:=b;" might actually execute a subroutine rather than just copy some
memory around.

I'm not saying that my applications *never* access my objects'
attributes directly, just that it's one of those things that raises at
least a yellow flag in my mind.

Regards,
Dan
 
T

Thomas Lotze

Dan said:
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.

But then you put application logic into a library function. Doing this
consistently leads to a monster of a library that tries to account for all
possible applications. Where does this leave the KISS principle?
In the case of simply reading the current temperature, and not knowing
what's inside that device driver, I'd still lean away from exposing a
current temperature attribute directly. I think part of my thinking comes
from my old Pascal days, when it made me cringe to think that "x:=b;"
might actually execute a subroutine rather than just copy some memory
around.

Then you also avoid lists, dicts and, ironically, methods. Accessing
methods means to access a callable attribute, after all, with all the
stuff going on behind the scenes on attribute access.
 
D

Dan Sommers

Dan Sommers wrote:
But then you put application logic into a library function. Doing this
consistently leads to a monster of a library that tries to account for
all possible applications. Where does this leave the KISS principle?

Maybe I'm "old school," but I usually end up with lots of layers in
between library functions and application logic. If I think my
"library" layer is too big, yes, I will add another layer of abstraction
around it. Nothing says that my application has to talk directly to
every low-level library function.
Then you also avoid lists, dicts and, ironically, methods. Accessing
methods means to access a callable attribute, after all, with all the
stuff going on behind the scenes on attribute access.

By that logic, I'd also avoid Python, which, obviously, I'm don't.

When I see a simple construct like "a = b," or "a = b[ 2 ]," or even
"a.b.c = d.e.f," I would like to think that nothing "magic" (for some
suitable definition of "magic") is happening. Yes, in a language like
Python, a lot more is happening (and a whole lot more *could* happen)
under the hood than in the extremely roughly equivalent "move.l d1,d2"
in assembly language.

I guess we all have our own personal tolerances for "Explicit is better
than implicit."

Regards,
Dan
 
A

Andrew Dalke

Me:
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.
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.

The note about errors is interesting. For example, if the
cable to the controller was disconnected then someone, especially
someone used to memory lookups for attributes, might not expect

temp_controller.current

to possibly raise an I/O error exception. On the other hand,
at the C level that could be memory mapped I/O, so that

int x = temp_controller.current;

could also have all sorts of side effects. That case
is dangerous in C because of its poor exception mechanism.
I think in Python it's much less of a problem.

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.

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.
I think part of my thinking
comes from my old Pascal days, when it made me cringe to think that
"x:=b;" might actually execute a subroutine rather than just copy some
memory around.

To give a more recent example for me, which I covered here some
years back, I wrote an OO interface to an "OO-ish" C library
for doing chemistry. In the data model, atoms have an atomic
symbol, a charge and a list of bonds (and many other things).
Bonds have a bond type and the two atoms at the ends of the bonds
(and many other things).

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.

Andrew
(e-mail address removed)
 
D

Dan Sommers

Dan Sommers:
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.
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).
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
 
N

Nick Craig-Wood

Dan Sommers said:
The reason their code is so inflexible is that they've filled their
classes with boiler plate get/set methods.

Amen to that! As programmers we abhor code duplication, and boiler
plate is just code duplication. Even if your fancy editor adds it for
you ;-)
Why do users of classes need such access anyway? If my class performs
useful functions and returns useful results, no user of my class should
care about its attributes. If I "have to" allow access to my attributes
in order that my users be happy, then I did something else wrong when I
designed the class and its public interface in the first place.

I would say this is an excellent philosphy for C++ or Java. When I'm
writing C++ I try to keep the attributes private. I try not to make
accessor methods at all until absolutely necessary. I always think
I've failed if I end up writing getBlah and setBlah methods. In C++
its always in the back of my mind that an inline accessor method will
get optimised into exactly the same code as accessing the attribute
directly anyway.
I usually aim for this: if users of the public interface of my class
can figure out that I changed the implementation, then I've exposed too
much. Sure there are exceptions, but that's my basic thought process.

However in python, there is no harm in accessing the attributes
directly. You can change the implementation whenever you like, and
change the attributes into property()s and the users will never know.

And, as another poster pointed out - you are already accessing the
instance variables just by calling its methods, so you shouldn't feel
too squeamish!

Read only attributes are easy to understand, unlikely to go wrong and
faster than getBlah() accessor methods.

Writable attributes I think are good candidates for methods though.
Looking inside an object is one thing but changing its internal state
is another and should probably be done through a defined interface.
Sorry about the rant.

I wouldn't call that a rant, it was quite polite compared to some of
the threads on c.l.p recently ;-)
 
S

Steve Holden

Andrew said:
Me:


Dan Sommers:
[...]

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.
Indeed, but it also comes down to control paradigm. I don't *know*, but
I'll make a guess that Dan, who admits to being "old school", hasn't
done a lot of work with GUIs, which are inherently event-based.

The difference between your approaches to controlling an external
process appear to me to be very similar to the differences between the
traditional "we ask the questions" approach of a batch program (where
the program logic dictates the sequence of inputs) and the "what just
happened" approach required by event-driven GUI-based programming.
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.
Well, you are clearly more up-to-date on Pascal than me, and I blush to
recall that I used to *teach* the language (back when "structured
programming" was supposed to be a novelty).
To give a more recent example for me, which I covered here some
years back, I wrote an OO interface to an "OO-ish" C library
for doing chemistry. In the data model, atoms have an atomic
symbol, a charge and a list of bonds (and many other things).
Bonds have a bond type and the two atoms at the ends of the bonds
(and many other things).

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.
What this may boil down to is exactly Dan's suggestion that we are all
comfortable with our own definition of "explicit".

Really, of course, the only things you need to make explicit are the
ones that readers don't understand :)

so-you-are-fine-if-there's-only-one-reader-ly y'rs - steve
 
S

Steve Holden

Carl said:
(e-mail address removed) wrote: [...]
My questions are:
a) Are the three things above considered pythonic?


No. It's not good programming practice in C++, either.

If you have a class that's nothing but a big data structure, you ought
to use it as a data structure. Writing accessor and mutator methods
for its fields is just doing a lot of work to accomplish nothing.
Unfortunately Java has introduced this as a standard practice, and a lot
of people who learned their programming by learning Java in the last ten
years have absolutely no clue what a data structure *is*. (i.e. data,
with a structure, but no logic required).
If you want to provide access to a certain occasional field, but you're
concerned about keeping the interface backwards-compatible, go ahead
and use them. But try to observe the following rules of thumb:

1. Don't provide accessor or mutator function to every single member of
every single class you write. Only provide accessor/mutator functions
if the accessor/mutator methods are a sensible and useful part of the
class's interface.

2. Don't think of these methods as accessors or mutators. Instead,
think
of them as methods that access or mutate a certain abstract property of
the object that happens to be represented by a single member.

And, keep in mind that, since Python doesn't really have private data,
you don't have to worry about adding these functions to make debugging
easier.





Don't use getattr and setattr unless you have to construct the name of
the attribute at run time. That's what they're for.
Well, they are surely helpful in delegation contexts as well, or do I
misunderstand?

regards
Steve
 
D

Dan Sommers

Indeed, but it also comes down to control paradigm. I don't *know*,
but I'll make a guess that Dan, who admits to being "old school",
hasn't done a lot of work with GUIs, which are inherently event-based.

Not a lot of GUIs, but a lot with (very large, very complex, multi
tasking, multi processor) event-driven embedded stuff, almost all of
which was in C and/or assembly languages. The C++ stuff I saw made me
want to gouge my eyes out, but a lot of us felt that way at the time,
and we think it came down to the particular (ab)uses of C++ involved.
Really, of course, the only things you need to make explicit are the
ones that readers don't understand :)

+1 QOTW

We used to have holy wars over the appropriate level of comments in
source code.

Regards,
Dan
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,221
Messages
2,571,133
Members
47,748
Latest member
LyleMondra

Latest Threads

Top