Computer code is dense. It packs a lot of meaning into a small amount of text, and each character is necessary for the code to work. That's fine for machines, but our squishy human brains don't operate that way. Sentences that look like mathematical expressions may be incredibly efficient at conveying information, but they look like gobbledygook to most people.
As a coder, you need to write code that computers and people can read. Coders need to read their own code, or each other's code, all the time in order to maintain it. Code inevitably gets outdated and needs to work differently. New features come along. Whatever maintenance the code needs, good code is easy to change, even if you're not the person who originally wrote it.
Here's where learning to code can seem tricky. You need to learn how to write code that's efficient and readable:
- Efficient code is easy to modify.
- Readable code is easy for humans to understand.
As you learn how to code, writing efficient and readable code is a balancing act that every programmer learns with experience. This post shows several versions of an app I wrote. With each version, I explain how to code the app so that it's a little more efficient or a little easier to read.
How to spot inefficient code
The following code works just great: It fills the screen with the background image 'hills', plays the song 'farm', and stamps 9 pigs at equal intervals, making them look like they're stacked on top of each other. Each pig is placed at an x-coordinate of 400, y-coordinates that are 100 pixels apart, and sized 150 pixels wide. The tap handler tells a pig to dance when it's been tapped.
1 fill('hills')
2 song('farm')
3
4 stamp('pig',400,900,150).tap = dance
5 stamp('pig',400,800,150).tap = dance
6 stamp('pig',400,700,150).tap = dance
7 stamp('pig',400,600,150).tap = dance
8 stamp('pig',400,500,150).tap = dance
9 stamp('pig',400,400,150).tap = dance
10 stamp('pig',400,300,150).tap = dance
11 stamp('pig',400,200,150).tap = dance
12 stamp('pig',400,100,150).tap = dance
The problem with this program is that it isn't easy to change. For example, changing the program to stack 15 pigs instead of 9 would entail adding 6 more lines (one for each additional pig). Even more painfully, you'd have to change the numbers on each of the 9 existing pig-lines to fit all 15 pigs on the screen. Ugh.
How functions and variables make code efficient
So what makes code easy to change? A lack of repetition, for one thing. There's even a whole acronym for this principle:
DRY. Don't Repeat Yourself.
Good code makes ample use of things like variables and functions so that changes don't entail hours of haystack needle-hunting. The DRY principle also reduces bugs, and bugs are the worst.
Here's my code snippet again, with changes that make it more efficient:
1 fill('hills')
2 song('farm')
3
4 i = 9
5 function stack() {
6 stamp('pig',400,i * 100,150).tap = dance
7 i = i - 1
8 }
9
10 repeat(stack,9)
Here's how I changed the code to make it more efficient:
- Lines 1 and 2 are exactly the same as before.
- Line 4 is a new variable called i that represents the number of pigs I want.
- Lines 5 through 8 are a new function called stack that stamps a dancing pig on the screen, moving upward by 100 pixels with each new pig.
- Line 7 reduces the value of i by 1 every time the stack function runs.
- Line 10 tells the stack function to run exactly 9 times, so that the app stacks 9 pigs.
- Lines 3 and 9 are blank for the sake of readability, for the same reason you leave spaces between paragraphs in normal text.
This second version is only 10 lines long. Much more importantly, changing the code to stamp more (or fewer) pigs only requires you to change a total of 4 numbers (the number 9 on lines 4 and 10, and the 100 and 150 on line 6). This app is more efficient than my first version — but still not as efficient as I'd like.
Ideally, I should be able to enter a number of pigs once (instead of twice), and have the app do some math to figure out their size and spacing. That version looks like this:
1 fill('hills')
2 song('farm')
3 pigs = 9
4
5 i = pigs
6 function stack() {
7 stamp('pig',400,i*900/pigs,900/pigs*1.5).tap = dance
8 i = i - 1
9 }
10
11 repeat(stack,pigs)
Here's how I changed the code to make it more efficient:
- Line 3 is a new variable called pigs whose value is 9 - because I want 9 pigs, you see.
- Lines5 and 11 now both refer to the variable pigs, which means I now have to type my desired number of pigs only once, on line 3.
- Line 7 is a mess, but it works. To calculate the y (vertical) position of each pig, the function multiplies the current pig number (i) by 900 and divides the product by the value of pigs. To determine the size of each pig, the function divides 900 by the number of pigs and multiplies the quotient by 1.5. The 900 comes from the size of the screen; it's 1024 pixels tall, and I want the pigs to occupy 900 pixels of it. I figured out the other calculations with a combination of intuition and trial and error.
This third version of my Pig Dancers app is one line longer than the second version because I added a variable that makes it easier to change the number of pigs. That addition is good for both efficiency and readability. On the other hand, although line 7 (which stamps a dancing pig) makes the code more efficient, figuring out how line 7 works takes some real concentration. I can do better.
How one step per line makes code easy to read
Combining too many steps on a single line of code is like writing run-on sentences with lots of fancy words: seemingly efficient but utterly incomprehensible. To improve my app, I need to make a few changes that help humans read the code easily.
Here's what my efficient and readable version of the app looks like:
1 fill('hills')
2 song('farm')
3 pigs = 9
4 animal = 'pig'
5 spacing = 900/pigs
6 size = spacing * 1.5
7
8 i = pigs
9 function stack() {
10 y = i * spacing
11 stamp(animal,400,y,size).tap = dance
12 i = i - 1
13 }
14
15 repeat(stack,pigs)
Here's how I changed the code to make it more readable:
- Line 4 is a new variable called animal whose value is 'pig'. Adding this new variable makes it easy to change the image, if I want to.
- Line 5 is a new variable called spacing. Its value is calculated by dividing 900 by the value of pigs. If the app stamps 9 pigs, then the inter-pig spacing is 100 pixels. (I just wanted an excuse to write "inter-pig spacing.")
- Line 6 is a new variable called size. It multiplies the value of spacing by 1.5 to determine the size of each pig on the screen.
- Line 10 is a new variable called y, which specifies the location of each pig on-screen. To do this, the y variable multiplies the pig number (i) by the value of the spacing variable. The first pig (i = 9) is stamped at screen position x = 400, y = 900. The second pig (i = 8) is stamped at 400,800. And so on.
- Line 11 is now nice and tidy. It stamps the value of animal at the screen position 400, y and sizes the image width based on the value of the size variable. When the user taps an image, it dances.
This fourth version of Pig Dancers is longer than the first version by three lines. However, my fourth version has some important advantages:
- I can stack any number of pigs by changing one number, on line 3.
- Basic arithmetic calculates pig spacing and size based on the number of pigs.
- This fourth version clarifies how the spacing and size are calculated by breaking those values into separate variables.
When you're learning how to code, it's enough to write code that works. The most important thing is that everything functions the way it's supposed to. After that, you're ready to learn how to code efficiently and so that your code is easy to read. Doing one sometimes comes at the expense of the other — efficient code is sometimes harder to read, and readable code is often less efficient. Striking a balance between the two is the difference between writing code that works and writing code that's easy to work with. Your future self — and your future collaborators — will thank you.