JavaZone 2010: What Clouds Are Out There and Which Do You Need?

Last month, I attended JavaZone 2010 (as I did last year). This year I presented a short lightning talk on cloud computing, giving a brief overview of what cloud services are available for software developers and what they can be used for.

Unfortunately, I can’t find the video stream online (I suspect there were some technical issues with the recording), but the presentation slides are available for download in English and Norwegian.

In my talk I discussed several different providers of cloud services, but since the slides don’t include any links, here’s a quick listing of the most important ones.

General cloud computing providers:

Two useful services for developers:

  • Assembla (Subversion/Git/Mercurial hosting, issue tracking, wiki and more)
  • JungleDisk (off-site backup, access to Amazon S3 account via network drive or web interface)

Other Presentations

My colleagues, Anders Bjørnestad and Thor Henning Hetland, also did two interesting presentations on the psychological aspects of introducing change and new technologies in an organization and how to reliably deliver important content with high availability using cloud services (Norwegian only):

  • Cloud Psychology – hvordan realisere smarte løsninger (slides, video)
  • HA-løsning anno 2010 (slides, video)
Share

JavaZone 2009: Utilizing Scripting in Real-World Applications

Last week I attended JavaZone 2009, where I was allowed to give a presentation on using the script engine interfaces defined in JSR 223 (Scripting for the Java Platform) to easily add scripting capabilities to Java applications.

For those of you who have no idea what that means, here’s the abstract:

By combining the power of compiled and interpreted languages in the same application, can we get the best of both worlds? Can embedding scripting capabilities in our applications help us develop software that is more flexible and more usable? Can we reduce development time by making volatile and highly fluctuating application logic customizable, dynamic and scriptable? Can we make life easier for ourselves as developers by choosing the right language for the right task at any given time?

This presentation gives an introduction to the concept of scripting engines and how they can be used to add scripting capabilities to real-world applications. We take a closer look at the Java scripting engine API (JSR 223) and popular implementations of the standard. The session includes practical examples and actual code.

Thanks to Tandberg and the JavaZone organizers, the presentation was recorded and is now available for online viewing (requires WMV codec/browser plug-in, I think).

Although the practical examples in the presentation are Java (combined with with JavaScript, Python and Ruby), the general principles of combining compiled and interpreted languages apply to other platforms and architectures as well (i.e. C, C++, C#/.NET and other scripting languages), so you may find it relevant even if you are not working in a Java environment.

As promised, I have also uploaded the presentation slides and example source code for your convenience. To run the examples you will need JRuby and Jython, and possibly the JSR 223 engines, depending on which versions of Jython and JRuby you have. (Jython 2.5.1 rc2 includes a working JSR 223 engine, JRuby 1.3.x doesn’t have it, but it looks like JRuby 1.4 will.) Also note that you have to edit the build-*.bat and run-*.bat files to reflect your environment if you want to use them for running and building the examples.

Share

The Mental Cork Board

A well-known technique for remembering arbitrary items through visual association is the method of loci (also known as “the journey method”):

[...] In this technique the subject memorizes the layout of some building, or the arrangement of shops on a street, or any geographical entity which is composed of a number of discrete loci. When desiring to remember a set of items the subject literally ‘walks’ through these loci and commits an item to each one by forming an image between the item and any distinguishing feature of that locus. Retrieval of items is achieved by ‘walking’ through the loci, allowing the latter to activate the desired items. [...]

Even though the journey method is useful for remembering potentially long, ordered lists, I never really found much practical use for it in my everyday life. It’s a fun party game, but I think it takes too much preparation time to be useful in “real life” (probably only because I haven’t practiced it enough, but never mind that).

“To Do” Lists, Ideas, Thoughts and Random Notes

The canonical example of stuff we need to remember on a day-to-day basis is, of course, the (in)famous “to do” list. The list typically consists of an unordered collection of unrelated items with one or more actions associated with them. (Yeah, I know some people like to prioritize their “to do” list, but that’s usually just a symptom of the fact that they have too many items on it to begin with.) Another trait of the “to do” list is that its contents are highly volatile, typically changing from day to day, or even through the course of a single day. Also, once an item on the list is completed, remembering it typically no longer serves any purpose.

If you are a creative person you most likely also have other things you would like to remember, such as ideas, insights, decisions, random notes and other potentially interesting thoughts that may pop into your head during the day (or night). Of course, when possible, immediately persisting your thoughts is the best thing to do, but if that’s not an option, remembering them until you can is a good second.

Mental Notes

Pins and Month (by francisteresa)

So, in order to remember everyday stuff like that, I came up with a very simple visualization technique I like to call “the mental cork board”. (I’m probably not the first person to come up with this technique, but I had never heard of it before, so I thought I would give it a try to see if it worked.) Here’s how it works:

In your mind, imagine an empty cork board hanging on a wall. As the board is initially empty, you can fill it up by pinning notes on to it, describing what you need to do or what you need to remember. For example, if you need to buy milk on your way home from work, imagine taking a physical paper note and writing down “buy milk” on it before you pin it up on the board. Need to fill gas on your car too? Write down “fill gas” on another note and stick it up there next to the first one. Now, as you drive off from work, you can easily recall the mental image of the cork board and read the notes that remind you to fill gas and buy milk on your way home.

If your visual memory is good (and if it isn’t, using this and similar techniques as exercises will hopefully improve it over time), you can add even more information to the notes by writing stuff on the back of them. Say that you needed to buy more than just milk in the grocery store. If so, you could write “buy groceries” on the note, then imagine flipping it around and writing out the shopping list on the back. Now, when you arrive at the store, simply imagine taking the note down from the board, flipping it around again and reading what’s written on the back.

Association with Physical Objects

If remembering text seems hard, don’t worry. You don’t have to limit the items to be paper notes or words. Why not hang other physical objects up there to remind you of whatever you need to do or remember? Say you need to deliver your car at the dealer’s for a service check. Just mentally hang your car keys on the board. Need to remember to pay a bill or post a letter? Pin it up there, and you will be reminded of it the next time you visualize the board in your mind. Need to remember a specific date, like someone’s birthday or an important event? Imagine a calendar hanging there and draw a red circle around the day. Need to buy oranges? Stick an orange up there. Whatever items will help you trigger the association and remember, put them up on the board.

Scaling Up

If you have a lot of stuff on your mind, the technique can also scale to include items of different topics. For example, you can keep separate mental boards for your personal and professional life or other projects you are involved in. When dealing with multiple boards it can be useful to distinguish them from each other by putting labels or signs above them, giving them different colors, or even putting them on different walls or in different rooms. Although it’s probably possible to extend this technique quite far, if you have so much stuff on your mind that you fill up more than three or four boards, I think it’s time to start writing things down…

Share

WinCue Blog Online

My WinCue project now has its very own blog:

http://blog.wincue.org/

… and I even updated it with some news!

Related links:

Share

Converting Bugs to User Stories

A question that often comes up when people start using Scrum for the first time is how to deal with bugs. One approach is to convert them into user stories and add them to the product backlog. This way the bug can be prioritized, estimated and planned like any other requirement, feature or change request.

An important property of user stories is that they are written from a user’s point of view. On a recent project I worked on, the quality assurance people took this quite literally, which gave us a good laugh when presented with the following user story during sprint planning for a student database system:

As [school] principal I want all expected transcripts to be printed every time I press the “Print Transcripts” button. Currently only two transcripts are printed, even though there are more students in the class. The system also stops responding after printing the first two.

I think this is a good example of how a bug can be successfully converted into a user story. After all, when presented like this, we simply had no choice but to make the system do as the principal wanted. I have found “bug stories” like these to be a valuable tool when explaining the concept of user stories to people who are new to story-based requirement specification. When treated like this, there really is no difference between a bug and a feature.

Estimating and Planning Bug Fixes

One of the most common objections people have to converting bugs into user stories and adding them to the sprint is that they see them as very difficult to estimate. To help with this, I often find it useful to split the story up into the following general tasks:

  1. Reproduce error
  2. Find error
  3. Fix error

Estimating will still be hard, but splitting it up makes it easier to assess, theorize and discuss each part of the problem and estimate an effort for each task—it’s a good application of the “divide and conquer” technique. Sometimes the first two or the last two tasks can be merged, i.e. finding the error assumes it’s either reproducible, detectable by reading code or otherwise discoverable by logical reasoning or other problem-solving techniques. Exactly which task split will be the most suitable can vary from time to time, but the concept of consciously dividing the process into smaller parts remains the same.

If the bug report contains a detailed description of how to reproduce the error, the first task can usually be estimated with good accuracy (assuming the described procedure does in fact reproduce the bug in the developer’s working environment). In some cases the steps required to fix the error is known in advance, in which case estimating the first two tasks can be trivial—if they are needed at all—and the third task may be possible to split up and detail even further.

Sometimes the team will have a theory about what portion of the code the error might be in, which can be helpful when estimating the second task. In many cases the developers will also have theories on how complicated the third task will be once the first two are completed (i.e. fixing the error is assumed trivial once the error is found, or the bug is suspected easy to find but hard to fix). Of course, these assumption may not be true, but the tasks and estimates are just guidelines anyway.

If you find it difficult to estimate each task in the bug story, one alternative is to simply decide how much time the team can or wants to spend on fixing this particular bug, and divide the time equally among the tasks. For example, if you decide you want to spend at most 12 hours1 to fix a bug, you could assign 4 hours to each task. Of course, you may still not be able to resolve the issue in 12 hours (or it could take considerably less), but at least now you can plan with it. If the bug is not solved in the assigned sprint, a new story can be created for a future sprint based on the current progress when the sprint ends. If nothing else, the work spent on the first sprint will hopefully make it easier to estimate the required effort for the next sprint.

Alternative Approaches

Converting bugs to user stories is not the only way to deal with bugs when doing Scrum (although I suspect some purists may argue it is). There are also two other popular alternatives that are worth mentioning:

  1. Allocate a certain number of days between sprints to do bug fixing.
  2. Allocate a certain number of hours/days in each sprint to do bug fixing.

Allocating time to work on bugs between sprints is often chosen because it allows good utilization of resources during team “downtime”. Sometimes some team members have other obligations to attend to outside of sprints, and this allows the remaining resources to be active while waiting for the team to get ready for the next iteration.

The second approach can be very effective for teams working on maintaining existing products with potentially large backlogs of bugs and unresolved issues while still developing new features during sprints. It’s also a good way to smoothly transition into an agile development cycle and keep the rest of the organization happy (i.e. support staff) until they are able to catch up with the new way of doing things.

For these approaches it’s not necessarily required to convert the bugs into stories or putting them in the product backlog. When doing bug fixing this way the team can work off a separate bug list—preferably also prioritized by the product owner—and pick new issues from the list as they complete old ones. There is no estimation involved and the work simply stops when the allocated time runs out.

Of course, there is nothing wrong with combining these approaches. For example, any unresolved issues at the end of the allocated time block can be converted into stories and added to a later sprint. Teams have also been known to do entire sprints dedicated to bug fixing, which I have been told has been very successful on many projects.

Notes:

  1. Naturally, this works just as well with story points instead of hours.
Share

Essential Developer Tools

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.

Share

Writing a Good Technical Résumé/CV

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:

  1. Personal details and contact information.
  2. Work experience (in reverse chronological order).
  3. Education and training (in reverse chronological order).
  4. 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:

Notes:

  1. 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.
  2. 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.
Share

Simulating Missing Language Features (with Cheap Tricks)

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.

Share

Please, Ask Stupid Questions

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.

Share

How I Got Started Programming

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.

Share