Programming: A Series of Interesting Decisions

Imagine you are watching a Java programmer writing some code. Can you predict what they are most likely to do next in each of these situations?

  • The programmer moves the cursor to a new line, and types the three characters “boo”. What will they type next?
  • The programmer types “x = gteLength();” then gets an error that the method name is unknown. There is a method declared in the class named “getLength()”. What will the programmer do now?
  • The programmer types “ArrayList items;”. No class named ArrayList has been imported, but the standard library class java.util.ArrayList exists. What will the programmer do now?
  • The programmer has a variable named “old”. They have just renamed the declaration to “oldValue”. Now all the uses of the variable “old” are showing an error that the variable “old” does not exist. What will the programmer do next?

No prizes for guessing the most likely action in each case (but to be clear: type “lean” to make “boolean”, correct the typo, import the ArrayList class, change all the uses of “old” to use “oldValue”). These are so obvious that most IDEs now have automated support for helping in these situations. In Eclipse, Ctrl-Space (then Enter) will complete “boo” into “boolean”, hovering over the second error will offer a one-click option to correct the method name, pressing Ctrl-Shift-O in the third case will import the java.util.ArrayList class for you, and pressing Alt-Shift-R before renaming in the fourth case will rename all uses of the variable at the same time.

did-you-mean

One measure of a computer interface, such as an IDE, is the extent to which it reduces the predictability of your next sequence of actions. This may initially sound odd, but your next actions should always be hard to predict — if it’s easy to predict the next sequence of actions (e.g. “boo” being followed by “lean”), the interface should roll it into one action (code completion) or, if it’s 99+% clear what the action will be, just do it for you. Contrast the boo-lean case with what the programmer is going to type when they’ve just written “int ” in a method — it will be a new variable name, but it’s very difficult to predict what the name will be.

There are parallels to information entropy here — the letter E was one dot in morse code because it makes sense that the most frequent action has the shortest code. Similarly here, the most likely behaviour should have the shortest sequence of interface actions to trigger it. (You have to be a bit careful because the user might not want to fix the error immediately, especially in the third case. They may want to keep coding, so you don’t want to interrupt them with a dialog or anything too extreme.)

IDEs in Education

In a professional IDE, the goal is to support an expert programmer in writing good code quickly. However, our team makes educational IDEs, which have a different goal: to support novice programmers in learning how to program. Assistance can of course be positive — it can help move novices past the boring, frustrating parts of learning coding (syntax errors, obscure error messages) on to the interesting parts (like algorithms and design). However, assistance can also have downsides for novices:

  • If you present novices with a list of actions, they may not understand them fully, and may choose one just because it’s available. For example, “You are trying to pass a Person to this method but the type required is the Product interface. Do you want to (a) cast Person to Product or (b) let Person implement the Product interface?” The correct fix is to pass a different value as that argument, but that fix is not offered — a novice may think the only possible fixes are those in the list.
  • Doing too much in one action may lead to not understanding what assistance was given. For example, Eclipse has an option to pick a parent method from a class and override it. Will students understand why the “public void setLocation(int x, int y)” method in Crab overrides a corresponding method in Actor (but “public void setLocation(double x, double y)” does not)? At the extreme case, you don’t want Clippy popping up with “You seem to have written a bug in your quicksort implementation. Click here to automatically fix it”.
  • Too much assistance may be overwhelming at first. Some IDEs start offering completion as soon as you start typing a type or method name. If all the novice is trying to do is write their first variable declarion, do you want to present them, unbidden, with a popup list with all the available classes in the Java standard library?

There is no single right or wrong answer to these issues, and the question of how much assistance is the right level to provide. In the past, BlueJ and Greenfoot have offered only minimal assistance, preferring too little rather than too much. However, in our work at the moment on Greenfoot 3, we are moving towards having more assistance: code completion will be more featured (though I think it will still not popup automatically), and there will generally be more help offered by the environment in writing code and correcting errors.


Postscript: The title for this post comes from Sid Meier, who said that games (which, for him, means strategy games) are “A series of interesting decisions”. If there are no decisions to be made then there is no player involvement and there is not much point in them being sat there. If the decisions are obvious, then you are wasting the player’s time. The reason for the player to be involved is that there is a non-obvious decision for them to make. This seems to me to have a clear parallel in designing interfaces.

2 Comments

Filed under Uncategorized

The ugliest beautiful line of code

Some program code is considered beautiful, often because it accomplishes a great deal just by combining a few simple primitives. One such line in C is the loop that copies one string (const char* src) into another (char* dest), using only programming language primitives:

while (*dest++ = *src++);

(For those who don’t know C very well, “*src++” takes the value from the src pointer, then increments the src pointer. “*dest++ =” stores the value in the dest pointer then increments the dest pointer. The result of the expression is the copied value, and as long as this value is non-zero, the loop continues. Because C strings end in a zero, usually called a null terminator, this loop keeps copying from src to dest until the zero has been copied.)

The code does have an elegance to it. But the more I think about it, the more I realise that this one line manages to contain many of the flaws in the C language:

  • The expressions have both a prefix and postfix operator on the same item, which makes precedence very hard to guess. Is that (*dest)++ or *(dest++)? Both are reasonable answers, but you can’t judge it easily from the syntax. (See also “const char * p” — is that “const (char * p)” or “(const char) * p”?)
  • The loop body is a single semi-colon. This can cause problems for beginners, who instinctively put a semi-colon at the end of every line. For example, what does this code do?
    int n = 0;
    while (*dest++);
    {
        n++;
    }
    
  • The loop condition has a side effect, which is why no body is needed. In general, side effects in loop conditions and if conditions are a source of bugs because they make refactoring trickier and you are more likely to miss seeing side effects in conditions than other code. Not to mention that assignments in conditions are easily confused with equality checks. What do these two loops do: “while (*dest++ = 0);” vs “while (*dest++ == 0);” ?
  • The condition uses C’s ability to have any numeric type in an if condition, with non-zero meaning true. This is another source of bugs, as you won’t notice if you forget to add “== 0″ or “< n" on the end of a condition.
  • Perhaps most crucially, this code works because C’s strings are null-terminated. Unless you can guarantee that src has a null terminator within the bounds of the dest array (not src!), this is a buffer overflow that will write beyond the end of the dest buffer and trash your stack until src happens to finish. Oh, and if dest is pointing to a location in src before the end of the src string, it’s an overflowing infinite loop.

So what lesson should be taken from this, apart from the fact that C is a dangerous language? I wonder if we should beware any such terse elegant code. I’ve written some wonderfully brief code in Haskell before, and usually had to rewrite it again so that it is more easily intelligible for next time I look at it. A lot of people mock Java’s verbosity, but I at least find it reasonably rare that I have to deal with Java code that is too clever for its own good.

1 Comment

Filed under Uncategorized

Localisation of Programming Languages

Localisation is a technical term meaning the translation of software into foreign languages (German, Chinese, etc). This typically relates to a software’s interface: the translation of menus and text in dialog boxes into the local language. For example, if you set Greenfoot’s interface language to German, the “Edit” menu becomes “Bearbeiten”, Copy becomes “Kopieren” and so on.

Almost all programming languages have English keywords: if, while, etc. For a non-native English speaker, these keywords may well appear to be magic invocations, just as it would be to me if the keyword for “while” was a Chinese character. (One study suggests that the names for Java keywords are not very obvious for English speakers anyway, but at least they are in the right language!) In a block language like Scratch, there is the opportunity to localise the programming language itself: to translate the text in the blocks to the local language. The “change colour” block could become “Farbe ändern”. [Note: that one is picked from Google Translate, excuse any mistranslation] Is localising a programming language worthwhile?

I think the value of localising a programming language depends greatly on two things: the age group you are pitching your programming language at, and the control you have over the programming language and libraries. If you are aiming at six year olds then it is unlikely they will have had much chance to learn much English, and especially going outside their native character set would be confusing. (I believe that ScratchJr uses pictures for instructions partly to solve the localisation problem, but also to some extent to overcome reading weaknesses at such young ages.) The languages used in systems for this age group tend to be custom-designed, so the designers of the system have full control over the small language and libraries. So for small systems at young age groups, localisation is feasible, and there is a lot of benefit to be gained from it.

However, consider a system aimed at universities. For better or for worse, all major professionally used languages are in English. Java, C#, Python and the rest have English keywords, and (perhaps even more importantly) English APIs. Even if you provide a thin pre-processor to translate the keywords, you can’t feasibly do the same for all the APIs. There is no way you can translate the entire Java ecosystem and its documentation into another language (e.g. French). So even if you created an educational language, X, which can be fully localised into Arabic, is there much advantage to using it at a university when the students’ next language will be Java and they will have to learn English anyway?

Edit: I note that being able to put variable names in your local language is definitely useful for the programmers, but because the APIs are in English, there will still be a lot of English throughout any code; programmers will need to know English even if they don’t use it everywhere, and whether the keywords are localised doesn’t make a whole lot of difference as they are easy to learn over the long-term.

Summary

The older (and thus closer to professional programming) that you aim, the less sense it makes to try to translate the language. In Scratch 1.4, you can only use the blocks provided with the system, but in a language like Java, the core APIs (even List, String) etc are in English, and so are all the add-on libraries (e.g. to talk to MySQL), so you will have to know English to read the documentation and use the methods. Trying to localise programming languages at older ages seems to be a fool’s errand, and only protects students temporarily from the inevitable truth: to be a professional programmer, you need to learn English.

Leave a comment

Filed under Uncategorized

Spaces in variable names

Most programming languages do not permit spaces in variable names. However, it is often useful to have a variable name that is composed of several words, such as “destination file” or “error handler”. Programmers have tended to work around this issue by using either underscores (“destination_file”, “error_handler”) or camel case (“destinationFile”, “errorHandler”). But what if you were in a position to allow spaces in variable names — is there a good reason not to allow spaces?

Technical Challenges

The reasons that spaces were historically disallowed in variable names is that it tends to introduce ambiguity into language grammars, where a space separating two identifiers may be meaningful (e.g. Haskell). However, I believe that some languages could almost allow spaces in variable names, because two identifiers (i.e. not keywords) separated by a space are a syntax error. In Java, for example, the only situation I can think of that it is valid to have two identifiers separated by only a space is during declaration of variables, methods and parameters, where the type and name are separated by whitespace (“int x”, “String getText()”).

If we use a symbol, let’s say double colon, to separate types and names, I think we could allow spaces in Java variable names without ambiguity, e.g. (newline added solely for readability)

int :: x position of rocket =
  x position of spaceship + x rocket launch offset;

It may look a bit alien to an experienced coder, but there’s no ambiguity in parsing that, and I don’t see that it is necessarily worse than:

int xPositionOfRocket =
  xPositionOfSpaceship + xRocketLaunchOffset;

(Ok, the plus symbol is a bit buried in the first line, but a little syntax colouring would probably offset that.)

In a text-based language like Java, you do have the complication that if one of the words in your variable name is a keyword — or begins with a digit — it may become hard to parse. In contrast, in a block-based language like Scratch, there is no such problem — variable names are typed into their own text field, so there is no parsing problem and thus Scratch allows spaces in variable names.

Pragmatic Restrictions

When you use a variable in Scratch, you select the declared name from a dropdown. Thus there is no requirement for the user to type the exact declared variable name, as there is in most other systems. To this end, I would suggest prevent leading and trailing spaces on a variable name (parsing that would definitely be a nightmare), and also for sanity, preventing multiple adjacent spaces in a variable name. There is no good reason to have a difference between “x position” (one space) and “x position” (two spaces), and allowing a difference will only lead to madness while you track down a syntax error caused by an accidental double space.

Spaces

If you were designing a language and could allow spaces in variable names, would you do it? Is there any reason not to allow them, if you can overcome the potential parsing difficulties?

2 Comments

Filed under Uncategorized

Using Haskell’s type system in Blackbox analysis

Neil Brown:

For some of the Blackbox analysis work that I’ve been doing, I have used Haskell as a programming language. It seemed like the best tool for the job, given its strong support for concurrency and parallelism (needed to speed up the analysis) and for parsing and manipulating syntax trees (which is needed for most of the analyses). I wrote a short article for “The Monad Reader” magazine about some of the ways in which Haskell’s strong type system helped with writing the analysis. Direct link: http://themonadreader.files.wordpress.com/2014/04/nccb.pdf or see the reblogged post for the full contents and other articles in the issue.

Originally posted on The Monad.Reader:

I am pleased to announce that Issue 23 of the Monad Reader is now available.

Issue 23 consists of the following five articles:

This time around, I have individual article files for each (and the supercompilation article has an extra appendix not included in the full issue PDF).

Feel free to browse the source files. You can check out the entire repository using Git:

git clone https://github.com/ezyang/tmr-issue23.git

If you’d like to write something for Issue 24, please get in touch!

View original

Leave a comment

Filed under Uncategorized

Blackbox: Observing Student Behaviour

Blackbox logoWhat do beginners do when they are learning to program? Where do they get stuck, and how can we improve their learning?

Because people program via a computer, we have the ability to add data recording capabilities to the tool they are using to program, and thus automatically observe their programming behaviour. (Aside: this should also be possible with a word processor to see how different students compose essays — surely someone must have looked at that?) From these observations we can hopefully learn how different students program, where they are getting stuck, and come up with ways to improve their learning experience.

There have been many previous small local studies that have recorded data from students at a single institution. In a paper published last week at the SIGCSE 2014 conference, we detailed our “Blackbox” project, in which we are collecting data from hundreds of thousands of programming students worldwide, and sharing the data with other programming education researchers. This kind of data is not a panacea for programming education, but we hope that it provides an interesting new, large dataset with which to study some aspects of beginner behaviour. I’ve written more about this project in a previous post, and hopefully the paper provides a more thorough (but still readable) summary of the project so far, along with a few example mini-analyses.

At the end of the SIGCSE conference, we held a workshop to explore how to get started with analysing this kind of data. Here are some relevant points that arose:

  • We looked at some traces of programmer behaviour in the workshop. One participant shared their observation: “This student was not having a great time.” Browsing some of these traces is like watching a classic horror film, as you watch frustrated while the protagonist makes all the wrong decisions, heading into all the wrong situations. They’re so close to right… and then a bad error message sends them down the wrong track, and they delete their code and try writing it again. You want to reach back through time, and across the Internet, to give them a hug. And point out how to fix their problem. Looking at these traces shows how much headroom there is to improve students’ learning experience.
  • Analysing this kind of data is difficult. If you want to analyse at large scale, you must be able to do it automatically, with a program. The requirement to translate your relatively high-level abstract research question into a concrete analysis program is difficult, and full of non-obvious caveats and assumptions.
  • We are sharing this data with other researchers, and I am confident that this is a good decision. Research surely progresses much faster when teams of researchers communicate with each other and build on each other’s work. If you want to advance the methodology in a domain, you want researchers to have easy access to data. Where feasible, data sharing seems to make as much sense as code sharing. We are now launching a small online community to allow researchers using the Blackbox data to coordinate and share tools and ideas with each other.

I’ll hopefully post a bit more about some simple trends and results in future, time permitting. For now, the paper contains most of what little we have done with the data thus far.

Leave a comment

Filed under Uncategorized

Seven Short Book Reviews

In the middle of last year I started reading non-fiction books quite regularly. Most of books relevant to computing education have already been covered in previous posts: Teacher Proof by Tom Bennett, Why Don’t Students Like School by Dan Willingham, Mindstorms by Seymour Papert, Visible Learning by John Hattie, and Peer Instruction by Eric Mazur. (Are there many good non-fiction computing books? Seems like the economists and psychologists have managed to produce best-sellers, but not computer scientists.)

Instead, this post features mini-reviews of seven books not relevant to computing education that I’ve read in the past year:

signal-and-noiseThe Signal and the Noise by Nate Silver. At a previous job, we used to play poker at lunchtimes. Once an argument broke out over whether you judged a decision (raise/fold) on the information you had available at the time, or the eventual outcome of the hand. Were you right to fold against a high bet when only holding a pair of eights because it seemed unlikely you would win, or wrong because you later would have won when the third eight appeared? I see Silver’s book, which features a chunk on poker, as a long explanation of why the decision must be judged against the available evidence, not the outcome that unfolded later. Most practical outcomes have an element of uncertainty, and Silver argues that people are bad at recognising and accounting for the uncertainty. We may want to predict the election or the weather, or some other outcome of interest. Realistically, we can only offer a probabilistic prediction: 80% chance of rain, 75% chance of Obama’s victory. If it later turns out there was no rain, that does not mean the prediction was flawed. Moreover, any certain prediction — it will definitely rain today, Obama will win the election — is flawed or useless, even if it appears better and more useful than the hazy probabilistic prediction.

the-gambleThe Gamble by John Sides and Lynn Vavreck. The Gamble concerns the determining factors behind the 2012 US election result. It is chock full of data, and offers a relatively unexciting explanation for the election result: there were no game-changing gaffes, no big swings, no canny campaigning. The election was decided by fundamentals (e.g. the economy) and two juggernaut campaigns that cancelled each other out. I find The Gamble an interesting book in the wider scheme of things. I must admit that I would have preferred to read a dramatic blow-by-blow account of the debates and gaffes (binders full of women! that 47% remark!) and so on, but The Gamble seems to be the correct answer: a slow and steady data-based account of the election that gets to the heart of the matter. I guess evidence-based rationalism means that you have to live without unnecessary excitement.

liars-pokerthebigshortLiar’s Poker, and The Big Short, both by Michael Lewis. These are excellent as a pair. Liar’s Poker was written in the ’80s by Lewis after he quit his bond trading job and wrote a tell-all book about Wall Street. It explains how, in the ’80s, mortgages went from simple affairs between the building society (or equivalent) and the borrower, to being traded as bonds on Wall Street. It details that a lot of traders were immature, unscrupulous, and often trading on their customers’ ignorance to make fortunes. Of course, repackaging and misrating of these mortgage-backed bonds was a trigger for the recent economic crisis, so it was no surprise that Lewis returned to the same area to write The Big Short, which focuses on the oddball few who correctly predicted the meltdown ahead of time and found clever ways to make money off this (more on this in a moment). Several of them were driven close to a personal meltdown, because they could not tally their evidence-based prediction that the market would crash heavily, with the behaviour and beliefs of all the other traders in the industry, who seemed to be happily sailing their ships over the cliff. It gives you some insight into why when everyone is wrong, it is hard to be right.

This pair of books also leads to an interesting observation. In Liar’s Poker, Lewis did not portray brokers well. They mostly appear in the book as a bunch of conniving (although admittedly canny), greedy, immature louts. The book was a fairly damning exposé, and Lewis’ ex-CEO would later claim that it “destroyed his career”. So there Lewis is, 20 years on, trying to write a second book about Wall Street. Who would dare talk to him, knowing all this? NPR asked him in an interview, as described by Tim O’Reilly:

You have to understand, Lewis replied (more or less), that many of those people got into the financial industry after reading [Liar's Poker]. Their big takeaway was how easy it was to make a lot of money without regard to the niceties of creating much value. He finished with the memorable line, “You never know what book you wrote until you know what book people read.”

Bad PharmaBad Pharma by Ben Goldacre. Bad Pharma is an examination of how medical research and development is set up wrongly, and is providing opportunities and incentives for companies to act against patient’s interests, often with collusion from regulators and doctors. Some of the bad-regulation aspects chime with The Big Short, where regulators seem beholden to the companies they are intended to regulate. It’s an important book and one worth reading, as a general read, and if you are involved in (any kind of) research. The practices to do with authorship on papers and ghost-writing, and the responses by some journal editors, are quite eye-opening.

marvelcomicsBrick by BrickMarvel Comics: The Untold Story by Sean Howe, and Brick by Brick by David Robertson. Two similar books, one about Marvel Comics and one about Lego. My slight frustration with both books is that I was somewhat hoping for an indulgent read all about the evolution of Technic and Spider-Man, but instead both books focus heavily on the political and business sides of Marvel and Lego, with surprising little detail on the actual products of the company. You read all about the politics that forced a change in writer of the X-Men, but not much about the plotlines, or evolution of the art and colouring. You read about the background to the changing CEOs at Lego, but get little description of the differing sets and bricks beyond their general sales figures. Clearly, I was still picking too much from the serious end of things!

You do come away with a sense of how Marvel shoot themselves in the foot by driving short-term sales (limited edition covers, cross-overs) over quality or long-term loyalty — and they continued to do this even though they knew it hurt long-term sales. Also interesting is how both companies nearly drove themselves to the point of irrelevance and bankruptcy: Lego were saved by refocusing and getting smarter about their business processes; Marvel were largely saved by their recent adventures into blockbuster films. The Marvel book also has a fairly dark undertone: steadily thoughout the book, lots of employees seem to die early, to the point where it no longer seems to be confirmation bias. One illustrator dies at the drawing board of a heart attack, aged just 32. It’s a little like seeing a documentary about the sweatshops where your clothes are made: a hidden human cost to your fun. I suspect there would be similar tales from a book about the computer game industry.

That’s the lot for now! I’ve got a few more books left on my reading pile, but recommendations for others (relevant to computing education or not) are welcome.

1 Comment

Filed under Uncategorized