Rudiments of Computer Science: Learning to Write Code Well

In the internships I've done at larger companies, and in the upper year Computer Science courses I've taken, I've noticed a disturbing trend: nobody can write code well. On one hand, it's a matter of practice and experience, but on the other, more grave hand, it's the effect of shyness and laziness, and an unwillingness to learn above what is taught in school or can be found by copying and pasting code from the web. Like any skill, it takes time and effort to develop. And while I certainly wasn't the best coder in my earlier years of school, and while I still have a tremendous amount to learn, there are some of the rudiments I wished had been taught to me years ago.

The compiler is smarter than you. Make friends with it.

This is not to say the computer is supreme and you, for one, should welcome your pedantic overlords, but you should accept its nature and work in harmony with it. Too often have I seen students slapping their computer, calling it stupid and wrong. You need to accept if the compiler is giving you errors, no matter how cryptic they may seem, it is correct and you are wrong. There is no shame in this, however, and petulance on your part will only slow you down.

So, when the compiler spews out an error message you don't understand, take this as an opportunity to learn something about how your language works. When you eventually track down the source of the error, you'll learn from the mistake, which will make you a better programmer, and you'll be far less likely to make the same mistake twice.

(Brief interlude about how to read compiler errors: If you're a particularly new programmer, you'll probably write all your code, save and then try to compile, resulting in what seems like a bazillion compile errors. Firstly, don't do this. Try to compile as often as possible, every time you finish some discrete unit of code, like a method. Secondly, and most importantly, when you get a ton of compile errors, it may seem daunting at first, but it's usually trivial to fix: start fixing the first error, save, re-compile, and keep going. You'll find by fixing the top ones first, most of the other errors disappear. Finally, if your compiler has an option to treat “Warnings as Errors”, you should enable this. Warnings are usually a sign you're doing something which may work. Programming fundamental: “*Could happen* should be treated as Will happen”, so you need to fix these warnings, too.)

Once you accept the compiler for what it is, your programming job becomes much simpler. Treat the compiler as a pedagogue and work with it. Remember, it's just a piece of software, it does not care how you feel.

Make effective use of Google and Documentation.

Taming the compiler is a great first step to writing better code, but eventually you'll master the syntax of your language and move into higher-level problems, where you'll need to use much more than just the basic syntax, instead using more features of the language and the libraries it provides. You need to learn this too. This means going beyond lecture slides and your textbook, and reaching up into the documentation provided by the language's vendor.

Most language installations come with some form of local documentation, in the form of Help documentation and usually Library references (I'll assume you're using an Object Oriented language, but the same applies to other language styles just as well). These documents provide references for all classes available to you as part of your language's standard libraries. Each class reference has written explanations of the Class, its purpose, and detailed descriptions of how to use each of its methods. If you're lucky, you'll also be provided with programming tutorials for certain problem domains (like “Collections Programming Guide”) and Sample Code for your perusal.

While so much documentation may at first seem overwhelming, in practice it's exactly what you need exactly when you need it. I don't recommend just opening up the help and reading every piece of documentation before you start, but I do recommend using a search engine and researching the classes you're using, so as to make the most of them, and to use them as they were designed. The Documentation is your best way to find out which methods are available for a class, which parameters they take, what they do, and what they return. If this documentation was provided with your language installation, chances are it's also available through Google.

Learning how to use your language libraries is going to make you a much better programmer.

Learn your environment.

I figured this one was a given, but I'm amazed time after time when programmers don't make the most of their compiler, code editor or IDE, and operating system. A startling number of programmers I know fear and loathe the command line, which paralyzes them from using some of the richer and helpful tools available to them.

(Brief interlude wherein I scold nerds for being afraid of their own computers: If you are a Computer Science student, or otherwise beginner programmer, you are expected to be at a certain level of comfort and proficiency with computers. This means you should know how to use a command line interface. You don't have to be an expert, but you shouldn't avoid it, either. You should be familiar with a Unixy system. OS X is a great one, and Linux works really well too. Your faculty's computer labs probably run Linux, so you have no excuse. But it goes deeper than just learning certain environments. I've encountered a large number of Computer Science students who seem to have a general fear of using computers, to the extent where menus aren't read, programs aren't understood, and Google isn't used. You didn't even try. This is how my non-nerd family treats computers. You need to do better.)

Integrated Development Environments, like Eclipse and Xcode are massive and overwhelming tools for the beginner. You'll probably start off writing your code in a basic text editor. I recommend moving to an IDE as soon as possible. They're big. They're scary. They're worth the pain. Once you become comfortable with your IDE, you'll be much more productive and learn quicker, as the IDE will provide things like Syntax Highlighting, Code Completion, and integrated and graphical debugging. These will help you find problems much more easily than had you been writing in Notepad.

IDEs are not the only way to write code, but they're an important one, and extremely useful. You won't regret learning how to use one.

Use source control.

Source Control is the most useful tool for your programming after your environment (if you're working in a good environment, source control is integrated), and the sad part is very few of my peers ever seem to use it, and schools rarely seem to teach it.

Source Control Management allows you to keep your code files in a managed way, so as you edit your files, you can make checkpoints or commits, and if you later botch your code, you can revert it back to a given checkpoint. It also allows you to create different copies of your code so you can change two separate pieces in safety net areas, without having them break each other.

Lets say you've got a project of files, and you're about to work on your next big task. Before you do any more work, you make sure you commit your changes. You can then create a separate branch of code to work on the next big task. As you're working on this task, you realize there was a bug in your previous task, so you can switch branches, fix the previous bug, and then resume working on your current task. When it's done, you merge the branches together, and now your code has both the old fix, and the newly completed task. Branches give your code an extra safety net so you can easily separate tasks.

SCM gives you other benefits, like having a backup of your code (as you can just go back to previous commits in your code if need be), and it allows you to keep your code on other machines. This also means you can collaborate with other coders, too. If you share a repository with other coders, each coder can push and pull commits from branches and repositories. This is great if you're working on group projects.

The real importance of Source Control, even for the solo programmer, is it gives you a safety net around your code. If you mess it up, you can always revert it and fix it.

There are many kinds of SCM tools available, but I'd recommend going with git. It's a little scary to use (but hopefully you're no longer afraid of using the command line, and you're not afraid to seek out answers, either), but it's also one of the most powerful. It's very popular, so there's a plethora of documentation and tutorials available on the web. There's also a little website called GitHub which hosts open source projects contained in git repositories. If you're looking for examples on how to code (or how not to code), learning to read open source software will take you a long way. And if you decide you'd like to practice writing code, contributing to open source software is an excellent exercise.

Learn how to debug.

Once you learn how to write code, read documentation and seek help, use your environment, and keep your code safe with source control, you'll need to learn how to properly debug your code as well.

Bugs are subtle mistakes in your code which can't be found with a compiler. You'll encounter them constantly, though hopefully not the same ones more than once.

Working with my peers, I'm again surprised at how few programmers know how to make the most of the debugging tools at their disposal. The extent of most debugging seems to end at print statements. And while printing and logging information to a console is helpful, if it's your only debugging tool, you're going to quickly find yourself bogged down.

Logging statements gunk up your code. They only reveal to you the state of whichever values you explicitly ask to be logged. They don't allow for conditional output. To really debug your app, you should learn how to use your IDE's graphical debugger and Breakpoints (of course, you could do this all from the command line, but I find graphical debuggers much nicer for visualizing the state of your app). You set breakpoints in your code, typically by clicking somewhere in your editor's gutter, and then Build + Debug your app.

When execution of your program code reaches the breakpoint's line, execution pauses and the debugger takes over. From here, you can now see the values of your objects and variables, which is incredibly helpful. You can also control the flow of your code, by telling the debugger to advance one line, or to jump in or out of a method. These primary functions are going to help you tremendously when fixing problems.

There are other helpful debugging features of breakpoints, like setting conditions for a breakpoint. You can make it so the debugger only kicks in if (x > 4) for example, which is helpful when a bug only happens under some condition.

Write an app.

Finally, and this one is simple: Practice! The best way to become a better programmer is to practice. Doing well on assignments is one thing, but it's not nearly as helpful as building your own app from start to finish. Or joining an Open Source project, finding your way around its codebase, and contributing to it.

These are all things I wish I'd known when I started programming. They are things which I've learned the hard way on my own, through painful mistakes. They are things I wish I could teach to all programming writing students, and they are things hopefully others can learn from.

Speed of Light