Essential tools for Python development

Ben Finney ben+python at benfinney.id.au
Thu Apr 23 21:21:06 EDT 2009


Phillip B Oldham <phillip.oldham at gmail.com> writes:

> On Apr 22, 5:00 am, Ben Finney <ben+pyt... at benfinney.id.au> wrote:
> > code each module so that the behaviour is easily introspected and
> > tested from outside the module. If I'm not able to easily introspect
> > the code at an interactive prompt, that's a clear sign that the code
> > interface is poorly designed. So I fix that first.
> 
> Could you give a small example of this approach?

Sure, though the principle is general and applies to many different
situations (there are many more ways to write bad code than ways to
write good code :-)

A common anti-pattern is a swath of code that does too much in one
lump. A contrived example::

    def one_man_band():
        intermediate_result = (frob * spang) + foo
        floop.twiddle(intermediate_result)
        floop.juggle()
        secondary_result = spam.register(intermediate_result)
        return secondary_result

This is difficult to introspect because it's not clearly parameterised,
and it does too many things so it's difficult to trigger only part of
its behaviour for testing.

Depending on the conceptual arrangement of the steps and their actual
semantic meaning, this might work better as::

    def frob_and_spang(foo):
        result = (frob * spang) + foo
        return result

    def convert_floop(floop, twiddler):
        floop.twiddle(twiddler)
        floop.juggle()

    def register_spam(spam, entry):
        result = spam.register(entry)
        return result

    def one_man_band():
        foo_twiddler = frob_and_spang(foo)
        convert_floop(foo_twiddler)
        result = register_spam(foo_twiddler)
        return result

Rather contrived, but I hope you can see that this approach makes it
much easier to get at any of the steps that comprise ‘one_man_band’ from
outside the module, and introspect them simply by calling small
functions. Debugging is much easier with this design.

This also makes them easier to unit test; in fact, if unit testing is
adopted as a mandatory practice, it's much more likely to result in the
loosely-coupled approach *first* rather than needing to be refactored to
achieve it later.

-- 
 \         “I may disagree with what you say, but I will defend to the |
  `\        death your right to mis-attribute this quote to Voltaire.” |
_o__)                     —Avram Grumer, rec.arts.sf.written, May 2000 |
Ben Finney



More information about the Python-list mailing list