Game programming: A step outside the Ivory Tower – 6/17/14
Game programming: A step outside the Ivory Tower
By Benji Smith, sophomore, Northeastern University
For the past three weeks at MassDiGI’s Summer Innovation Program, I’ve had to do a lot of learning when it comes to programming. But I’ve also had to do a lot of unlearning, specifically some of the things I learned during my first year at college.
During that year, I learned about coding in a very academic fashion: functional programming, the correlations between computer science and mathematics, and other aspects of pure programming theory. I’ve had to unlearn them, but that’s not to say that these things didn’t have merit. In fact, many of the lessons I’ve learned in the classroom carry over to the real world perfectly. But there are some assumptions when doing academic programming, assumptions that you can’t make in other contexts. And it’s these expectations that I’ve had to reconcile with what really happens.
Before I continue, I’d like to say that I have nothing against academic programming, or those who do it. I think pure coding is a great starting point, and with it comes a certain beauty that comes from seeing the connections between subjects, connections that get blocked and dragged down by real world constraints. And as said before, there is plenty to be learned from a purer form of coding, it just can’t cover everything that needs to be learned in an actual coding team.
In my first year at college, we learned functional programming, first in Racket/Scheme and then in Java (Java isn’t functional, but we used it in a functional style). For those unaware, that is programming by merely defining functions. There is no concept of state or global variables, and the program just calls functions that call more functions, etc. Academics like this kind of programming because it makes programs easier to reason about. And it does have its uses, on a philosophical level. Code written in a functional style automatically becomes modularized and easy to test. Each part can be thought of as independent of the others, since there’s no global state to keep track of.
The problem though, is that functional programming is really bad for games. First off, the languages tend to be obscure: Scheme, OCaml, and Haskell don’t have as many fluent coders as C/C++, Java, Python, and C#. Secondly, as said before, pure functional programs don’t have any idea of state. Unfortunately, as my classmate Matt Kolosick put it, “Games are state-ful.” Whether it is graphics, physics, or AI, holding variables in memory is simpler, easier, and faster. Let’s say you wanted to repaint your room to be green. In standard imperative programming, you’d simply change the wall’s color to be green. In functional programming, you’d destroy your house, duplicate it, and then as you’re rebuilding your room, you paint it green instead of its original color.
When it comes to how to deal with incorrect use of one’s code, the academic and real philosophies split again. In all of my classes, we learned to make assumptions about what the user passed as arguments to our functions. If a function couldn’t handle negative numbers, then we were told to just assume we wouldn’t get any. It’s simpler to reason about, it’s easier to teach, and it (technically) runs faster. But it would never fly in the real world.
In the real world, your code will be tortured. It will be called on all sorts of arbitrary inputs, including on nothing at all (if the language supports null). This could be an accident: some other function didn’t properly handle things and returned incorrect values, or it could be a mistake: some programmer wrote 3.0 instead of 3.0f. In any case, they will happen, and it’s your responsibility to handle as many errors as you can, so they don’t propagate through to someone else’s function. Simply documenting a function’s contract isn’t enough, it needs to be in the code itself, and it needs to be easy to trace back to what happened.
Because of the different purposes for the final code, programming for academia allows for certain assumptions. Code doesn’t have to quite work, it doesn’t need to be extendable, and it doesn’t need to meet industry standards. There isn’t anything wrong with this, it’s just necessary to re-evaluate the assumptions you make when coding for a particular audience. Especially when that audience is subject to change.