Showing posts with label book_review. Show all posts
Showing posts with label book_review. Show all posts

2011-08-30

Book Review: Python 3 Web Development Beginner's Guide

I recently received a free review copy (eBook version) of
Cover art for Python 3 Web Development Beginner's Guide
from Packt Publishing. I was looking forward to this book, because I haven't really done much Python 3 work yet, and I wanted to see how it could make my life as a web developer better. However, the book wasn't what I expected. Instead of covering the basics of web development and how Python 3 applies, it is more of an introduction to the sorts of concerns that come up when you build a web framework on top of CherryPy. The sample code just happens to be in Python 3.

The Good

The two best parts of the book, to me, were the coverage of writing a jQuery plugin, and growing an ORM that uses metaclasses to provide a compact, readable way to define the models.

The Bad

I have a rather long list of things I didn't like about the book, some of which are a function of the title setting misleading expectations, and some of which I think are just problematic in general.

In general, I didn't care for the examples. Some of this is personal preference: I find that many people (myself included) learn better when they must type in the examples instead of opening up the code and reading through a completed solution. While the book sometimes indicated that something had been left as an exercise to the reader, opening up the sample code showed that the exercise actually had not been left to the reader. This mismatch between what the text of the book says will be in the sample code and what is actually in the sample code occurs in multiple places throughout the book, and gives a sense that the book was sloppily edited.

I also felt the examples in general were too complicated. It's fine to build up a complicated example over the course of a book, but instead we got a task list, a wiki, a Customer Relationship Management (CRM) tool, a spreadsheet, and more. That's an awful lot to distract you from the beginner's principles that you would expect in a book with this title.

I also didn't care for many of the shortcuts taken in the book. In most instances, the book did acknowledge that the approach taken was not appropriate in the real world, but then proceeded with little or no justification for why it was done the way it was. The two examples that really leap out in this category are the password hashing scheme and the failure to use a template engine.

When the book first introduces authentication, it explains that you should never store passwords in plaintext. This is absolutely correct, but the book then goes on to demonstrate a completely insecure password hashing scheme: UNSALTED SHA1. The author only provides a cursory link to explain what you should actually be doing. In this day and age, demonstrating anything less than a bcrypt-based solution is wrong. Read Enough With The Rainbow Tables and How To Safely Store A Password for a far better explanation than I can provide. There's really no excuse for this: the added complexity of using py-bcrypt instead of writing your own (insecure) SHA1-based solution is trivial at worst; there's a strong case to be made that it would actually be simpler.

The failure to use a template engine (also a weakness acknowledged by the book) really makes the code harder to follow than it should be. Virtually any serious web development effort is going to take advantage of a template engine, and for good reason. This code gives me flashbacks to my days of writing Java servlets before the advent of JSP, and I saw where one other reviewer invoked the specter of PHP. The fact that this style of coding draws such comparisons should give you an idea of just how unpythonic it is. I would be sympathetic to claims of not wanting to add too many external dependencies if the book did not already rely significantly on the magic of jQuery UI.

My last major complaint is simply one of focus: the book spends substantial amounts of time growing an ORM and teaching Python metaclasses (and doing a good job of it), but spends little more than the bare minimum required on CherryPy (which is at the core of the code), and essentially none on understanding HTTP. In fact, the few times it comes up is usually in relation to GET vs. POST, where the decision is usually made based on inane implementation details such as whether request arguments are logged by default instead of HTTP fundamentals such as idempotency, safety, or cacheability (although caching is mentioned elsewhere, in the context of how to prevent it). Also, the book does mention security, but it does not give it the sort of omnipresent emphasis that is necessary to write good web applications, given the hostile nature of the domain. XSS, CSRF, and SQL injection attacks all deserve much more attention than they were given.

The Summary

The book has some good content mixed in with the stuff I didn't like. Unfortunately, the good content is rarely specific to web development. For example, the chapter that uses metaclasses to clean up the ORM is one of the better resources on metaclasses that I've seen, but metaclasses are clearly not specific to web development. Furthermore, the impression of sloppy editing makes it hard to put as much faith in the content as it probably deserves. Given these flaws, I really don't think I'd recommend this book to a friend who was looking to get started with web development.

Back to flipping out...

2011-08-06

Now Reading: Python 3 Web Development Beginner's Guide

Packt Publishing has kindly given me a free review copy of the eBook edition of
Cover art for Python 3 Web Development Beginner's Guide
I'll be reading it and publishing my review here and on the PyATL Book Club blog.

Back to flipping out...

2009-06-06

Review of Expert Python Programming, Part Four

Chapter 5: Writing a Package

A Common Pattern for All Packages

This section provides all the details necessary to create a namespaced package that consists of multiple eggs glued together by a master egg using distutils and setuptools. There are multiple subsections that cover everything you should need to build your project, register it with the Cheeseshop (or any other package index), and upload it for the world to enjoy.

How to Uninstall a Package

This section provides a short rationalization for why there isn't a built-in uninstall command and the current workaround. It's not mentioned in the book, but the author is currently working on improving distutils, and an uninstall command is on the agenda. The full details are in the Adding an Uninstall Function section of PEP 376.

The Template-Based Approach

After covering the basics of building and distributing a package in the previous section, this section focuses on using templates to reduce the tedium in creating consistent application skeletons. The tool used in this section is Python Paste. There are a couple of short examples using pre-existing templates.

Creating the Package Template

This section covers the process of creating a custom template that describes the structure introduce in the first section.

The rest of the chapter just covers generic aspects of the development cycle, such as version numbering, so I will skip it for this review.

Back to flipping out...

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

2009-05-23

Review of Expert Python Programming, Part Two

Chapter 3
Subclassing Built-in Types
  • I started learning Python after this was added, so it never occurred to me not to do this.
Accessing Methods from Superclasses
  • Tries to explain super, but it's quite confusing (mostly due to the multiple-inheritance problems).
  • The standard docs do a better job of making it clear the main benefit is making maintenance easier in single-inheritance examples.
Understanding Python's Method Resolution Order (MRO)
The section isn't as clear as it could be, but it has solid information. It explains what the MRO is used for and how it's different between 2.2 and 2.3, and the __mro__ attribute
super Pitfalls
Points out some of the most common problems with super: mixing super and classic calls (and how to use __mro__ to choose what to do) and subclass constructors that take arguments that differ from their parent classes.
Best Practices
  • Solid, short (so you can remember it) section.
Descriptors and Properties
Descriptors
This section isn't overly clear. It describes what descriptors are from a technical perspective, but doesn't do a great job of explaining why you'd want to use them. Also, a fair number of the examples have errors, e.g., code for setting values when the text says it is for reading values. Luckily, it contains a link to the (more helpful) How-To Guide for Descriptors.
Properties
This section explains property and the property attributes it returns (though not necessarily why they're so useful) and does a good job of pointing out some gotchas, e.g., the way they don't pick up overridden methods. The solution offered is perfectly sensible: override the property instead of the (typically private) method bound to fget.
Slots
  • Short but informative section on slots, which I haven't seen mentioned before.
Meta-Programming
The __new__ Method
This section covers __new__ and its usefulness for making sure that a class's invariants aren't violated because a subclass didn't explicitly invoke __init__.
The __metaclass__ method
This section covers customizing class creation using __metaclass__ and points out that, in most cases, there are easier-to-understand alternatives. One example of when there isn't is adjusting read-only attributes, e.g., the __doc__ attribute of the built-in metaclass type. Other suggested usages for __metaclass__ include frameworks enforcing behavior across large groups of classes and orthogonal functionality such as logging. The section closes with a link to A Primer on Python Metaclass Programming.
Summary

The summary section is a short, bulleted list highlighting the most important points made in the chapter. Again, it's short enough to be easily memorable.

Back to flipping out...

2009-05-21

Review of Expert Python Programming, Part One

As I mentioned, I got started with the PyAtl Book Club at the May meeting. The first book I received was Expert Python Programming, by Tarek Ziadé. Part of the deal with the book club is posting a review of the book, so I will be posting about the book as I work my way through it.

Chapter 1

This is basic setup info (though the vim section has a nice selection of config settings for those new to it), so I won't really cover it; I already have multiple versions of Python running on my dev box.

Chapter 2

This chapter is entitled "Syntax Best Practices—Below the Class Level", and that's a pretty accurate description. There's a short section on List Comprehensions followed by a longer section on Iterators and Generators. This is a fast but detailed look at the subject, including the use of send and coroutines (via the mechanisms defined in PEP 342). The treatment is rather brief, so I recommend David Beazley's A Curious Course on Coroutines and Concurrency for more detail. Up next are genexps (defined in PEP 289); these were added in Python 2.4. This section is short and to the point: use genexps wherever you would use a list comprehension unless you need some feature of lists that a generator lacks. The next section is a brief glimpse at itertools. It is hardly complete, but it does highlight one of the (IMO) most interesting pieces of the module: tee. This function makes it practical to use genexps even when you need to make multiple passes across the data. Up next is the section on decorators (defined in PEP 318), which were introduced with Python 2.4. The author addresses decorators in much more detail than the previous topics, with extended examples of using them for various things such as caching, proxies, and context providers. That last provides a nice segue into the next session, where he shows us how to replace context provider decorators by using the with statement (defined in PEP 343) introduced in Python 2.5. The author does a pretty thorough job of explaining what with is doing and how you can use it to good effect, including how to use the contextlib module (introduced at the same time as the with statement) to use context managers with code that doesn't provide them out of the box.

Thoughts

Although it was a bit whirlwind at times, the author does a good job of covering the modern language constructs that Python has picked up in the last few versions. Although you may want to read a more detailed tutorial on a given feature, this chapter does a good job of getting you up to speed with modern Python.

Back to flipping out...