Photo by Trey Ratcliff (license: Noncommercial Creative Commons).
Building software can be as tricky as managing a complicated metropolitan city. Yet, as with many other things related to delicate handling, there are always approaches which are, time and time again, proven to streamline the workflow and increase the chance of success.
During my amateur and professional time doing software development, I collected selection of best development practices which I had hoped I could really exercise. With PhantomJS and Esprima, I finally got the chance to give these practices a try. Often they work, sometimes they don’t.
Note that obviously these are not all what we are doing. There are the typical mandatory activities like test-driven approach, extensive code review, proper repository access, agile trick, and the usual yada yada.
plan your release like you plan your wedding
When you say, “Sweetheart, we’ll have our wedding on the 4th of July this year”, you mean it. You won’t come back again in several weeks and then express “I’m not ready yet, let’s postpone it by few months”. Barring any extraordinary events (earthquake, nuclear holocaust, or world war), you give your best to fulfill your commitment. You want badly that you two get married on that date.
The implication of this is huge: you give your words to the users that you will ship a release and you won’t slip at all cost. It helps if you put a sticky note with that fundamental premise in front of your desk. Read it every morning, loud if necessary.
Never forget that real artists ship.
predictable time-based release
Now that you set a contract between you and your users about the release, pick a reasonable date and stick with it. I was always undecided about time-based releases but over the last few years I can see how this makes sense after all. Engineers are excited about cool new stuff, customers are thrilled about getting the best possible values. The first group is the early adopter, but the folks who stick with your product always need something stable to serve their own customers.
There is a dramatic consequence of this approach with respect to feature development. First of all, you need to align your development timeframe with the release plan. This is always good as not everyone can afford “release it when it’s done” strategy. But the best side effect that you want to isolate your refactoring, rewrite, redesign, and the other two dozens potential screw up. Modern version control, like Git, makes it easy to create a special feature branch, while at the same time also doing frequent merge and QA from the stable branch.
A small choice I make for PhantomJS, it’s always released every season. To make it more fun, the release date is chosen to be a solstice or an equinox. Astronomy does not need to be boring, right?
use the project tracker extensively
Even if you are the only developer working on your project, there is a chance that you don’t remember everything. Assume right now you still remember most of the important stuff, in few months things will look different. Real life takes over sooner or later. Out of sudden you have a baby and good luck trying to recall how you ended up with that obscure design choice.
A lot of projects use some sort of tracking software, usually web-based, which allows you to create an entry and track them. For software hosted at Google Code, Github, SourceForge, etc, the tracker software is pretty good. Use the tracker for note taking. Capture your Eureka moment and save it for your future kids. It is imperative that every little decision must be properly documented (I know, it’s just common sense!). For large-scale projects (like WebKit), this is logical but I believe any small-scale projects should do the same.
If you’re still not convinced, remember that commit log is frozen and read-only. If you commit a bug fix and 42 days later you realize it was a mistake, you can’t change the old commit log to say “oops”. However, if someone tracks some regression and finds that commit (via git blame
, for example), then the commit log does not represent the current amended situation. Now, if there is an issue linked from the commit log, it’s easy to follow it and possible find the reopened bug, along with further investigation result. This also helps if the commit message blames/credits a wrong person or refers/excludes a different product.
One monumental benefit of recording everything in the tracker: it is searchable by anyone, including (of course) the future version of you. Now go one step further and mandate that the link to the issue is mentioned in the commit log. A tracking system usually has some sort of hooks so that it can automatically even link back to the commit or do other related activites (closing the bug upon a certain keyword), if the commit log mentions the issue.
This cross referencing is extremely time-saving in the long run. One day you will decide to run git blame, find the culprit check in, and thus can easily track the real issue. Perhaps even the other way around, a new bug is reopened and you can trace back the original changes related to the bug. On the DRY front, such a practice centralizes all the info related to future plan, defects, known problems, etc in the most logical place: the issue tracker itself.
Last but not least, issues aggregated based on the targeted version can easily serve as your mission center, a quick overview of the status and the plan. For example, Esprima has this wonderful grid view which shows its status with regards to the next release, a kind of a project dashboard.
semi-esoteric code names
Why? Mostly because it is fun and it gives a sense of personality. Your software is not just a series of ones and zeros packaged in a nicely presented user interface, it actually has a lot of stories, dramas, and tragedies behind it. After all, I’d like to refer the capital of my country with its name, Jakarta, rather than 6°12′S 106°48′E.
Look at how some browers are named (exploration theme): Navigator, Explorer, Konqueror, Safari. Perhaps you also see the connection in Android release names like Eclair, Froyo, and Gingerbread (beside the fact that they are tasty)? Are you aware that Maemo versions (Chinook, Diablo, Fremantle, and Harmattan) are named after winds, possibly a way for Nokia to indicate “the wind of change”? For some reasons, Mozilla JavaScript engine has a lot to do with a specific primate: SpiderMonkey, TraceMonkey, IonMonkey. Ubuntu is well-known for its funky codenames like Natty Narwhal and Maverick Meerkat.
For PhantomJS I pick up the name of specific flower related to the season of the release: Cherry Blossom, Birds of Paradise, Water Lily, Glory of the Snow. There is a whole wiki page on the story behind the names, if you care.
Any other uncommon best practices for small-scale software you always practice?