Good code vs. usability

Writing Python in a “Pythonic” way means adhering to conventions1 and using the language in the most general way possible2. I would even go so far and say, that only Pythonic code is correct code. Unfortunately, this assumption crumbles away when using Python code to interact with an end-user.

It is not uncommon to use Python itself as a domain specific language because it is easy to learn and comes with a high quality, standard library and a vast amount of third-party libraries that fill in even the smallest niche. This was also the route that a colleague and I took for a piece of software that we are currently developing. With this software, the user is expected to control hardware devices from within an IPython shell.

Here is the dilemma: On the one hand, I try to write as Pythonic as possible, on the other hand, I want to make it as easy as possible for the user to accomplish a given task. For example, in a proper way, a function is called by appending parentheses at the end of the name. But then, is the user aware of being inside a programming environment? Instead of writing device.show_info(), the user wants to type

>>> device

and investigate a device’s state. So, I abuse __repr__ and return a string that does not “look like a valid Python expression”, hence violating a very basic requirements of the object “protocol”. Not very cool in my book.

I also added a function that shows information for all devices currently defined. This is impossible to achieve without inspecting the frame stack, iterating over all globals() and checking the type via isinstance(). This is pure magic, but again very helpful for the user.

Without going on with more examples, the question quickly becomes: Where to draw the line? How much should I mess with Python internals for the sake of a nice user interface? Is even using Python as a DSL the right approach?

Maybe I am not experienced enough, but unfortunately I cannot answer these questions.

  1. PEP8 is the prime example to enforce a consistent style through formal conventions whereas PEP20 is an informal guide line for writing good Python code.

  2. Often, iterating over iterables instead of manually constructing for loops is given as an introductory example for Pythonic code.


Discussion