My heyday in programming was about five years ago, and I’ve really let my skills fade. I started finding myself making excuses for my lack of ability. I’d tackle harder ways to work around problems just so I wouldn’t have to code. Worst of all, I’d find myself shelving projects because I no longer enjoyed coding enough to do that portion. So I decided to put in the time and get back up to speed.
Normally, I’d get back into programming out of necessity. I’d go on a coding binge, read a lot of documentation, and cut and paste a lot of code. It works, but I’d end up with a really mixed understanding of what I did to get the working code. This time I wanted to structure my learning so I’d end up with a more, well, structured understanding.
However, there’s a problem. Programming books are universally boring. I own a really big pile of them, and that’s after I gave a bunch away. It’s not really the fault of the writer; it’s an awkward subject to teach. It usually starts off by torturing the reader with a chapter or two of painfully basic concepts with just enough arcana sprinkled in to massage a migraine into existence. Typically they also like to mention that the arcana will be demystified in another chapter. The next step is to make you play typist and transcribe a big block of code with new and interesting bits into an editor and run it. Presumably, the act of typing along leaves the reader with such a burning curiosity that the next seventeen pages of dry monologue about the thirteen lines of code are transformed into riveting prose within the reader’s mind. Maybe a structured understanding just isn’t worth it.
I wanted to find a new way to study programming. One where I could interact with the example code as I typed it. I wanted to end up with a full understanding before I pressed that run button for the first time, not after.
When I first read about literate programming , my very first instinct said: “nope, not doing that.” Donald Knuth, who is no small name in computing, proposes a new way of doing things in his Literate Programming . Rather than writing the code in the order the compiler likes to see it, write the code in the order you’d like to think about it along with a constant narrative about your thoughts while you’re developing it. The method by which he’d like people to achieve this feat is with the extensive use of macros. So, for example, a literate program would start with a section like this:
Herein lies my totally rad game in which a bird flaps to avoids pipes.The code is structured in this manner: <<*>>= <<included files> <<the objects and characters in my game>> <<the main loop>> @ This is the main loop, It contains the logic and state machine, but it also has a loop to update all the graphics within each object. <<the main loop>>+= <<the game logic> <<the graphics> @
In this example, you’d later write things like this.
In this next bit I am going to define the bird who flaps. To do this I will have to create an object. The object will contain the position of my bird, the state of its flapping wings, and the physics by which its perpetual descent is governed. <<the objects within my game>>+= <<flapping bird>>= class Flapping_Bird: <<initialize the bird>> @ The bird is initialized in the middle of the left side of the screen. As soon as the user grazes any key for the first time, the bird will begin to suffer. To enable this I will need to know what size window the bird inhabits, and with this information I will determine the scale of the bird and its initial location. <<initialize the bird>>+= __init__(self,screenx,screeny): etc..
Okay, this will take a bit of deciphering, and I probably didn’t nail the syntax. In simple terms, anything between a <<>> and a @ is actual code. If you see <<>>+= it means add this bit of code to the previous definition (which was defined by <<>>=. Well, Wikipedia explained it better.
That introduction aside, the concept that really stuck with me was the idea of writing down the thoughts in your head along with your code.
Ordinarily, I’d say this would be bad to put into practice. Your coworkers won’t really appreciate paragraphs of exposé between every line. The whole point of learning a programming language is to become fluent in it. The goal is, in my mind at least, to get to the point that you’ll be able to read code and logic flow like you’d read a book. (Along with a helpful spattering of comments to orient you.) Of course, I’m certainly not Donald Knuth, and I’m not even a very good programmer, so don’t take that as gospel.
Programming Should Be Enjoyable
Which gets me to the core of the article. It’s something I started doing soon after I read about literate programming, and it’s tripled how fast I learn programming. It’s also made it more fun.
I’ve been working through a great beginner book on pygame, Making Games with Python and Pygame by Al Weigart which is free online. Below is the very first example in the book, and it is presented in the standard way. The reader is expected to type the code into their text editor of choice and run the code. After the code performs as expected, the reader is then expected to go through a line by line dissection in order to figure out what each line did. This works, but I think it’s typically better at teaching someone to transcribe code, than to actually code code.
import pygame, sys from pygame.locals import * pygame.init() DISPLAYSURF = pygame.display.set_mode((400, 300)) pygame.display.set_caption('Hello World!') while True: # main game loop for event in pygame.event.get(): if event.type == QUIT: pygame.quit() sys.exit() pygame.display.update()
With my revelations from literate programming my code started to look like this:
#alright, we remember this. The compiler or interpreter or whatever gets mad if we don't import the functions and files we need first import pygame, sys #pygame is the game library I'm using, sys is full of useful system calls. I think I'm importing this one for the sys.exit() function later. I skipped ahead and read that this is similar to breaking from the loop or pressing ctrl-D. Maybe this is a cleaner way to exit a program and a bit more universal? I don't know but I don't want to get bogged down at this point, so I'll remember the question for later. from pygame.locals import * #I've already imported pygame, but I'd like to get the stuff inside pygame.locals out. The book mentions that this is mostly useful constants like the QUIT I'll be using later.
I would attempt to explain as much as I could about what each line was doing. It’s a bit tedious, but it helped me note the bits I remembered and figure out which parts I only thought I recognized.
pygame.init() #I should initialize pygame before I start using it. No complaints with that logic here. Apparently it will throw errors if I don't. ### Yep, tested it by moving pygame.init() down a few lines. It definitely throws errors.
One thing I realized was pretty fun, was to keep a log of my experiments in my code. Since python doesn’t really care, I’d just add more hashes to show when I’d gone back to try something out. Anyway, the rest is at the end of the article if you want to read the full content of my inane and perhaps incorrect comments.
While I’m still not sold on literate programming, and perhaps, am not at a level to be sold on it anyway. I definitely benefited from some of its core ideas.
Programming is one of those things that’s really hard to take notes on. I can’t imagine anything more useless than writing, “print(‘the thing you want to print’) – prints something to the console,” on a bit of lined notebook paper. What good will that do?
Programming is about experience, developing good thought patterns, and clearly understanding what the magic is doing. If you’ve been having trouble making programming stick for you, give this a try. Maybe it will help. Looking forward to thoughts in the comments. Any tricks you use for learning programming?
DISPLAYSURF = pygame.display.set_mode((400, 300)) #gosh I hate all caps, but I'm gonna trust that the book writer knows what he's up to. This is is the main "surface" on which everything will be drawn and defines the size of the game's window. Not entirely sure what a surface is yet in the context of pygame. ###played with it a bit, changed the window size, etc. It doesn't like it if the (x,y) of the screen isn't in a tuple pygame.display.set_caption('Butts') #change the title bar. I'm an a dolt Noting that this is all in the display bit of pygame. while True: # main game loop for event in pygame.event.get(): #this bit gets all the events that happened and cycles through them one by one until its done. I think each event might be an object, but I'm not sure. if event.type == QUIT: #The book mentioned that the event types are just numbers and I imported QUIT from pygame.locals earlier with the from statement. I could have left the from statement out and also gotten this with pygame.locals.QUIT ###yep, just for the heck of it I tested that and it worked. pygame.quit() #quit pygame first. This seems important. sys.exit() #quit out of the program second. pygame.display.update() #just going out on a limb here, but my guess is that this function updates that DISPLAYSURF I made earlier.