This post originated from an RSS feed registered with Python Buzz
by Ian Bicking.
Original Post: A Python Poka-Yoke
Feed Title: Ian Bicking
Feed URL: http://www.ianbicking.org/feeds/atom.xml
Feed Description: Thoughts on Python and Programming.
A while ago I read about Poka-Yoke, a Japanese quality assurance
technique. To me it really seems like attention to the small
processes we go through in performing our tasks; an example:
System Message: WARNING/2 (<string>, line 6)
Explicit markup ends without a blank line; unexpected unindent.
In the old method, a worker began by taking two springs out of a
large parts box and then assembled a switch.
In the new approach, a small dish is placed in front of the parts
box and the worker's first task is to take two springs out of the
box and place them on the dish. Then the worker assembles the
switch. If any spring remains on the dish, then the worker knows
that he or she has forgotten to insert it.
This kind of attention to detail in manufacturing obviously applies
very much to software development as well, where small defects can
cause difficult bugs. Keith Ray also writes about this.
An obvious Poka-Yoke for Python is PyChecker, which checks Python
source for many common problems. But I find the most important Python
Poke-Yokes are the ones built right into the languages. Exceptions
are our defect detection mechanisms, moreso than analysis. Prevention
is done in a more ad hoc manner.
My little Poke-Yoke: don't use default arguments. It's tempting to
find a sort of "preferred" value for an argument, or a trivial value,
and use that as a default. For instance, every boolean input can
probably be thought of in terms of a default and non-default input.
This especially becomes tempting when you have a large number of
inputs to a function, as with some constructors.
But what seems to be the obvious default value when writing the
function isn't necessarily obvious when reading the function
invocation. Even worse, the reader may not even recognize that the
default exists.
More importantly, though, is that you not cover up complexity. Given
a long, complicated function signature, when you use that function you
need to look up the signature, and understand all the arguments. You
should explicitly and consciously choose values for all the
arguments. If you do not do so, you'll get an exception -- problem
detected. With default arguments, you may miss something
unintentionally but have your mistake "fixed" by the default value.
But the default can't think for you, and it can't make the
context-sensitive decision about the appropriate value for that
argument.
This should not be confused with an indictment of keyword arguments --
quite the contrary, in fact. Keyword arguments are another Poka-Yoke,
that protect you against misremembering the order of arguments, or
having that order changed. They also mean that the values are tightly
bound to the argument names, which are indicative of semantics --
change the semantics, then change the argument names, then change all
function invocations. You don't need default values to use keyword
arguments, so you can use keywords copiously, and almost always
increase readability in the process.
Of course, these aren't hard rules. But in the right context these
can save you some problems -- or maybe just make you immediately aware
of the problems.