2009-06-06

Review of Expert Python Programming, Part Three

Chapter 4: Choosing Good Names

This chapter is aimed at helping improve API design, mostly by helping improve the names you choose when building the API. Ironically enough, not all of the advice is about naming, so the chapter title could be better. Most of the advice is good, although some of it overlaps with PEP 8 and some of it is far more general than just Python. That doesn't dilute the value of the advice, but I will skip it in this review.

Best Practices for Arguments
Build Arguments by Iterative Design

This advice is applicable to pretty much any language, but it is surprising how many people get it wrong. Also, if you're new to languages that allow you to specify default values for parameters, this section highlights one of the best uses for that feature.

Trust the Arguments and Your Tests

More solid advice: don't try to recreate a static typing system in a dynamically typed language. This isn't exactly profound insight, but a lot of people (myself included) make this mistake when they transition to dynamic typing from static typing. Instead of just saying "the tests will catch that", which some interpret as "write unit tests and/or assertions to enforce static-style typing", the author is careful to explain that the tests are supposed to test actual use cases. The author also mentions Design-by-Contract. While he doesn't seem to favor it, he does provide a link to Contracts for Python. It should be noted that the related PEP 316 has been deferred, so some people may find the resulting code "unpythonic".

Use *args and **kw Magic Arguments Carefully

The author acknowledges that use of *args and **kw (also seen as **kwargs) is sometimes necessary, e.g., metaprogramming, but in general considers them a design smell. He also offers advice for improving the design, e.g., accepting a single iterable parameter instead of *args.

Module and Package Names

Mostly mundane and duplicative of PEP 8, but there are a couple of gems: the convention of using a lib suffix in a module or package name if it is implementing a protocol, e.g., smtplib; using __init__ to import some APIs into the top level of the package, including a caveat about the increased potential of circular dependencies.

Working on APIs
Tracking Verbosity

Even though this is the sort of generic advice I said I was going to skip, I liked it so much I decided to include it anyway. If there is a common use case for some sequence of calls into your API, you should expose a function that encapsulates it. Doing anything else just invites errors.

Building the Namespace Tree

I really liked this section. In just a couple of short pages, the author shows an example of evolving the namespace structure for an application. I don't have enough experience in the Python world to know if this is a realistic example, but I thought it was presented well and made good sense. I also like that the book addresses this topic at all. The Zen of Python says "Namespaces are one honking great idea -- let's do more of those!" but I don't see many mentions of resources covering how to design them well.

Using Eggs

This sections provides a concise explanation of what eggs do and a sneak preview at how to define them. I would have liked more info, but the inset promises more details in Chapter 6.

Using a Deprecation Process

The advice in this section is also generic (don't break an already-published API), but I mentioned it because it shows the Pythonic method for deprecating old APIs: DeprecationWarning.

Useful Tools

This section only lists two tools: Pylint and CloneDigger. They are useful, but some tips for using them to greatest effect would have been nice.

Back to flipping out...

blog comments powered by Disqus