I was talking to my friend Tristan the other day, via the MUD which he has created and programmed himself. If you don’t know what a MUD (Multi User Dungeon) is, it’s a sort of a text based adventure world where you can interact with other people, and move between various rooms and locations, and interact with various objects. If you are about my age you probably remember those books in which you read a paragraph and then at the bottom it gives you a choice of “go to page 46” or “go to page 32” – at which point you secretly keep your finger in the original page just in case your choice of page 46 leads to you being eaten horribly by some kind of dragon. It’s a bit like World of Warcraft with no graphics, or an IRC client with dragons – take your pick.
I digress.
Near the start of this year, I had suggested that students have a go at creating their own text based adventure game as an early task in Python. I gave them this code as a template, and asked them to continue:
# Python adventure game # Define the direction variable direction1 = '' # Print out a statement setting the scene for the user print """As you step into the cave you can smell musty cobwebs and the dank odour of dripping water. At the back of the cave the path forks and you can see two directions to travel, left and right.""" # Keep doing this until they have entered either left or right while direction1 not in ["left","right"]: # Ask the user where they want to go direction1 = raw_input("Do you want to go left or right?: ") # Decide what happens if direction1 == "left": print "\nYou have entered the bear's lair!" print "Sadly all that is left of you is a pile of bones." elif direction1 == "right": print "\nThe back of this passage seems to lead somewhere..." else: print "That is not a direction"
I’m not afraid to admit, this was not one of my finer tasks because it doesn’t take a genius to figure out (but perhaps this did not occur to a sleep deprived teacher) that very quickly you are going to get in a huge muddle of where you are, which direction you can go in and which you can’t – let alone add in usable items and an inventory! Still, it was a nice practice of lots and lots of nested if statements…
I thought I’d ask Tristan how he would go about solving this problem – and his first response was that he’d use classes. Spanner in the works then, because I told him that we don’t seem to cover any Object Oriented programming at all at AS Level. His second idea was to use the dictionary construct in Python, which is different to the list construct which I usually use to teach arrays, because it allows you to use string keys. (Of course, if PHP were a supported language of the exam board, we wouldn’t have to bother with either we’d just use arrays *grumble* :D) This seemed like a pretty good idea, and we discussed how we would go about it, with the discussion coming to a close on his comment of
“well you do know this is the crappy way of doing it?”
This got me thinking…a lot of the time when we are teaching programming, we are actually teaching “the crappy way” of doing something – and not the way that a real life programmer would approach it. Sometimes this is because the crappy way of doing it is actually more understandable to the learner…a prime example of this which comes to mind is in PHP when you extract all items from an array (most commonly a query result) into variables with the key names. e.g.
$fruit = array("orange" => 1, "apple" => 2, "pear" => 1); extract($fruit); print $orange; // Output will be 1
I suspect that most experienced programmers would not use this much (and especially not on form data!) but often it’s easier to just suggest doing it to avoid the hassle of explaining how to use array keys and then getting a blank look. Even though you’ve covered arrays for approximately 4 weeks and done 10 past papers on it. I exaggerate.
So is this a bad thing? I remember being rather miffed in Science lessons when I was in school that we would be taught something in Year 7, and then the next year they would say “well that’s not completely true, it’s actually like this”…and so on. As much as I cringe a little bit inside every time I have to do it, I don’t think that teaching some things “the crappy way” is necessarily bad. I’m not saying that we should forget good habits like variable names, indentation, and algorithm efficiency – far from it – but as long as they are aware that there are other ways of achieving the same result, you are still teaching a method which works. It’s not the most efficient way, but it gives the students a starting point to work from rather than totally confusing them and making them feel like they’ll never be any good and might as well pack up now. That’s why we are teachers, that’s why we are here – to teach the foundations of the subject and to ignite an interest in programming, not to make a legion of perfect programmers. If they are interested enough to go and look up how things could be done more efficiently and properly, and tell you off for your terrible code – GREAT! Our work here is done. If not, at least their program worked. 🙂 At present I have one of my Lower 6th classes picking me up on EVERY piece of bad coding, poor variable naming, or general mistakes they possibly can, and I LOVE IT!!!
Oh and in case you’re wondering, here’s the foundations of the text adventure game, using the dictionary constructs in Python
# Python adventure game using dictionaries # Validate their input direction def input_direction(): direction = raw_input("Which direction do you want to go? ") while direction not in ["north", "south", "east", "west", "exit"]: direction = raw_input("Which direction do you want to go ") return direction # --------------------------------------------- # Set up the rooms compass = dict({ "north" : {0: 1, 1:2, 2:-1}, "south": {0: -1, 1:0, 2:1} }) descr = dict({0: "You are in a small lobby type room.", 1: "You are in a grand hall way", 2: "You are in a huge palace"}) currentRoom = 0 newDir = "" # Game loop while( currentRoom != -1 ): # Describe the current room print descr[currentRoom] # Ask what they want to do newDir = input_direction() # If they wish to exit if newDir == "exit": print "See ya later, alligator!" currentRoom = -1 else: # Otherwise look up whether there is a path that way if compass[newDir][currentRoom] != -1: currentRoom = compass[newDir][currentRoom] else: print "There is no path in that direction"
In case you are interested, a link to Tristan’s MUD
I think teaching things the “crappy” way as an introduction is okay, but *only* if you also teach them how to convert that into good code. This approach is often helpful to show the advantages of the better approach, how it reduces code size, eliminates defects, etc. Keep in mind that even in “professional” programming a lot of the good code just starts out as a cobbled-together idea that is refactored many times into a solid solution — you can’t always just jump to the good solution at the start.
Though do avoid teaching really bad things (like that extract example). Some idioms and functions are pretty much regarded as horrible by all developers and should be avoided.
I think that yes, the idea is difficult to grasp, but as a programming task it’s brilliant! I can see my year 10 kids who are struggling with thinking logically would get a kick out of this and would get to to plan things out before they start. What about proividing them with a fighting fantasy book to start with so they can see the idea and come up with different angles to the same solution.
I’m giving my lot 3 weeks to come up with something interesting.
I’m not even sure about ‘teach the crappy way and then show how to convert’. I think we should be teaching them by always showing them good, nay excellent, code. They probably won’t be able to reach that standard for a long time, but the examples should always be there.
We can then show them why what they’ve written is ‘crappy’ and how to improve it.
I’d like to think that the materials we give them are good (I don’t think we’d ever claim excellent), but that, in the heat of the moment when we are doing something on the board on-the-fly, we sometimes write crappy code, but we should always say it’s crappy and not try to hide it.
The problem is in defining what “crappy” code is. Code which is junk I’d say we should never show them. But this game is a good example of how migrating to good code is almost required to understand why it is good code. If you just have 3 rooms in the game, it’s hard to see why you need more than a handful of ifs. If you immediately try to subject the students to a full-fledged game engine they’ll be completely lost.
Indeed, I think this is a bit of a misunderstanding. Let me clarify! The code I would encourage people to write, and that I would write myself on worksheets or solutions or (hopefully) on the board is code that sets a good example and maintains a decent level of integrity. I’m not saying I’m going around deliberately handing out bad code, unless of course the aim of the lesson is to find out WHY this code is bad and improve it! However, there are certain things and certain ways of coding which I would simply not expect the average A-Level student to be able to understand.
For instance…supposing you had to validate some fields in a web app. Many programmers would use regular expressions to do this, which is probably more robust and more efficient. I can’t imagine many A-Level students being able to get their head around regular expressions (I can hardly do it myself!) so I’d be happy if they just did things like length checks, or type checks…or say it was an email address possibly did a string search for the character “@”. Not as good, not how a programmer would go about it, but it allows a) those who are actually curious to read up about regexp from some directed reading and b) those who are already confused not to be totally left behind.
What is crappy ?. From a coding point of view something that “works” is just enough, and that’s all you need, whether it’s crappy or not. At some stage visualising what you want or have to produce is usually important.
The interesting, learning experience is exploring what we mean by “works”, going beyond the functional requirements to the non-functional such as testing, readability, efficiency, throughput, consumption of resources, integration, enhancement, support, cost and so forth.
These requirements lead one to re-write code in perhaps a “non-crappy” way.
Early visualisation also helps someone focused on programming to appreciate what the impact of their design will be on the user, or indeed sometimes “who are the users” and what might they use the application for. This is just as important as writing good code.
I’ve just found your pdf student booklet for F452 Computing, which my pupils are taking in January. It looks very useful as a revision booklet. Thanks!
However, it is a good job I didn’t email out the link to it for my students! I’ve just clicked on the xkcd link on the front page – not good! I would have got into a mountain of trouble if that had gone out!
Huh? Not sure I understand – are you joking?
im trying to read your entire blog, at least back to 2010– and i promise not to reply to all your posts. this one is really important to me, however.
frankly, im pretty tired of all the fanciness with professional languages gilding the lily with every fad construct and frankensteinism that permeates the creep from language to art project. whats more, there is never a lot of consensus between the “helpful” people telling you “the right way.”
according to allen downey, the computer can do four things: read values, write values, do math, and jump conditionally. thats the essence of computing for the past 30 or 40 years or more. everything else is a useful abstraction so we dont have to write in machine language.
dictionaries are a wonderful thing, but teaching “the best way” to do something is kind of like refusing to teach someone how to drive across the country because “flying is so much better, so i will teach you how to fly a plane.”
deal with enough professionals, and you will see that a lot of times these “best practices” are fads, many dont work out, every one claims to be “the way its done now” and some will stick for 10, 20 years. meanwhile, you cant function as the citizen of a democracy in the 21st century unless youre computer literate. and how many people feel confident that they understand any of this?
theres a lot more to code than teaching people to become professional developers. and a lot of this “optimization” is a distraction from whats essential. if i were a conspiracy theorist, i would say theyre trying to prevent competition, not helping people learn the essence of computing.
but theyre not all wrong. what i take exception to is the baseless assumption that they have their priorities right. programming is like language, and like math. should math skip through all the basics and start with calculus or algebra? probably not.
the best example is goto. i never use it anymore; python doesnt have it. but dijkstra created this phobia that if you teach anything other than “the right way,” that education and computing will degenerate into chaos, and it will be impossible to salvage students that are ruined forever by a glorified JMP instruction. well then, i guess we shouldnt teach assembly either. if goto ruins you, so should jmp.
over and over, people circle angrily around anything simple enough to teach a beginner like a mob with pitchforks and torches. theyre not protecting anything but the status of the uninitiated. honestly, we make it much more difficult than it needs to be. lets not glorify that just because we invent a “better way” now and then. its a much bigger waste of time and energy than teaching the class twice: once to beginners, once to the novices.
computing claims to be a science. well, there are no formal studies to back up the claim that goto does any harm (to the student) whatsoever. its time we put that nonsense to bed. dijkstra was correct that goto is a construct worth avoiding in design, but wildly mistaken that it has any bearing on education. its one of the great myths of computing lore, that learning a simple thing the wrong way does harm. if computing is a science, lets start being scientific about this– im confident we will learn something.
This is a brilliant reply. I couldn’t have said it better myself. It reminds me of an article I found recently: http://blog.programmersmotivation.com/2014/06/19/beginner-programmer-want-learn-programming-start-build-crap/
The point is to get out and start writing programs, even if it’s “wrong.” You can always go and “improve” it later, just get something that works out there, even if you’re the only one who ever sees that form of it.
thanks very much!
also, great article. same blog has a post from 2014/10/21 about the command line that i would recommend to anyone.