Table of Contents
Introduction
What is technical debt? Technical debt is code written for one sole purpose: to work. It doesn’t need to be beautifully formatted, readable code. You might be thinking “why would you ever want to write ‘bad code’?” The simple answer is that you are trying to reach a deadline. You have a limited amount of time, and need to get a feature out.
I used to hate creating technical debt. My boss would tell me that he needed me to fix something ASAP for a demo he has. I would tell him that it will take a while, and he responds with: “Make it work. Copy and paste, just get me something I can demo.” I used to hate it. Then I realized that sometimes it is necessary.
A really common example for me is UI changes. We are constantly changing our UI - it is just what happens when you are following an iterative design model. You try something to see if you like it. I used to get a little upset that I would code up an awesome feature, only to be told that it sucked and needed to be changed. It isn’t that what I coded sucked, and it wasn’t that the requirement sucked. It is just very difficult to judge the user experience when you are looking at a mockup done in Keynote. If it will only take somebody a day or two to get a 100% working prototype, it might just be worth it to do.
It has gotten to the point now that when something needs to be done quickly, I just do it. I will always try to follow basic SENG principles as best as I can, but I am definitely comfortable throwing them out the window, getting some coffee, and just pressing keys on my keyboard.
This is a collection of a few of my experiences creating technical debt. I am writing it half because one of my courses requires it, and half out of interest. Hopefully you enjoy reading them; maybe they will even inspire you to write some technical debt.
Sublime Text
Before I get to the stories, I thought I would talk about Sublime Text. When you start using Sublime, it just feels like any other editor, except it has an awesome default theme. But as you use it more, and learn the features, it becomes more than just an editor. It becomes….sublime. I thought that I would share a few of the keyboard short-cuts that I most commonly use in Sublime, incase you didn’t know them already. Since I use OSX, I will write the commands using the command key (cmd).
Find Across All Files (cmd+shift+f)
This command is pretty straight forward. Hit cmd+shift+f, and enter a string. It will pop open a new tab with search results. If you click a line in the search results, it will open that file, on that line. If you want to get really fancy, you can use regular expressions in your searches. I don’t use them that often, but I almost always search by file type & location:
Multiple Selection (cmd+d)
One of the first things people seem to mention when talking about Sublime is its ability to create multiple cursors. Just hold down cmd, and click anywhere to create a new cursor. This is especially useful if you want to say…indent everything after a comma. But something that works even better (in most situations), is cmd+d. If you highlight a string and hit cmd+d, it will select the next occurrence of that string. Hold it down, and you will see it select all occurrences. But be careful, it may not be case sensitive (to make it case sensitive, press cmd+shift+f, and hit the Aa button).
Duplicate (cmd+shift+d)
If you select a string, cmd+shift+d will append a copy of that string right after the selection. If you have nothing selected, it will duplicate the whole line.
Move Line (cmd+ctrl+up/down)
I wasn’t very sold on this one at first. But I tell you - combine it with duplicating a line (cmd+shift+d), and you can do some seriously fast copying. You don’t even need to copy and paste!
Open File (cmd+t)
A dropdown will appear, with files in it. Start typing, and it will intelligently filter your results. Once you find the file you want, you can enter a hashtag (#), even if the filename isn’t complete, and then you can search for methods or variables.
Geenie Experiment
This project was for the course that inspired me to write this article. The goal was simple: emulate (very roughly) the Google App Engine on the academic platform Genie Cloud. To be more specific I would write the client/server interaction that distributes jobs across various nodes all over the world. The reason I started this project, was to help my friend with his masters research. He had to present his work in less than a month, so I started immediately.
I love CoffeeScript and node.js. Right from the get-go I knew that I was using these technologies. As anyone who has used node.js will tell you, it is an amazingly simple framework for getting a server up and running. Here is a high level overview of my project:
- You have a master server, and many client servers
- Send the master job requests (for example a python, or JavaScript file to run)
- The master will send job requests to the clients, trying to balance across the many clients
- If all clients are full, use an overflow queue to hold the jobs
- Save the output of the ran jobs
Libraries
I used the node.js module Express to setup my server, and used Needle to send the requests between nodes. On top of these two libraries, I also used Underscore.js and Async.js. These libraries all make your life so much easier if you are trying to write code fast, and with the exception of Needle, I had used them all previously.
What Worked?
There were a few key parts that ensured I reached my deliverable in time. We felt the easiest solution would be to use a simple HTTP server. Although there are great libraries for working with sockets, we thought it would be safer to just use HTTP.
The first step was to design the communication system. How would the clients and master communicate with one another, and how would the user interact with the master? It is very easy to create a communication system that is a jumbled mess. To avoid this, we carefully drew out diagrams that illustrated how nodes would talk to one another. The important part was defining the functionality that we needed. Once we had that, we drew out the message types that we needed to send over HTTP.
Another key part was assuming that things would just work perfectly. I did not have time to design a bomb proof system. Since this was just a prototype, that was an acceptable assumption. The way that I kept the server and clients up to date was just to keep a snapshot of each client on the server. If a client crashed, the server would need to be restarted as well, which means that all the other clients would need to be restarted. #technicalDebt
The final thing I would like to talk about is how I used modular code. You might be the type of person who writes all of your code in one file; not me. I like modular, object oriented code. For this project I kept the client and server almost completely separate. Even though there was some overlap, I was afraid that I would run into issues if I was trying to share too much code. I was that since I was coding so fast, that I might accidentally change some code in one place that breaks the application in another place.
In the end the application worked pretty well. It was definitely just a prototype, but it served its purpose, and was a great learning experience.
Concentric 2012
One day I was talking with my friend Griffin, and he mentioned that the UVIC game-dev club was hosting a gamejam on the weekend. At that point, I had never even heard of a game jam/hackathon. It sounded interesting, but I didn’t think it was for me. After a fair bit of discussion, he talked me into it. Going into the gamejam, neither of us know what to expect. Here is what we did know:
- We had 48 hours to make a game
- We would get the theme about an hour before it started
- We were going to use C# and XNA to make a Windows game
- We were likely going to make a 2D platformer
The theme of this game jam was accretion, which means “growth or increase by the gradual accumulation of additional layers or matter.” It wasn’t immediately obvious how we could make a platformer centred around accretion. Our game plan was to just start coding a basic platformer engine, and then figure out how to work the theme in later. The first step was to draw a circle (the player), and squares (tiles for the map) to the screen, which is very easy using XNA.
Then we ran into a problem that would haunt us for the rest of the game jam - collision detection. The thought never occurred to us to use a physics library to handle the collision detection, we just wanted to brute force hand code it…Big mistake.
At this point we were using square tiles for our map, and a circle for our character. Circle-square collision? That will be easy - that is what we thought. It actually is very easy to determine if a circle collides with a square. The problem was that we had several square tiles lined up. If the circle hit the corner of a square, the ball would not obey the laws of physics as it bounced off. But, if the ball hit the corner between two tiles, it would fly across the screen, and its position would approach (infinity, infinity). We probably spent more than half of the game jam working on collision detection.
On the second day, we figured out how we were going to work the theme into our game. You will roll through the level, and collect items. For each item you collect, you would grow. The “fun” part, was that the level would stay the same size. If you got too big, you couldn’t fit through gaps to get to the end of the level. It was a balance of getting points, while staying small enough that you could actually reach the goal.
Needless to say, our game sucked. In the end, the only thing that worked was our automatic map generation. We figured out how to automatically generate maps, and put items in places so that you could usually reach them. It was a really fun experience, but ended up being a lot more difficult than I expected. I didn’t really have any concept of “production level code” at this time, so the code I wrote was pretty gross.
Hacklandia
It was less than a year between my first gamejam, and this next one. In this year, my skill as a programmer improved exponentially thanks to my new job where I worked with people (instead of as an independent contractor.) This second gamejam was brought to my attention by one of my professors, Dr. Yvonne Coady. It was a gamejam sponsored by Microsoft, where we had a weekend to make a game for the Xbox Kinect.
From the get-go it was a pretty sweet deal. Just for attending, you received a free pass to Rifflandia (a local music festival). The winners also received a very generous package from Microsoft. More important than the material prizes was the exposure to Microsoft. They were going to see my work, I really wanted to win this one.
There were spots for 15 teams of up to 4 people. I immediately signed up, and then started thinking about a team. I knew right away that I wanted Griffin on my team. Together we decided to invite our friends Cory and Dan. None of us had ever worked with the Kinect before, but we were all familiar with C#. We met up later that week to make a game plan. This is what we came up with:
- Use C# and XNA
- Use a physics library - Box2D
- Make sure our roles were clear
- Code as carefully as possible on Friday, because we knew things were going to start getting dirty on Saturday
- If we got stuck on something, move on!!
As for our game, we came up with an idea pretty quickly. It was inspired by Multitask. We wanted people doing different things, with different parts of their bodies at the same time (think of patting your head while rubbing your tummy.) We liked this idea because it had the following properties:
- Fun
- 0 learning curve
- Easy to adjust the difficulty - just add more minigames!
Team - check. Idea - check. Coffee - check. Here is how the weekend went.
On Friday we met at the Rifflandia HQ to get the run down from Microsoft. After this, we started programming. Due to some compatibility issues, I could not work with XNA, so I was officially on Kinect API duty. This turned out to be a good thing, because I could just focus on learning how to communicate with the Kinect. We think that this is one of the reasons we did so well. The other guys would just tell me what they need: “Paul, I need you to make a method to determine the angle between the player’s torso and their extended left arm.” While I was creating the back end, Dan started creating a Minigame Interface, so that we could easily plug different minigames into the larger game. Griffin joined us halfway through the day - he was at work - and immediately started making games! Cory’s computer was broken. His time was split between fixing his computer and helping whoever was having problems.
Friday went much better than expected. The backend Kinect API was pretty good, and we had a few minigames. We could actually play our game. After the 12 hour push we went to a lounge, had a drink, and then went home to sleep.
Saturday we met at the University of Victoria, bright and early, to start programming. We had one game plan for the day… games games games games games. I would continue shipping out Kinect functionality when people needed it, but I would also pair-program to help out with games.
Our plan of coding cleanly on Friday sure payed off. As we expected, we started to really embrace the hackathon-spirit on Saturday. There was no time to do things properly, if something didn’t work, make it work. The amount of copy and pasted code was incredible, especially on the Kinect side. What is that? You need a vector for right arm AND left arm? I could make a method that calculates either, but I would so rather just copy and paste the 50 lines.
At the end of day Saturday, our minigame count was up to 10. We also had a functional menu to choose your difficulty, instructions for each minigame, and the game restarted when you died. Griffin and I finally decided to call it quits around 2 AM.
We. Were. Stoked. Our game was awesome. We were blown away with how well we did! Then Sunday happened.
Oh god Sunday - why?! Everything went so well on the weekend. On Sunday everything fell apart.
We met up at my parent’s house at 10 AM on Sunday, and had to be at the festival by noon to present. We booted up the game to show my parents, and everything broke. Our game didn’t work at all. We lost the competition. After all the hard work we put in, we had nothing to show. Thankfully it was a hackathon, nobody was going to look at our code. We had to make it work!
Cory and I told Dan and Griffin to sit back; we were going to hack any remaining life out of this game.
The first big problem was that our games which used the voice recognition weren’t working well. We figured that if we tried them at the festival, with loud music and people talking, they wouldn’t work at all. Voice recognition got cut.
The next problem wasn’t as easy to fix. Our game didn’t work. I don’t remember exactly what didn’t work, but we did some pretty heavy debugging in Visual Studio, and finally Cory figured out the source of the error had something to do with a static variable in our main Game class. Cory saved the weekend.
We hitched a ride to the festival from my mom, and after a good luck hug, we were off to the races.
I had planned a rough presentation in the morning, so I did the majority of the talking for the presentation. And we killed it. Our game worked perfectly, and the presentation went very smoothly.
In the end of the day our game, which we called Corgi, won us first prize. We were offered job interviews, and won some sweet prizes. The hard part of the weekend was over! Now for the fun part. Getting soaking wet in the rain with thousands of people and listening to music.
Concentric 2013
Another gamejam, another weekend with Griffin. It marked the one year anniversary since our first gamejam. It was hosted by the UVIC game-dev club again, so there were many familiar faces.
I suggested we carry the corgi ‘theme’ from the last gamejam. It was decided - we were going to make a card game with corgies. The actual gamejam theme was castles and wizards, once again we decided to just ignore the theme for now and work it in later.
We knew right from the get-go that we wanted our game to be networked. Our game would be nothing if we didnt make it so two players could play cards against each other. Griffin and I both had a fair bit of experience working with node.js, so we decided that would be our platform. Since we were using node.js for the back-end, we decided to use HTML5, JavaScript, and SASS for the front end. I was determined to use Coffeescript for whatever I did, since that is my bread and butter language as I said earlier. Griffin, however, wanted to write vanilla JavaScript (I am as confused as you are.) We thought that the best way to handle this language conflict was to just have Griffin write the back end, and have me write the front end.
We thought about using HTML Canvas for the front end, but I didn’t really see the point, since we would just be dragging cards around the screen. So we used Knockout to do our HTML templating. With Knockout, we used jQuery-UI to handle the dragging and dropping functionality.
Ahh, Coffeescript, HTML, SASS, and Knockout. This is familiar to me - I can work efficiently. We started programming at 6 PM on Friday, and right from the start we went our separate ways. Griffin coded the back end, and I coded the front end. All of our communication was done using sockets, Socket.io to be more specific. Most of our collaboration on Friday was figuring out the communication scheme between the server and client. As I mentioned previously, this is very important to me, and it turned out to be equally as important to Griffin.
We took inspiration from other online cards games - Magic: The Gathering and Hearthstone. Although we looked to them for ideas, we wanted to make our game different. We wanted to do things such as:
- When you move your hand, show it moving on the opponents screen as well (blacked out of course)
- Drop cards from your hand onto the board
- Add stats to play monsters and spells
By the end of Friday, we had it in decent shape. You could drag cards around, and your opponent would see them move. But that is about all it did. We didn’t have any art, or any card mechanics. Definitely a decent start, but Saturday would be a big push.
On Saturday my goal was to make the game a little bit more functional. Add monsters & spells, card drawing & decks, and stats so you could play things. That wasn’t so hard thanks to Knockout. The hard part was hooking it up to the server. We realized now that we were a little sloppy on Friday. Our game wasn’t really set up to handle ‘multiple players’, so we spent a good part of the morning fixing that. Once that was done, we needed to refactor the way that hands worked. On the server, and client, we would store arrays that contained the cards in each players hand. It was difficult to keep the client up to date with which cards were yours, and which were your opponents. This consumed most of our Saturday afternoon and evening. Pretty good progress - we had a decent game.
When Sunday rolled around, we decided that priority #1 was getting some art. Griffin found a cute cartoon Corgi online, so we just abused that to no end. While he did that, I polished up the game, so that it was actually play-able. The final thing to do was add turns. We wanted the game to know whose turn it was, so the players didn’t have to manage that. What happens when you turn starts, or when you turn ends?
The general consensus was that our game was pretty good. It was apparently the first networked game that has ever come out of the UVIC game dev club. It was pretty decent, but it wasn’t good enough. I wanted to make it better.
Corgi Cards II
The game that we made in the gamejam was good for what it was - a game made in a weekend. But it was full of bugs, and the code was a mess.
Step 1
Delete all the code
Step 2
I wanted the game to look the same, I just wanted to change everything else. Since I had a prototype to mess around with, it was pretty easy to figure out what sort of client-server messages I needed. As usual, this is where I started. Our game supports multiple rooms, so I needed to make sure that any events stayed within the correct rooms. Socket.io makes this pretty easy, thanks to its rooms. Each “room” on the server, had a Socket.io room associated with it.
I started rewriting the back end in CoffeeScript, and heavily object-oriented it. I had four main classes:
- Player
- Card
- CardCollection
- Room
One of the harder decisions I had to make was how to store the cards. I decided that I would just store them in memory, in a JSON object for the time being. I feel like storing them in JSON (on disk), is probably the best solution for the long term.
The front-end structure was pretty much identical to the server, but since I was using Knockout, the front end code was very different. As a result, I once again kept the client and server completely separate.
The code rewrite went smoothly. It took me about a week. The reason that I think it went well was due to my careful planning. It helped that I had a very rough prototype from the weekend before. I could play the game, and see what I needed. The game itself turned out pretty good. It has been up stably for about a month. There are different rooms, so any number of games can be going on at the same time.
If you are interested in checking out the game, visit: Corgi Cards. There is a good chance if you are reading this down the line, the server will be down; but as of right now it is good to go.
Also, if you are interested in building a simple networked game using node.js and HTML5, you might find some value in checking out my GitHub repo and flipping through the code: Repo
The End
I thought I would just sum up some of the things i mentioned. Maybe they will help you down the road if you find your self in a situation to write code in a hurry :)
Know your roles
This is probably the most important thing if you are working in a team. When you are on a strict time limit, you do not have time to figure out what team members need to be doing. You need to be working as efficiently as possible, maximizing your work output.
Keep things separate
It is important to be modular, for a couple of reasons. First, it helps your team work efficiently if you have clear separations. Also, if something breaks, or you decide you don’t like something, it is easier to swap it out for a new version.
Move On
Easy. If time is of the essence, you don’t have time to get hung up on details. Just move on if you get stuck and come back to it later.
Use Libraries
There is no point reinventing the wheel. If somebody has already written a plugin to do what you need to do, use it. Chances are they have put a lot of thought into it, and it will work better than what you write in a limited time frame.
Use Version Control
This one is pretty straight forward. Not only is it a crucial skill to have if you are entering the job world, but if your code all of a sudden stops working, you can just revert to a previous version.
Thanks for reading, and Happy Hackathon-ing!