WinCue Blog Online
April 30, 2009
Essential Developer Tools
March 9, 2009
After having Windows XP crash on me in an infinite loop of blue screens last week (I was running it with unsupported and outdated drivers, so I guess I had it coming), I had to spend the weekend installing Windows Vista and reinstalling all my basic software for everyday use. In order to remember what I actually did, and hopefully make the process easier the next time around, I wrote down a list of my Windows essential developer tools (not including plug-ins, drivers and other hardware-specific stuff):
-
Mozilla Firefox. This is usually the first thing I install after getting the network up and running. Not much to say here. It’s just something to get out of the way so I can move on with the rest of the installations.
-
JungleDisk. This is the second thing to be installed, mainly because that’s where I keep my backups and shared files. JungleDisk provides convenient access to files stored on Amazon Simple Storage Service (Amazon S3) via a mapped network drive.
-
WinRAR and DAEMON Tools (Lite). The easiest and simplest way to deal with compressed files and CD/DVD image files. WinRAR can handle pretty much any (useful) compressed file format out there and DAEMON Tools allows you to mount CD and DVD image files on a virtual drive. Together they can save you a lot of time, bandwidth and plastic discs.
-
Cygwin. I use this as my default shell environment and for running Bash, Python, Perl and Ruby scripts. If you do cross-platform development or want the power of the Unix/Linux shell, scripts and utilities on Windows, this is the way to go.
-
Komodo Edit. This happens to be my current favorite text editor for text, HTML and XML files as well as Python, Perl and Ruby scrips. It’s a bit heavy to start, but once it’s up and running I just keep it open.
-
TortoiseSVN and TortoiseCVS. I use these to access various Subversion and CVS repositories. The tortoise shell extensions make version control as easy as any other file operation in Windows Explorer. I prefer these over integrated revision control in other programs, because they give me better control and allow me to manipulate the repositories independently of any specific development environments. This is particularly useful when working on projects with multiple implementation languages or different development environments.
-
Python, Perl and Ruby. I usually run the Cygwin version of these, so they can be installed together with Cygwin, but since I tend to forget them the first time around, I put them here as a separate item.
-
LyX. This is a great software package for writing documentation and working with structured text documents in general. In their own words: “LyX combines the power and flexibility of TeX/LaTeX with the ease of use of a graphical interface.” The default Windows installer automatically downloads and installs MikTex, making it possible to work manually with TeX/LaTeX documents outside of LyX. I used to edit .tex files manually and process them on the command line, but after discovering LyX I rarely bother with that anymore.
-
Adobe Acrobat Reader and PDFCreator. These I use to read and generate PDF files. For those of you who don’t know PDFCreator, it’s a very useful printer driver that allows you to print your output to a PDF file from any Windows program. It’s a valuable tool for debugging printing or when you want to distribute or archive something electronically.
-
OpenOffice.org. I prefer this to Microsoft Office because it’s open source and the difference in functionality is hardly ever important to me. I mostly use it to read Word and Excel documents that other people send me, and for this it works very well. Sometimes I also use it to edit existing Word and Excel documents or export documents for others.
-
Eclipse and the latest JDK. Much can be said about Java IDEs, but I’m not going to. I simply use Eclipse because I like it and it works well for me (most of the time).
-
Microsoft Visual Studio and the latest Windows SDK. If you develop Windows software in C, C++, C# or Visual Basic, you know why you need this. If you don’t, you probably don’t need it either (although the text/code editor is really nice). Note that if you don’t require the added functionality of the complete versions of Visual Studio, you can download and use the Visual Studio Express Editions for free.
-
Skype and Windows Live Messenger. You may not think these are essential for a developer, but when working with distributed development teams, they actually are (at least to me).
It’s interesting to see that with the exception of JungleDisk, all programs on the list are either open source or free to download and use.
Writing a Good Technical Résumé/CV
February 12, 2009
From time to time people ask me to help them write a résumé for a job application or review their CV. I have also noticed the topic popping up elsewhere, so I decided to write down some of my general advice and recommendations for everyone to see (and discuss). These guidelines are intended for programmers, software developers, system architects, system administrators, technical support staff and other people applying for technical and engineering positions, but many of the ground rules are valid for any profession.1
The Anatomy of a Résumé
The main purpose of a résumé2 is to get you an interview. It’s fair to assume that your résumé will only be one in a large pile of applications, and that whoever is reading them is a busy person who’s time is limited and/or valuable. Therefore, it’s important to note that a potential employer wants to learn as much as possible about you, your skills and your experience by reading as little as possible.
With this in mind you should keep it short and to the point. Few people bother to read anything longer than three pages, and some may only read the first page or the first few paragraphs during the initial screening. Therefore, put the most important information first, and make your first page a memorable one. As we all know, you don’t get a second chance to make a first impression.
To help your readers easily locate the information they are looking for, I recommend following a traditional CV layout with a structure your reader is already familiar with:
- Personal details and contact information.
- Work experience (in reverse chronological order).
- Education and training (in reverse chronological order).
- Optional sections (order may wary).
While the sections in the fourth part may appear in any order, I do not recommend changing the order of the first three parts. These should appear in the order listed to make quick scanning as easy as possible. It also shows that you know how to set up a résumé properly, thereby implicitly indicating that you have a certain level of professionalism.
1. Personal Details and Contact Information
Maybe the most important part of a résumé is your personal details and contact information. It doesn’t matter if you have the best qualifications in the world if a potential employer doesn’t know who you are or how to get in touch with you.
I recommend always including the following on the first page:
-
Your full name and date of birth. If your have a foreign or uncommon name, or your name is commonly used by both men and women, including your gender may also bee a good idea.
-
Your home address. This is important to show your geographical location. If you are applying for a job in a different region or country than where you are currently living, providing some information about whether you will be locally available for an interview is also recommended. If you are staying on a temporary address while applying for jobs (i.e. while visiting abroad), also include the temporary address to show that you are locally available.
-
Your phone number and e-mail address. Obviously, you must provide this in order for a potential employer to contact you. If you are living in a different time zone and/or country from where the employer is located, it may also be a good idea to include some information about when you will be available via phone or when you will be replying to e-mails. This also applies if you are only available at certain times because of your current job or other factors. In general, you should only list phone numbers and e-mail addresses that you will be able to respond to immediately or within a short time frame. A potential employer trying to call you only to be met by an answering machine or an endless ringing may not bother to call back, so make yourself as available as possible.
-
Address of your homepage, blog or otherwise relevant web site. This should only be included if the site(s) contain information about you or your technical skills and experience that is relevant to the position(s) you are applying for. A good example of this would be a link to a software project you are participating in or a technical blog you are contributing to. Such sites can provide useful background information for an employer and is a good way to show your interest for projects outside of work.
Some people also like to include their marital status and number of children (when applicable) with their personal details. Some argue that including such information can be beneficial in helping the reader get an overall impression of you as a person (i.e. are you a family person or not), and it can be useful as a casual conversation topic during an interview, but not including it is not likely to affect your application negatively.
Often people ask if they should include a picture of themselves. Personally I don’t have any strong opinions on this, so feel free to do it if you want to. In some countries pictures are more common, but they are hardly ever required for technical positions.
Update: As several readers have pointed out, including your age, date of birth, gender, ethnicity, marital status, picture and other “trivia” is not recommended in many countries (including the EU), due to the employer’s possibility of rejecting the application in fear of discrimination lawsuits.
Quick Summary
Since résumés are typically scanned very fast, I recommend to include a short—one or to paragraphs–”snippet” about yourself at the top of the first page (after the basic personal information, contact details, etc.). If someone only reads the first few sentences of your résumé, this is your only chance to make a good first impression.
A good way to quickly give the reader an overview of your skills and qualification is to also summarize your areas of expertise and key domains with a few keywords on the first page. Again, this is your first impression for lazy and busy readers, so put “trigger” keywords here that will make people interested in reading more. For example:
Key areas:
programming, quality assurance, usability, networking (TCP/IP), enterprise systems, distributed applications, Scrum, security, databases (SQL), test-driven development, real-time graphics (2D/3D).
Don’t fall for the temptation to put a lot of buzzwords in this section. It’s not likely to impress anyone and you risk appearing to be trying too hard. It’s much better to use plain, regular words to describe your skills and areas of expertise. However, if you are responding to a job opening where experience with specific technologies or domains are required, you should list them (given that you have the required skills and experience, of course), even if they seem a bit “buzzy”. After all, if the employer listed them, they hopefully know what they mean and why they are important. Also, never include words or technical phrases if you are not absolutely confident you know what they mean. If something is on your résumé, be prepared to answer questions about it during an interview.
In conclusion, the first page is the most important page of your résumé. Ideally, this page should contain enough information to still make you an interesting candidate for the job, even when your cover letter and original application is lost (believe me, it happens) and somebody forgot to staple the pages together after printing, so only the first page makes it to the reviewers desk (yes, this also happens).
2. Work Experience
Work experience should be listed in reverse chronological order with the newest positions/projects appearing first. It’s also quite common to elaborate more on the most recent entries and provide less detail for older ones.
To make the list easy to scan, I recommend laying it out as a two-column table, listing the year in one column and position/project description in the other. For positions or projects lasting shorter than a year, list the year in the left column and provide a note about the duration in the right column. For anything lasting more than a year, provide a number range in the left column. To keep the list as simple as possible, you should avoid specifying dates in the left column. If anything needs further clarification or specification, write it as a part of the description in the right column.
An alternative to the two-column table layout is to write out each entry as a separate paragraph, with the paragraph heading containing year or year range (possibly with duration) and job title or project name.
How much detail should be provided with each entry in the work experience list is a hard to say in absolute terms, as this will depend on how much experience you have and how much there is to tell about each position or project. If you have many entries in your list (i.e. due to participation in many projects or extensive work experience over many years), you may have to shorten your descriptions to avoid making the résumé too long. If you lack experience, it’s fine to elaborate on whatever experience you do have, but avoid writing too much just to fill up the page. Again, the less is more principle applies, so chose your words carefully and keep it short and to the point.
It’s also a good idea to include keywords for your work experience. If you write a few sentences about each job position or project, also include some keywords about the languages, concepts and technologies used. Again, this is to make the list easier to scan for people who don’t have time to read it all or who are looking for specific “triggers”.
Example:
2006: Mad scientist assistant, Insanely Rich Man Inc., Secret Place.
Worked as an assistant for a mad scientist on a private research
project funded by an insanely rich man. Developed humanoid robots
to feed and play with his pet tigers while he was on vacation.
Project duration: 6 months
Keywords: Python, C++, Scrum, robotics, micro-controllers,
animal psychology.
3. Education
Your education should be listed in a similar way to the work experience, preferably with the same layout (i.e. a two-column table or separate paragraphs with accompanying headers).
If you have taken certifications or training courses after graduating from a university, college or other higher education, I recommend listing them separately in a section after your “traditional” education. There’s nothing wrong with interleaving the two, but separating them often make it easier to scan the page and quickly locating your formal eduction and your certifications independently of each other (i.e. an employer may not care whether you have a master or bachelor degree, but just wants to see if you have a given certification or have attended a certain training course).
4. Optional Sections
The final sections of the résumé do not follow the same strict rules as the ones describe above, and opinions on what to include and not include vary greatly. However, some sections are more common than others. One of the most common to include is a list of spoken and written languages. Some also like to include a listing of volunteer work they have done or organizational positions they hold or have held (i.e. coaching a junior soccer team or working Monday nights in a soup kitchen). This information may not be directly relevant to the position you are applying for, but it can provide an indication of commitment, social skills or leadership talent (even if the experience is informal).
Hobbies and Interests
I also recommend to list your hobbies and interests. They tell something about you as a person and it gives the interviewer a chance to “break the ice” and make you relax with some smalltalk. You might be surprised how often geeks (even geek bosses) share similar interests, also outside the domain of computers and natural sciences.
If you have participated in any hobby or open source software projects or published any articles or other manuscripts, I also recommend making a section describing those. This can be particularly beneficial if you lack formal work experience or formal education, as describing hobby projects or other relevant experience shows that you have an interest in your field and are eager to learn.
Skill Table
If you have experience in many programming languages or technologies, it might be useful to list them in a three-column table listing the language or technology, years of experience and your subjective experience level. For example:
Language Level Known since C++ Basic 2005 Perl Basic 2007 PHP Intermediate 2004 Java Advanced 2003
This gives the reader a quick overview of your experience levels and allows you to list many entries in a compact and clean way. The table can consist of any skill, technology or domain you want to emphasize and is of course not limited to programming languages.
References
Some people recommend listing references on your résumé. Personally, I don’t see any need for this, as references are usually not relevant until further down the line. It’s very unlikely that anyone would need to check your references before an initial interview, so I doubt anyone would require them on a résumé. That being said, having references on your résumé will never hurt. I can imagine some employers prefer it that way, as this may save them some time when looking up your references later (i.e. they don’t have to remember where they wrote down the names and phone numbers during the interview). Anything that will make life easier for the employer is likely to be seen as positive.
Even if you don’t list the actual references, it can be useful to indicate that references will be provided upon request, either on your résumé or in the cover letter. This way you show that you have someone who is willing to be your reference, which is always a plus. Also, make sure that if you do include include named references with contact details, that you have talked to them beforehand and that they are ready to be contacted by potential employers.
The Cover Letter
As the résumé is meant to get you an interview, the cover letter is meant to get your résumé read. If you are sending your résumé in response to an advertised job opening, always include a cover letter. Including a cover letter is also recommended when sending a general application or offering your services without anyone actually requesting them. In fact, I can’t think of a single situation where not including a cover letter would be a good idea. So, to summarize: always include a cover letter with your résumé.
The cover letter should contain information about why you are sending your résumé and what job you are applying for. Remember, the people receiving your letter are busy, so keep in mind that sending a long cover letter is almost a certain guarantee that it will not be read and your résumé ignored. I can’t think of a single reason why a cover letter would ever need to be longer than a few paragraphs, so keep your cover letter as short as possible.
For example, there is no reason to write about how talented you are or how eager you are to start working at your potential employer’s company. They already know you are interested in the job by the fact that you applied, and the résumé will show your skills and experience. That being said, the cover letter is a good place to put a few sentences about your current job/study situation and why you are applying. If you are sending a general résumé with your application, the cover letter can also be useful for highlighting skills and experience that is particularly relevant for the position you are applying to. In short, the cover letter itself should be the job application, while the résumé should be the document convincing your future employer that you are the right person for the job.
If you are in doubt whether you should include something in the résumé or put it in the cover letter, I would recommend putting it in the résumé. The main reason for this is the simple fact that whoever is reviewing your résumé may never see your cover letter. It’s quite common that the person doing the initial screening—to pick out which résumés should be considered for further review—is not the same person who will do the second screening, and there is no guarantee that your cover letter will be passed along to the next step (even if both steps are done by the same person).
A common example of this is when a middle manager performs the initial screening of potential candidates and distributes their résumés to other technical personnel for a more in-depth analysis of skills and experience. There is also a chance that your résumé will be considered for other positions than the one you applied to—either immediately or at a later time—in which case the initial cover letter may no longer be considered relevant.
Common Pitfalls
There are many common pitfalls to writing and sending out résumés and job applications. I won’t be able to cover them all in depth here, but here is a short summary of what you should do to avoid some of the major ones:
-
Check your spelling and grammar. It’s amazing how many people seem to neglect this. I have seen applications from higly educated and well experienced people who did not appear to care much about their spelling or grammar. You may be lucky and have your application read by someone who will not notice or who does not care, but that’s not a chance I recommend you take. Since finding your own errors can be quite hard, it’s usually a good idea to have someone read through both your résumé and cover letter before sending it.
-
Make it clear what position you are applying for. This is preferably done by writing something like “Application for <position>” or “Job application: <position>” in the subject of your e-mail. Again, it’s amazing how many people actually forget this. It’s quite common for companies to use the same e-mail address for many job openings, and the person reading the e-mail may very well not be qualified (or have the time) to guess which position you applied for, so make sure there is no doubt.
-
Check for copy/paste errors. Sending out multiple applications at the same time or using a previous application as a base for a new one is all good, but please, do remember to check that you send it to the correct address and provide the correct company name in the cover letter. Copy/paste errors are usually obvious to the receiver, and it sends a signal of sloppiness, which you are better to avoid.
-
Use a standard file format for your résumé. What is considered standard may vary, but usually PDF is the best choice. Word or HTML format may also be accepted, but if in doubt, use PDF. Sometimes the employer will specify which format they want the files in, in which case you should of course use whatever format they request. Don’t try to embed the résumé in your e-mail. It may look good on your screen, but you have no idea what it will look like for others. Also, it makes it harder to distribute the résumés separately.
-
Remember to include your résumé. It sounds stupid, I know, but it still happens, so make sure to double-check that attachment before hitting “send”. It doesn’t look good when you forget.
-
Do not send your cover letter as an attachment. When sending an application via e-mail there is no reason whatsoever why you should not make the cover letter a part of the e-mail. Sending an extra attachment just creates more work for the receiver, and thus reduces the chance of your letter ever being read.
Related links:
- Best Format for a Software Engineer’s Resume (Stack Overflow)
- The Art of the Developer Resume – Improving the Programmer Resume (Daniel Read)
- Getting Your Résumé Read (Joel Spolsky)
Notes:
- The recommendations are based on my own experience and preferences after reading hundreds of résumés over the years, and also writing a few of my own. Of course, I can’t guarantee that whoever is reading your résumé feels the same way as me, but judging from the feedback I have received on my own résumés and advice given to others, I feel safe saying that at least someone out there agrees with me.
- Note that I do not distinguish between a résumé and a curriculum vitae (CV). Some industries and academic institutions may have specific requirements for the layout and presentation of your résumé/CV, but if you are qualified to apply to either, you are probably already aware of this. Unless you are applying to a very conservative company or an academic position, the difference is not likely to matter, and the format described here is probably what you want.
Simulating Missing Language Features (with Cheap Tricks)
October 1, 2008
If you have ever implemented “real-world” application logic in an uncommon or less advanced programming languages, you may have had to deal with the fact that features you take for granted in other languages are not available. When I encounter such obstacles I am often fascinated by the challenge of trying to add the missing functionality to the language in one way or another. Sometimes I will implement the feature “properly”, but often I find it easier and more convenient just to simulate the behavior I want. Over the years I have been playing around with a fair share of odd programming environments, so here I present you with a collection of some cheap tricks I have used to overcome language limitations in the past.
Simulating Hash Maps with Arrays
These days, any “respectable” language has some kind of support for hash maps or associative arrays, either in the language itself or via standard libraries. In Java there is the Map interface and the HashMap implementation, in C++ there is std::map and std::hash_map, while in Perl, PHP and Python, associative containers are a part of the language itself. But what do you do if you want the convenience of easy access to key/value pairs in languages that don’t provide any such features?
Of course, you could always set aside a couple of days to implement a real hash map, but unless you are trying to impress your university professor or performance actually matters to you, it will probably just be a waste of time. Implementing one may also prove rather difficult if your language lacks other “essential” features, like data records, structures or object encapsulation (i.e. classes).
However, most languages support arrays, and as it turns out, we can easily simulate a mapping container using two arrays:
function findIndex(array, value):
for index from 0 to size of array-1:
if array[index] equals value:
return index
return -1 // value not found
function setMapValue(keyArray, valArray, key, value):
index = findIndex(keyArray, key)
if index equals -1
append key to keyArray
append value to valArray
else
valArray[index] = value
function getMapValue(keyArray, valArray, key):
index = findIndex(keyArray, key)
if index equals -1
return nothing // key not found
return valArray[index]
Using the two utility functions setMapValue() and getMapValue(), we can now store and retrieve key/value pairs from our (simulated) map:
setMapValue(keyArray, valArray, "sortValue", 15) setMapValue(keyArray, valArray, "refCount", 0) ... sortValue = getValue(keyArray, valArray, "sortValue") refCount = getMapValue(keyArray, valArray, "refCount")
It may look a bit dirty, but compared to “manually” manipulating array pairs spread around the code, I find this technique very useful when working in “less sophisticated” environments.
Simulating Arrays with Variables
Hash maps and associative containers are somewhat advanced data structures, so I don’t expect every home-grown programming language or proprietary third-party scripting engine to support them, but what about arrays? What if your language has no concept of a sequence of (related) values?
The answer is simple. Just simulate arrays using regular variables:
function setArrayValue(index, value)
if index equals 0
arrayVariable0 = value
return
if index equals 1
arrayVariable1 = value
return
if index equals 2
arrayVariable2 = value
return
function getArrayValue(index)
if index equals 0
return arrayVariable0
if index equals 1
return arrayVariable1
if index equals 2
return arrayVariable2
return nothing // index out of bounds
As the example illustrates, this technique requires a lot of typing and code duplication, and is therefore somewhat tedious to implement for large arrays. Also, your language may require variables to be defined before use, resulting in even more verbose code. Another disadvantage is that since the variable names are hard-coded, you need a separate function for each array and care must be taken to avoid name collisions between distinct arrays.
This may sound like a debugging nightmare waiting to happen, but it is also an excellent opportunity to utilize your favorite—hopefully more advanced—scripting language and write a simple source code generator, saving you all the trouble of extensive manual typing and hard-to-find copy/paste errors.
An interesting feature of these “manually implemented” arrays is that they will allow you to have arrays with holes in them, or arrays using arbitrary indices of your choosing. If your implementation language supports dynamic variable typing, you can even use this technique to simulate arrays of mixed data types.
Utilizing Dynamic Variable Names
If your language supports rune-time generation of variable names (often called dynamic variables or variable variables), the array implementation described above can be rewritten to something much simpler (variable variable syntax borrowed from PHP):
function setArrayValue(array, index, value)
variableName = array + index
${variableName} = value
function getArrayValue(array, index)
variableName = array + index
return ${variableName}
In fact, the same trick can also be used to simplify the “hash map” implementation as well, eliminating the need for two array parameters:
function setMapValue(array, key, value):
keyArray = array + "Key"
valArray = array + "Value"
index = findIndex(${keyArray}, key)
if index equals -1
append key to ${keyArray}
append value to ${valArray}
else
${valArray}[index] = value
function getMapValue(array, key):
keyArray = array + "Key"
valArray = array + "Value"
index = findIndex(${keyArray}, key)
if index equals -1
return nothing // key not found
return ${valArray}[index]
Note that dynamic variables are considered by many as one of the most dangerous features of (modern) scripting languages, so be careful not to shoot yourself in the foot. They remind me of the good old days of self-modifying assembly code: great fun for (obscure) hacks and very hard to debug when things go wrong.
Simulating Random Access to List Elements
Some languages support iteration over lists, but not direct access to elements via indices. If you want to “break the rules”, and index lists directly anyway, you can often achieve this with a custom function or macro—assuming the language provides you with a way to define those—like this:
function getValueByIndex(list, index)
i = 0
for each element in list
if i equals index
return i
return nothing // index out of bounds
Again, iterating over the entire list to find your element may seem a bit odd, but when your data set is small, or you don’t care about efficiency, this approach works surprisingly well.
Simulating Data Records with (Simulated) Hash Maps
Have you ever wanted composite data structures while working in a language that doesn’t support them? Well, I have, and I usually get my will anyway, one way or the other.
Using the map implementation from before, we can simulate a three-field Person record with ease:
setMapValue("person", "firstName", "Johnny")
setMapValue("person", "lastName", "Mnemonic")
setMapValue("person", "age", 37)
...
firstName = getMapValue("person", "firstName")
lastName = getMapValue("person", "lastName")
age = getMapValue("person", "age")
Also here we can use dynamic variable names to simulate more complex data structures, like an array of Person records:
function setPerson(array, index, firstName, lastName, age, occupation)
recordName = array + index
setMapValue(${recordName}, "firstName", firstName)
setMapValue(${recordName}, "lastName", lastName)
setMapValue($(recordName}, "occupation", occupation)
Unfortunately, unless your language supports multiple return values or pass-by-reference parameters, retrieving the data from the array will involve a bit more “manual labor”:
function printRecords(prefix, arraySize)
for index from 0 to arraySize-1
recordName = prefix + index
firstName = getMapValue(${recordName), "firstName")
lastName = getMapValue(${recordName), "lastName")
occupation = getMapValue(${recordName), "occupation")
print "Record #" + index
print "First name: " + firstName
print "Last name: " + lastName
print "Occupation: " + occupation
This may not be the best way to represent thousands of records from a collection of database tables, but if you only need to read a few fields from a configuration file or a convenient way to organize an internal data structure, this approach can make things just a bit more readable and maintainable—at least in situations where the alternative would be manually managing separate variables for each field in each record, which can be a real drag, both to implement and maintain.
Simulating Variables with …
No, really. You don’t want to do that.
Conclusion
Often when suggesting feature simulations like these to people struggling with language limitations, I get negative reactions. Their first response is usually something like “No, that’s ugly” or “No, we can’t do that. It will be too slow”. Sometimes these concerns are valid, but most of the time the assumptions are just wrong.
When it comes to ugliness, I will be the first to admit that tricks like these are simple and ugly, but as it turns out, they often get the job done, and if you are lucky, they may even make your code more readable and maintainable. As for speed concerns, if you are worried about speed you should not be using a language requiring hacks to support these features anyway. You would probably be better off chosing a different approach, preferably by using a “real” langauge. In fact, if you encounter problems like these, and struggle with language limitations, on a regular basis, chances are you are using the wrong language for your tasks.
Please, Ask Stupid Questions
September 3, 2008
Last week I read about Jeff Atwood having some database problems on his new site. Being a popular blogger, he soon had hundreds of comments, most of them telling him how elementary his problem was and how disappointed people were that someone of his skill and reputation did not know how to solve such a trivial task as avoiding database deadlocks. Luckily, one person was wise enough to provide a different view (quoting an earlier comment):
“It’s always a little disturbing to see a well-known coder ask a dumb question, but come on, database locks?”
Wrong. Dead wrong and incredibly dangerous. And egotistical. If I were interviewing you I would immediately flip the bozo bit and thank you for your time.
It’s impossible to know everything. The hallmark of a good programmer is not what they know but their ability to learn what they don’t. If you do not promote an environment where any question can be asked, no matter how naive and trivial, problems become intractable because people are too afraid to ask for help. Just because someone has been in the industry for a while doesn’t mean they know everything.
Chris on August 25, 2008 12:09 PM
As children, we ask “stupid” questions all the time, and (hopefully) nobody gets their head bitten off for doing so. We might laugh and smile, but after all, we expect children to ask about everything, as this is how they learn. But does this method of learning stop being valid once we grow up? I hope not.
I remember once sitting on a public city bus observing a small child asking her father if the buses were on teams. The father, somewhat baffled by the question, did not seem to know what to answer. After a pause of silence, his expression of surprise transformed to a smile, followed by a short “no”, while trying to hide his laughter. The question may have appeared silly to the father, but considering we were on a red bus and a yellow one had just passed us, it made perfect sense to me. Assuming the child was familiar with the tradition of sports teams wearing different colors, it seemed logical that she would infer this also to be valid for buses. The analogy of sports teams might seem strange applied to public transportation, but even though both the yellow and red buses were operated by the same company at the time, the green ones were not.
In my opinion, there are no stupid questions, only stupid answers. Never bite someone’s head off for asking a “stupid” question—it can be very destructive. In these situations I think it is best to follow the good advice of Marge Simpson’s mother. If you don’t have anything nice to say, don’t say anything at all. Belittling someone by lecturing them on how trivial their question is, or how what they are asking about is something they should already know, does not really help anyone. If you don’t want to or don’t have the time to help someone, tell them so, but don’t ridicule them for asking.
Also, if asked about something you think the person should be capable of finding out themselves, you don’t have to give a direct answer. Often I find it better to provide the person with some reference material or relevant search keywords. That way they can do their own research, and hopefully gain a better understanding of the subject than a quick explanation or a direct answer to their question would have given them. When people do make an effort to conduct their own research, you should also be more willing to answer specific questions that may come up while they are studying the topic.
Often, asking a “stupid” question can reveal holes or misconceptions in your mental representation of a problem or knowledge domain that would otherwise go undetected. I much prefer someone to be honest about their uncertainties, and ask a stupid question, than pretending to understand something they don’t. In many cases you may not even be aware of your own lack of understanding until you do ask that “stupid” question, which is what makes asking them so important in the first place.
That being said, there is a huge difference between asking about something because you are unsure if you understand it correctly, or something is unclear to you, and asking because you are simply too lazy to look up the answer yourself or think through the problem properly. Personally, I ask stupid questions all the time, although these days most of them can be answered by Google or Wikipedia. However, if you do indeed make an effort to find and answer and you are not successful, please, don’t be afraid of asking someone.
How I Got Started Programming
August 21, 2008
Browsing through programming blogs at wordpress.com I noticed an interesting post (inspired by a similar post at toxicsoftware.com) asking people how they got started programming. It turned out this has been going on for a while, with various people answering and passing the questions on to new people, and so on. Even if nobody actually asked me, I decided to answer anyway. I don’t know who started it, but I tracked down what most people seem to consider the original source, a blog post by Michael Eaton, and copied the questions from there.
1. How Old Were You When You Started Programming?
I am not exactly sure. My family got our first PC when I was nine (1989), but I can’t remember how long we had it before I started with programming. My guess would be I was about ten. Before then I had also experimented with some BASIC on the C64. I didn’t have one myself, but some of my friends did. We mostly copied the examples from the manuals and modified them, so I wasn’t really doing much programming on my own at that point. It was not until I had regular access to a PC that I started to do some “serious” programming.
2. How Did You Get Started in Programming?
I don’t remember exactly. I learned to use Norton Commander for editing batch files and hacking save games very early. Later I discovered GW-BASIC—and the manual that came bundled with our PC—which I used to write text adventure games. I think one of the main reasons I started with programming was because I enjoyed being able to control the computer and make it do what I wanted.
3. What Was Your First Language?
MS-DOS batch scripting and GW-BASIC. Batch files was my first introduction to variables, conditions and control structures, but GW-BASIC was what I eventually used for “real” programs.
4. What Was the First Real Program You Wrote?
Again, it’s hard for me to remember, since it’s so many years ago, but I do remember writing a rather long text adventure game that could be played with multiple outcomes and various ways to complete the game. Later on I also wrote more graphics-oriented games, usually cloning classics like Space Invaders, Pong and Snake.
5. What Languages Have You Used Since You Started Programming?
In no particular order: MS-DOS and 4DOS batch files, GW-BASIC, QuickBASIC, Turbo Basic, Commodore BASIC, Turbo/Borland Pascal, x86 assembly, M68k assembly, C64 assembly, C, C++, Delphi, Java, JavaScript, JSP, C#, Visual Basic, VBScript, ASP, Cg, HLSL, PHP, Python, Perl, Ruby, mIRC scripting, Bash scripting, Lua, BeanShell, TI-82 BASIC and TI-82 assembly, in addition to various template languages, a few scripting languages I wrote myself, and possibly some I don’t remember.
6. What Was Your First Professional Programming Gig?
I guess that depends on what is meant by “professional programming gig”. The first time I earned money from programming was when I won the 4k intro competition at The Gathering in 1997. I had won some other competitions earlier, but The Gathering was the first event where the prize was actually payed in cash.
I also did some programming and scripting while working as a computer technician for the City of Oslo’s school districts during the summer and fall of 1997, but I was not actually hired to do programming. My main job was building computers, setting up servers and cabling networks.
I would have to say the first professional gig was when I started working full-time as a game programmer in 1999.
7. If You Knew Then What You Know Now, Would You Have Started Programming?
I don’t know, but probably, yes. I never planned on becoming a programmer, it just happened. I don’t think I would have chosen differently, because I only did what I thought was fun and kept on doing it.
8. If There is One Thing You Learned Along the Way that You Would Tell New Developers, What Would It Be?
Programming is about solving problems. To be good at it you have to practice it, at lot. Try and fail, and when you fail, try again. Stay up-to-date with current technologies and always try to educate yourself by reading books, discussing problems with your peers and experimenting—a lot. Technologies always change and (good) programmers never stop learning.
9. What’s the Most Fun You’ve Ever Had … Programming?
Actually, I have so much fun programming that I already wrote an article about it.
The Programming “High”
August 12, 2008
I recently read an interesting blog post asking “what’s the most fun you’ve ever had… programming?” After thinking about it for a while, I realized I wasn’t able to answer. Not because I don’t have fun programming, but because I have so much fun programming, I can’t easily single out one project as the one I enjoyed the most. Of course, not every project is fun all the time, but I find programming to be great fun most of the time.
I think almost any project—be it programming or something else—can be fun if you want it to be. If you tell yourself “this project is going to be boring”, or “this task is boring”, chances are you will be bored. I have the most fun when I achieve something and when I learn something, and in almost any project you can accomplish at least one of the two. Most of the time you can get both. Even a seemingly trivial task, like creating a simple snake game, can be challenging if you want it to be.
When I was a teenager, I thought games and graphics was the most fun things to program, and I couldn’t understand how anyone could possibly enjoy themselves writing “boring” enterprise code in systems with no graphics at all. To me, real-time graphics and interactivity were essential requirements for a “fun project”. As I grew older and learned more about programming, I realized there was a vast landscape of challenges out there, and the opportunities for fun and learning was by no means limited to visual effects and interactive games. I discovered that writing a script parser in a high-level language or implementing a routing algorithm can be just as much fun as pipeline-optimizing rendering loops in assembly or programming an animation engine.
Flow
To me, an essential part of having fun while programming is being able to enter a state of flow. The more often I can work in flow, the more often I will have fun. The flow state can be very consuming—almost intoxicating—giving you a great feeling inside. I like to describe this feeling as the programming “high”. For me, the feeling is especially strong if I am learning new things and discovering new truths while working in flow. The point when I realize I have solved a problem or mastered a new skill can be very exciting and rewarding. When entering flow state as a group, i.e. in a meeting or brainstorming, the effect can be even more powerful, often giving a major productivity boost. If you are able to enter flow on a regular basis and create challenges for yourself while working, it doesn’t really matter what kind of project you are on, you will have fun anyway.
Personal Accomplishment
Another variety of the programming “high” is the feeling I get when I have achieved something. This is of course not unique to programming, but is common to many areas of life and is a basic human emotion. For me, this “high” comes in two types. One is the feeling I get when I have completed or accomplished something, like solving a complex problem or managed to get a date with a cute girl. The feeling is usually immediate and comes right after completing the task or event that triggers the emotion. The strength of the feeling is often directly related to the complexity or difficulty of the challenge. I can only imagine, but I guess this is also something like the feeling—in a very strong form, I am sure—athletes have when they win an event or break a record. The feeling is not based on any external feedback, and will mostly be determined by what the accomplished challenge means to you, personally, rather than how impressive someone else may think it is.
External Feedback
The other form is sometimes more subtle, but can be even stronger and more overwhelming when it first happens. This is the feeling I get when someone appreciates my work or gives me a compliment. This feeling can come long after the initial accomplishment, and it may even come as a response to something you did not consider a big accomplishment in the first place. It is triggered by external feedback and can be very strong, filling your body with an overwhelming rush. Again, I can only imagine, but I think this is how musicians, actors and performance artists may feel when they are on stage. It is also interesting to note that if the receiver does not think the feedback is justified or honest (i.e. the task for which you are complimented was trivial to you), the feeling may not trigger at all. I think this is one of the reasons why this feeling can be so strong when it does trigger, because it is not directly caused by yourself, like the first variety. However, when the feeling is genuine, it can boost your motivation and self-esteem for days.
Whether it’s working in flow, the rewards of personal accomplishment or feedback on your work that makes a project fun, it’s up to you to find ways to trigger those emotions as often as possible.
New Challenges
In a recent interview, Steve McConnell was asked what had been been his toughest challenge in the past. I don’t know McConnell personally, but having read some of his material, the answer did not surprise me:
I believe that if you’re not struggling, you’re not growing. And if you’re not growing you’re probably decaying or dying. So my life has been characterized more by “the challenge of the month” than by any one toughest challenge.
To me, this is as logical as Boolean algebra. If you constantly seek out new challenges, the recent ones will always be the most difficult you have encountered. If not, you are not evolving. And we should all be evolving, as professionals and as human beings. When you have challenge you have learning, when you have learning you have fun. If you have to think back a long time to find the “the most fun you have ever had”, you are probably not having fun on a regular basis.
Please share your thoughts.
Best Practices for Version Control
July 28, 2008
Source code version control systems have been around for decades, but sometimes I suspect people are using them just because everybody else is, or because their manager told them to do so, or because it’s company policy. Although most people will agree that using version control is a prerequisite for any serious software project, many programmers only utilize a small percentage of the possibilities and advantages such systems can provide.
Here are some of my thoughts on what I consider best practices for using version control systems. In short, they can be described with seven basic sentences:
- Put everything under version control.
- Create sandbox home folders.
- Use a common project structure and naming convention.
- Commit often and in logical chunks.
- Write meaningful commit messages.
- Do all file operations in the version control system.
- Set up change notifications.
These recommendations are based on my own experience and preferences with using CVS and Subversion over the years, but the principles should easily transfer to other systems as well.
1. Put Everything Under Version Control
Any files associated with any project you are working on that may be of interest to anyone else—or even only to yourself—should be put under version control. Note that this is not limited to source code and files related to the implementation of a project, but also includes documents such as meeting minutes, specifications, architecture and design documents, artwork, configuration files and install scripts. When doing research for a project and gathering information from external resources, I also like to add those to the repository. Some examples are product brochures, protocol specifications, book references and links to company web sites. E-mail correspondence, scans of whiteboard notes or a concept drawing on a napkin are also useful to store for later reference.
Although some people think it’s silly to archive files that never change in a version control system, I find great value in having every document related to a project stored in the same place. It makes finding things so much easier—which can save you a lot of time when you don’t have to dig through hundreds of e-mails to locate that specification you got six months ago but didn’t have time to start implementing until now. Also, in the area of software development, there is no such thing as a document that never changes (or at least, there shouldn’t be, because you always remember to update your documentation, right?). If you are working on a project where many documents are produced by non-technical or non-programming people (i.e. people who don’t use version control), consider setting up automatic synchronization between project file shares and the version control repository.
When documentation is kept in a wiki, things might be a bit different. If the wiki itself keeps track of changes—which any decent wiki will do—there may be no need to store this data in a separate system. If your wiki is backed by a database, you may consider putting the database itself under version control, but some people will view this as redundant (after all, you have automated backups of all your databases, right?). I don’t have any preferences on how this should be solved, as long as all documents related to a project is stored on a central server with associated revision history.
For document formats that require processing before being readable, such as DocBook, LyX and LaTeX files, I prefer also committing them in a more readable form, like PDF or HTML. Some may argue this violates the DRY principle, but it also makes the documents easier to read for people who don’t have the required processing tools installed (or who are just lazy). This can be very useful when distributing documents by linking to them directly in the repository (i.e. via HTTP), but do take care to update both versions when making changes to such files—or even better, automate it.
2. Create Sandbox Home Folders
To encourage developers to use the version control system also for their own documents, (experimental) projects and tools, I recommend creating home folders in the repository, giving each user a sandbox to play with. In my experience, many useful tools have started out as simple scripts in a developer’s home folder and evolved into powerful utilities over time, so why not keep the revision history from day one? This also allows less experienced developers to experiment with branching, tagging and merging, hopefully encouraging them to use those features in “real” projects as well.
3. Use a Common Project Structure and Naming Convention
I recommend a consistent naming convention for all files and folders in a project. Preferably, an effort should be made to maintain the convention between projects throughout the repository. This makes it easier to locate files by partially guessing their name or location. For example, finding the source code for a project with many sub-folders will be much easier if the folder containing source code is named src rather than something totally arbitrary.
Using a common project structure can also be valuable for automated tools. For example, if all projects have a readme.txt or readme.html in their root folder, one can easily implement a script to generate a web page with a brief description of each project in the repository. If you are using an automated build system, such as Apache Maven, some of this structure may already defined for you. Ideally, the project structure and naming policies should be described in your coding conventions or similar guidelines.
4. Commit Often and in Logical Chunks
It’s better to have a broken build in your working repository than a working build on your broken hard drive.
I prefer to follow the basic work cycle described in the Subversion book. This means that you should always update your working copy before doing any changes to files. In general it’s preferred to commit changes in logical chunks. Changes that belong together should be committed together, changes that don’t shouldn’t. This can make the resulting revision history significantly more useful on systems with atomic commits when changes span multiple files.
If you are doing many changes to a project at the same time, split them up into logical parts and commit them in multiple sessions. This makes it much easier to track the history of individual changes, which will save you a lot of time when trying to find and fix bugs later on. For example, if you are implementing feature A, B and C and fixing bug 1, 2 and 3, that should result in a total of at least six commits, one for each feature and one for each bug. If you are working on a big feature or doing extensive refactoring, consider splitting your work up into even smaller parts, and make a commit after each part is completed. Also, when implementing independent changes to multiple logical modules, commit changes to each module separately, even if they are part of a bigger change.
Ideally, you should never leave your office with uncommitted changes on your hard drive. If you are working on projects where changes will affect other people, consider using a branch to implement your changes and merge them back into the trunk when you are done. When committing changes to libraries or projects that other projects—and thus, other people—depend on, make sure you don’t break their builds by committing code that won’t compile. However, having code that doesn’t compile is not an excuse to avoid committing. Use branches instead.
5. Write Meaningful Commit Messages
If you have nothing to say about what you are committing, you have nothing to commit.
Always write a comment when committing something to the repository. Your comment should be brief and to the point, describing what was changed and possibly why. If you made several changes, write one line or sentence about each part. If you find yourself writing a very long list of changes, consider splitting your commit into smaller parts, as described earlier. Prefixing your comments with identifiers like Fix or Add is a good way of indicating what type of change you did. It also makes it easier to filter the content later, either visually, by a human reader, or automatically, by a program.
If you fixed a specific bug or implemented a specific change request, I also recommend to reference the bug or issue number in the commit message. Some tools may process this information and generate a link to the corresponding page in a bug tracking system or automatically update the issue based on the commit.
Here are some examples of good commit messages:
Changed paragraph separation from indentation to vertical space.
...
Fix: Extra image removed.
Fix: CSS patched to give better results when embedded in javadoc.
Add: A javadoc {@link} tag in the lyx, just to show it's possible.
...
- Moved third party projects to ext folder.
- Added lib folder for binary library files.
...
Fix: Fixed bug #1938.
Add: Implemented change request #39381.
Many developers are sloppy about commenting their changes, and some may feel that commit messages are not needed. Either they consider the changes trivial, or they argue that you can just inspect the revision history to see what was changed. However, the revision history only shows what was actually changed, not what the programmer intended to do, or why the change was made. This can be even more problematic when people don’t do fine-grained commits, but rather submit a week’s worth of changes to multiple modules in one large pile. With a fine-grained revision history, comments can be useful to distinguish trivial from non-trivial changes in the repository. In my opinion, if the changes you made are not important enough to comment on, they probably are not worth committing either.
6. Do All File Operations in the Version Control System
Whenever you need to copy, delete, move or rename files or folders in the repository, do so using the corresponding file operations in the version control system.1 If this is done only on the local file system, the history of those changes will be lost forever. I consider structural changes just as important as changes to the files themselves, so there is no reason why not to let the version control system keep track of them. Also, when people know all their changes can be undone, the threshold for doing radical restructuring and major refactoring will be lowered, which can have a significant impact on preventing the build-up of technical debt.
7. Set Up Change Notifications
To monitor changes in the repository as they happen, I recommend setting up change notifications to send out an e-mail or update an RSS feed whenever a commit is made. Some systems support notifications directly via event hooks—sometimes with default implementations provided—while others may require external cron jobs, daemons or custom scripts to provide this feature.
My recommendation is that all developers subscribe to change notifications, since they can have many advantages. Obviously, they are useful if you want to see what changes are being done to projects you are working on or have an interest in (i.e. a library your project is using), but they might also encourage—or scare—people into writing more useful commit messages, since they know someone might actually be reading them.
Typically the notifications will also contain extracts of the files that were changed, making them useful for light-weight code reviews. Programmers who monitor source code changes can keep an eye out for code smells or violations of the coding conventions, and if you are lucky, you might even learn something by reading other people’s code.
Here’s an example of what a commit notification e-mail can look like:
From: svn-commit@company.com
Sent: Wednesday, March 05, 2008 11:23 AM
To: svn-commit@company.com
Subject: [SVN:CompanyRepository] r6523 - trunk/documents/templates
Author: anders
Date: 2008-03-05 11:23:08 +0100 (Wed, 05 Mar 2008) New Revision: 6523
Modified:
trunk/documents/templates/document.lyx
Log:
Changed paragraph separation from indentation to vertical space.
Modified: trunk/documents/templates/document.lyx
===================================================================
--- trunk/documents/templates/document.lyx 2008-03-05 09:22:49 UTC (rev 6522)
+++ trunk/documents/templates/document.lyx 2008-03-05 10:23:08 UTC (rev 6523)
@@ -32,7 +32,7 @@
\footskip 1cm
\secnumdepth 3
\tocdepth 3
-\paragraph_separation indent
+\paragraph_separation skip
\defskip medskip
\quotes_language english
\papercolumns 1
If you are working on a large project or there are many active projects in your repository, you may find it useful to create separate notifications for each module or project. If notifications are sent via e-mail, you can also configure the subject field to indicate which module or repository the notification belongs to, making them possible to process with standard e-mail filtering rules.
Conclusion
If you are already doing all of the above, great for you! If not, adding even a few of these to your work habits can make a difference. Of course, not everyone is in a position to change the structure of their project or the repository configuration, but any programmer can make their life easier with logically grouped commits and meaningful commit messages. Consider giving it a try, you might like it.
Please share your thoughts.
Notes:
How Important Is Your Keyboard?
July 20, 2008
As a programmer I spend a significant amount of my time punching keys on a keyboard while writing code, and even documentation. Over the years I have also accumulated a wide variety of shortcut key combinations that I use for everyday tasks. Because of this, a keyboard’s layout and physical design is very important to me. In fact, I’m so dependent on a decent keyboard that I bring my own keyboard to work.
Although programming and writing in general is possible with almost any input device, I prefer my keyboards to have certain qualities:
-
It should have the standard 104/105 key layout. If the keyboard provides additional keys, they should not be located in places where any of the standard keys normally are. Manufacturers not following this simple rule is especially annoying for people like me, who use keyboard shortcuts from muscle memory without conscious effort. For example, I once had a keyboard with a “power off” button in the Pause/Break location. After accidentally shutting down Windows several times when trying to access the System Properties dialog (Win+Break), I removed the offending keys permanently.
-
The keys should be somewhat durable. I don’t require the stamina of a Model M, but the keys shouldn’t fall off during the first week either.
-
When the keys do fall off, they should be possible to put back on. This is useful for fixing stuck keys or cleaning the keyboard.
-
The keys should be fast and agile. When I press a key it should respond immediately, and when released it should pop right back into place. I’m not a fan of the “machine gun” sound of buckling springs, but the keys must feel “real”.
-
It must be able to keep up with my typing speed. I find this especially annoying with many RF-based wireless keyboards, as they don’t respond fast enough. As a minimum it should be able to cope with the typematic rate settings of shortest repeat delay and fastest repeat rate.
-
It should be as slim and minimalistic as possible. I’m not fond of extra stuff like embedded palm wrists and other “ergonomic improvements”. I want the keyboard to take up as little space on my desk as possible.
Of course, these are only my personal preferences. What works for me may not work for you, but if you are looking for a decent keyboard for programming or extensive writing, here are some of my recommendations:
- KeyTronic KT2001
- Das Keyboard (review on Sladshdot)
- Unicomp Customizer (based on the old IBM Model M) (review)
- Logitech Deluxe 250 and Logitech Internet 350
- Dell Multimedia Keyboard (also available as wireless Bluetooth kit with mouse and Bluetooth dongle)
- Logitech UltraX Premium
So, how important is your keyboard? Are you comfortable typing on anything from a Happy Hacking to a Microsoft Natural, or do you have some special preferences?