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”.
**kw Magic Arguments Carefully
The author acknowledges that use of
**kw (also seen
**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
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.,
to import some APIs into the top level of the package, including a
caveat about the increased potential of circular dependencies.
Working on APIs
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.
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.
Back to flipping out…