Friday, August 31, 2012
What do Programmers do?
As a Software Engineer, people are generally asking me to explain what I do at work. I myself wouldn't have been able to explain this a few years ago, and thought (correctly) that programmers are mega nerds. I'd always considered programmers as glorified typists. That being said, let me try to explain what things are really like, from my own perspective. While reading this try to keep in mind that this is all from my personal experience, though I have had the opportunity to work at both massive and tiny companies.
First: some context. I'm working at OkCupid Labs as a software engineer, and my position is heavily focused on backend work. We work on small(er) software projects with the goal of bringing people together. We're pretty much a startup.
Ok then! Let's start at a high level, then work our way down; software teams at software companies have programs or program features that we want to add to our applications, and as a software engineer I need to find out how to turn an idea into a functioning (piece of a) program and then write it up. I'll first go through and do some really high level design - is this feature technically feasible, and if so, what is a good way to structure the program and its data structures? I'll run through designs in my head, reaching back to stuff I learned in college and things I've picked up since then. I might doodle some stuff on some paper or a whiteboard to sketch out designs if they're more complex, or if I need to discuss them with someone else. I may even talk out loud to myself, or try to explain my ideas to an inanimate (1) object because having to explain things often brings out the obvious flaws/solutions. No matter how I do it, I'm aiming for an efficient and reliable design (2).
If all went well and I've filled my notebook/whiteboard/coworker's head with my brilliant, working designs, then its on to coding this beast up! I grab my favorite text editor and start writing code in whatever language my group has chosen. Its kind of like this, but more like writing an essay with proper structure and syntax in which you describe in very precise terms what the computer should do. Inevitably I'll make some mistakes in writing this essay - maybe this construct here didn't mean exactly what I meant, or maybe I just left a word (or whole sentence, or idea) out. These will come up later as bugs, which will hopefully be caught by me when I test the feature, but may end up harassing some poor user in the distant future if not found. Bugs are inevitable - they will always be in your code; all you can do is minimizes your chances of introducing them into the system and finding as many as you can and fixing them.
Something that is really important to mention about coding is that its a very creative exercise. It's not quite like writing a recipe so much as writing an essay or a poem. Just because the instructions to the computer must be precise and accurate doesn't mean there's only one way to do it. Code has a style to it which makes everyone's look a little bit different. Spacing, naming conventions and commenting in someone's code may make it look very different from someone else's, and yet it may do the same exact thing. You may find one person's style much more readable than another person's. Even outside of code style, there are nuances in a program that may make it slightly more or less efficient in terms of CPU cycles or memory. Its often easy to tell how good a coder is by looking through their code - sloppy, complicated designs are marks of a novice, while experts write code that most programmers will describe as elegant and simple. Less code is often better code.
While running through this design and implementation of a feature, I won't necessarily be working alone. I'll be talking to other engineers about how to hook my feature up with the rest of the code, asking their opinions and perhaps working with a partner on the design and coding of the feature. There may be meetings in which various phases of this process are discussed, and there will always be requirements (things that this program must do).
At the end of all this, I'll get to 'ship' my code, meaning that this code will either be put onto a website for people to use, put up for download, or physically shipped on a dvd or other physical media. Still, it doesn't stop there. Unlike school projects, no software project is ever truly finished - there's maintenance and improvement that needs to be done so long as the software is still in use. Maintenance means fixing bugs and making sure that the program still works given new technologies, while improvements might be adding more functionality to the program, or where you go back to fix some of the design mistakes that were made previously.
Though I haven't spoken about this very much, software development is a huge team effort. There are product people, designers, frontend engineers, testers, technical writers, managers etc. Everyone contributes to a system that won't function without all components working together. Each day we come in, work on a feature, fix some bugs, and discuss the future of the project. Its an incredibly stimulating job where you're always trying to solve some new problem - and, to me it's incredibly rewarding.
1) I hear rubber ducks work best.
2) Efficiency and reliability - what do these mean? Reliability is a bit easier to explain, and means that the software you build should work every time, no matter what buttons you mash, etc. If it doesn't work every time, then it should at least fail gracefully - no blue screens of death, please. Efficiency is a bit more of a challenge. Like most things, a computer has limited resources which include memory in the form of RAM, disk space, CPU cycles, network bandwidth. If you have an application that uses any of these poorly you end up with a program that doesn't operate at all, operates poorly on low-end systems, or operates but takes so long that it would take 80 years to compute a solution (check out generating the fibonacci numbers recursively - this algorithm grows at roughly O(2^n) meaning that each extra number you want to generate increases the amount of work needed exponentially).