It is sometimes humbling to look back on code you’ve written. It is particularly humbling when you see a piece of your own code and wonder, “What was I thinking?” I’ve been going through this sort of programmer-introspection induced humiliation lately with my podgrabber project.
podgrabber began its life as a really simple Python script which would go through a set of RSS feeds, figure out what to download, then pull them in. I then decided to make it a little more interactive and allow the user to specify which of the undownloaded podcasts to download. A little coding, a little hacking and it was so. Somewhere along the way, I created a simple sync script to get the podcasts synced up on my MP3 player. (The MP3 player I had was a Sandisk Sansa e130 which showed up as a USB drive under Linux.) The final addition to podgrabber was a GUI (built in pyGTK) which would consolidate all of these features.
The GUI podgrabber has been pretty functional. I can add, remove, or update podcast feeds. I get a list of new podcasts and can select to either download all of them or just some of them. And I can go through a list of podcasts which are currently on my hard drive, delete them, and the next time I run “sync“, the old ones will be removed from my MP3 player and the new ones will be added.
While it has been functional (I use it nearly every work day), the architecture has made code changes pretty painful. I became very aware of this the other day when I went to make some change, the details of which I can’t recall at the moment. I really tried to separate the code into logical pieces, decouple components from unnecessary interaction with others, and plan for future easy extension such as downloading bittorrents and changing the frontend to be QT rather than GTK. But somewhere along the way, beauty and simplicity departed, code from one component melted into another, and the overall structure lost cohesion.
I intended the architecture to be sort of MVC based. The controller was supposed to be the central location for dispatching requests to do stuff. The view was supposed to interact with the user. And the model was there to store data and provide an interface to get at the data (mostly configuration related).
The primary culprit in the “code melting” issue was the configuration model. I store configuration information in a YAML file and deserialize the file at app startup. That has worked pretty well….except for the fact that I made nearly every component have to rely on having this configuration object to do its job. I became aware of how dumb this was when I attempted to separate out my download manager and create a command line utility for simple downloads. What was I thinking? And I won’t even mention referencing the config object in the GUI code rather than using a controller method….
Another problem was the lack of a good API for any given component. Since I built podgrabber as I went along, I built the interfaces as I went as well. The controller particularly has a feel of just being thrown together rather than planned. As I needed a new method on some component, I would just add it to the implementation class rather than to some formal interface class. (I am really not a fan of statically typed languages which require such behavior, but I think creating an interface class can help quite a bit by way of documentation and having a short summary of how an object of some type is supposed to behave.)
Yet another issue has been trying to let some pieces do too much. For example, the controller currently has logic for syncing files between my filesystem and my MP3 player. The result is that some modules, classes, or functions become unnecessarily large and complex.
So, what is the point of this post? This is an introduction to a journey of my rewrite of my podgrabber project. I would say “refactoring” rather than “rewrite”, but I think that “rewrite” is closer to the truth. I already have an architecture planned out and have begun implementing some of it. But as I make progress, I’ll post back with an update. I’m setting up a Bazaar repository on a hosted server and will include that reference in the next post. This is an open source project. The initial code referenced above is realeased under the MIT license and I am releasing this rewritten code under the same. So, play along. If you have suggestions along the way, please feel free to post them. If not, I hope you will find this entertaining and informational. If you have flames, send those along as well.