Last week I found myself wanting to automate some todo list maintenance. I’m keeping my todo list in a Zim wiki so I can access my notes easier. The internal links and formatting is very nice to have. Around the same time I was a bit curious about Python. I hadn’t worked with it in years, and even then I didn’t do anything significant with the language. I decided to take a couple of days to throw together a little script to take care of the menial work involved with maintaining my wiki. It’s a little kludgey, but it gets the job done. It probably isn’t very useful to anyone else, but I put it in a Gist just in case.
The work this program automates is fairly simple. It copies two sections of text from one file to another and does some minor editing of the first file. Since Zim has a small, regular syntax and stores everything in text files, this wasn’t a difficult task. As I started designing the program though, it became obvious that there was more work involved than I thought.
The Notebook Updater starts by reading two sections from the first (“Home”) text file — Schedule and Time Log. I keep all of my tasks in the Schedule section and a rough log of my time usage in Time Log. Both sections are copied to the second (“Week”) file and placed under the heading for the current day. After the data is safely stored in the Week file, the program starts modifying the data to update the Home file. The day’s completed tasks are removed and tomorrow’s tasks appended to the list. Then the Time Log section is cleared and the job is done.
Since this was such a small project it did not need any classes. I wrote tests using unittest for each function and tested the general operation of the program on some test data files.
This design worked out well, but there were some issues. When I started the project I didn’t plan as well as I could have. Some features of the program were designed on the spot as I was building. The features should have been well defined before I started working. This lack of design created led to messy code in some (read: many) areas. Even though it isn’t a huge or important project it still doesn’t feel right. Text manipulation isn’t my best subject, so I doubt the text-handling code is very efficient, but that’s probably not as important in this case.
The Notebook Updater project was a fun way to get started with Python. I learned something new and automated some menial work at the same time. Writing code for yourself really is a great way to learn.
You can find the Notebook Updater code here.
When should you stop planning and start working? In some projects I was ensnared by analysis paralysis and never got past the planning stage. In others I started writing code far too early and ended up redesigning the project several times. Both cases are obviously not productive and waste a lot of time.
I have been thinking about my process and why I get stuck so often. My fear of not starting seems to be greater than my fear of not finishing. I would often spend an hour or two thinking about how amazing the finished product would be and then jump into the code. Writing code must be more productive than designing code, right?
Being too eager to start working can be just as destructive and counter productive as over-planning. Without a solid plan the project is like a building without a foundation, it’ll sink into the mud when you start construction. Starting with a very detailed and rigid plan will produce a project like a house of cards; it’ll collapse under it’s own weight with the slightest disturbance. The process I’m describing tries to avoid the problems of both extremes by creating a solid plan and reevaluating it after each stage in development. It all starts with a good plan.
When I have trouble figuring out an algorithm I usually opt for a diagram in a program like Dia or on paper. A few days ago I was having a difficult time getting room saving to work properly in Constellation so I decided to draw it out. This time I didn’t use a flow chart or a diagramming program, I just used a napkin. In a few minutes I had sketched out the entire algorithm as it was going to be used in the program instead of building a set of flow charts I would only use once.
I didn’t need a big flow chart and a detailed plan of the algorithm, I just needed to see it. The sketch helped me visualize the steps. It let me refine the idea as I was working through it and spotting design flaws. Sometimes that’s all you need – A pen and paper to be your (very useful) rubber duck.
A few days ago I decided to work on a project just for fun. I called it Constellation because it sounded cool. I had no big plans or expectations for the code, I just wanted to have some fun with it for a few hours. I decided to use Ruby and try to see real results in one night. Usually these little projects don’t turn into anything and I toss the code into an “archive” to reference a couple of times a year, but this one’s different.
Writing my own text-based game engine is something I have wanted to do for a long time. I’ve played MUD‘s off and on for years and there’s something I like about text adventures. It’s like comparing reading a book to watching a movie; it’s a different experience. There is no lag, no glitchy physics, flickering textures or any of the other problems that graphical games can have to break the player’s immersion. Imagination can create more moving visuals than the most advanced rendering technology. Continue reading
Some people aren’t very fond of accessors and mutators. On the surface they seem like needless functions, a waste of code when a simple
class.variable would suffice. Some variables really are better off being set with
variable = foo than with a mutator. On the other hand, other data types have such complex initialization procedures it’s easier to pass values into a mutator. C++’s maps are a good example of this kind of situation. Which is easier,
std::map.insert(std::pair<Foo, Bar>(var1, var2)); or
This question comes up a lot when planning (and working on) programming projects. Should I use a library for this feature or just write the code myself? It can be applied to almost every section of a project. There are so many libraries and frameworks out there that you can probably get a prototype working just by gluing together third party code. There are a few factors to consider while making the decision.
Types provide a way to abstract data. 1 isn’t a collection of bytes in memory, it’s an Integer. Without types programmers would still be shuffling bits in memory. Types bundle up those bits and bytes and give a specific kind of collection of bytes a name. As with every system, no one can agree on a single way of working with types.