Gas station without pumps

2013 May 17

Gettting high school students excited about programming

Filed under: Uncategorized — gasstationwithoutpumps @ 20:33
Tags: , , ,

When it comes down to it, what I’m feeling right now is probably what every teacher feels at some point—the magical epiphany that “A few weeks ago, my students didn’t know [what programming was], and now they’re [running home to work on coding challenges] and [saying that they want to study computer science in college].”

There were two parts to this success story:

  • a one-hour introduction to programming, which was really a thinly disguised pitch for the computer science course we’ll be offering for the first time next year. I had my students warm up with a Do Now asking them to identify some of the many ways they rely on coding in their everyday lives, without even realizing it. I used this PowerPoint as a basis for our discussion, which led into this (now semi-viral) video put out by Code.org, and finally some live coding in Python (the Word Smoosher was a big hit).
  • a visit by Jeremy Keeshin, cofounder of CodeHS.com. Thirty-two (out of 74) juniors from across the academic spectrum signed up for an after-school workshop that Jeremy ran to introduce students to some of the basics of coding as well as the terrific online platform for learning coding that he has developed. The program is such that students are able to watch short tutorial videos and work on challenges at their own pace, and Jeremy and I mainly circulated to help students troubleshoot …

It sounds like a very good beginning—I hope that the programming course that they are offering next year goes well.

Read the full story at via Infinigons, etc.: Have an hour to fill with your students?.

2013 March 21

Why Python first?

Filed under: home school,Uncategorized — gasstationwithoutpumps @ 11:21
Tags: , , , , , , ,

On one of the mailing lists I subscribe to, I advocated for teaching Python after Scratch to kids (as I’ve done on this blog: Computer languages for kids), and one parent wanted to know why, and whether they should have used Python rather than Java in the home-school course they were teaching.  Here is my off-the-cuff reply:

Python has many advantages over Java as a first text-based language, but it is hard for me to articulate precisely which differences are the important ones.

One big difference is that Python does not require any declaration of variables. Objects are strongly typed, but names can be attached to any type of object—there is no static typing of variables. Python follows the Smalltalk tradition of “duck typing” (“If it walks like a duck and quacks like a duck, then it is a duck”). That means that operations and functions can be performed on any object that supports the necessary calls—there is no need for a complex class inheritance hierarchy.

Java has a lot of machinery that is really only useful in very large projects (where it may be essential), and this machinery interferes with the initial learning of programming concepts.

Python provides machinery that is particularly useful in small, rapid prototyping projects, which is much closer to the sorts of programming that beginners should start with. Python is in several ways much cleaner than Java (no distinction between primitive types and objects, for example), but there is a price to pay—Python can’t do much compile time optimization or error checking, because the types of objects are not known until the statements are executed. There is no enforcement of information hiding, just programmer conventions, so partitioning a large project into independent modules written by different programmers is more difficult to achieve than in statically typed languages with specified interfaces like Java.

As an example of the support for rapid prototyping, I find the “yield” statement in Python, which permits the easy creation of generator functions, a particularly useful feature for separating input parsing from processing, without having to load everything into memory at once, as is usually taught in early Java courses. Callbacks in Java are far more complicated to program.

Here is a simple example of breaking a file into space-separated words and putting the words into a hash table that counts how often they appear, then prints a list of words sorted by decreasing counts:

def readword(file_object):
    '''This generator yields one word at a time from a file-like object, using the white-space separation defined by split() to define the words.
    '''
    for line in file_object:
        words=line.strip().split()
        for word in words:
             yield word

import sys
count = dict()
for word in readword(sys.stdin):
     count[word] = count.get(word,0) +1
word_list = sorted(count.keys(), key=lambda w:count[w], reverse=True)
for word in word_list:
    print( "{:5d} {}".format(count[word], word) )

Note: there is a slightly better way using Counter instead of dict, and there are slightly more efficient ways to do the sorting—this example was chosen for minimal explanation, not because it was the most Pythonic way to write the code. Note: I typed this directly into the e-mail without testing it, but I then cut-and-pasted it into a file—it seems to work correctly, though I might prefer it if if the sort function used count and then alphabetic ordering to break ties. That can be done with one change:

word_list = sorted(count.keys(), key=lambda w:(-count[w],w))

Doing the same task in Java is certainly possible, but requires more setup, and changing the sort key is probably more effort.

Caveat: my main programming languages are Python and C++ so my knowledge of Java is a bit limited.

Bottom-line: I recommend starting kids with Scratch, then moving to Python when Scratch gets too limiting, and moving to Java only once they need to transition to an environment that requires Java (university courses that assume it, large multi-programmer projects, job, … ). It might be better for a student to learn C before picking up Java, as the need for compile-time type checking is more obvious in C, which is very close to the machine. Most of the objects-first approach to teaching programming can be better taught in Python than in either C or Java. For that matter, it might be better to include a radically different language (like Scheme) before teaching Java.

The approach I used with my son was more haphazard, and he started with various Logo and Lego languages, added Scratch and C before Scheme and then Python.  He’s been programming for about 6 years now, and has only picked up Java this year, through the Art of Problem Solving Java course, which is the only Java-after-Python course I could find for him—most Java courses would have been far too slow-paced for him.  It was still a bit low-level for him, but he found ways to challenge himself by stretching the assigned problems into more complicated ones.  His recreational programming is mostly in Python, but he does some JavaScript for web pages, and he has done a little C++ for Arduino programming (mostly the interrupt routines for the Data Logger code he wrote for me).  I think that his next steps should be more CS theory (he’s just finished an Applied Discrete Math course, and the AoPS programming course covers the basics of data structures, so he’s ready for some serious algorithm analysis), computer architecture (he’s started learning about interrupts on the Arduino, but has not had assembly language yet), and parallel programming (he’s done a little multi-threaded programming with queues for communication for the Data Logger, but has not had much parallel processing theory—Python relies pretty heavily on the global interpreter lock to avoid a lot of race conditions).

2013 January 1

Is coding for everyone?

Filed under: Uncategorized — gasstationwithoutpumps @ 07:41
Tags: , , , ,

One of the memes in computer education last year was “coding for everyone”.  For example, the year started with Mayor Bloomberg vowing to learn to code using Code Academy (how did that go for you, Mayor?), and there was Rip Empson’s post STEM Ed: CodeHS Wants To Teach Every American High Schooler How To Code, in which he reviewed the CodeHS online program to teach high schoolers how to program, and a host of other posts that I did not bother to bookmark all claiming the wonders of universal literacy in programming languages.

In May, there was a backlash: Jeff Atwood’s Coding Horror: Please don’t learn to code made the claim

The “everyone should learn to code” movement isn’t just wrong because it falsely equates coding with essential life skills like reading, writing, and math. I wish. It is wrong in so many other ways.

Atwood’s main points are that coding is not the goal, but just a tool in solving some types of problems, and that thinking about problems is more important than concentrating on this particular tool.  He’d rather have people like Bloomberg concentrate on doing the things they are good at rather than becoming half-assed programmers, and leave the programming to people who have the time and the inclination to do the job right.

I think that Atwood position, like Andrew Hacker’s claim that high algebra is pointless, is a deliberately extreme position taken to raise passionate responses and sell newspapers.  Hacker claims to want to lower the already low value of a high-school diploma by reducing the math required for it below the 8th-grade level currently required.  Atwood wants only professional programmers to learn to program.  Both appear to be protecting elite privileges by claiming that education is too much for the masses, and that they don’t really need it anyway.

Atwood makes an analogy to everyone learning to do plumbing, as if that were a ridiculous idea.  Personally, I think that everyone should learn a little plumbing: enough to clear a toilet or sink trap, or replace a faucet washer, and to know when to call in a professional plumber. So his analogy is an excellent one and completely undermines his conclusion.

Steve Myers, in Software developer revives debate about whether journalists should learn to code, makes the analogy to the “reporters vs. bloggers” war.  Unfortunately, that fight appears to have been settled by laying off most professional journalists and killing off a lot of newspapers, with the resultant degradation in the quality (though not the quantity) of news that people get.  As a blogger, I don’t think that discouraging blogging is the right way to support journalists, but if the analogy is a good one, then I can see why people like Atwood are attacking amateur programmers in fear for their jobs.

Myers quotes Andy in Don’t not learn to code

Even if someone who learned how to “code” never ends up as a “coder” professionally, they will be much better for having learned to think algorithmically and in the abstract. However, I bet that knowing how to write a quick script here and there will make them much more valuable in whatever profession they choose.

Andy makes the standard case for learning to program:

Do I always use software to solve problems? Definitely not. But do I often use the same problem solving techniques that learning to code taught me in order to solve other problems in my life and work situations? Definitely yes.

Can folks be taught to solve problems without using computer code? Definitely yes. But is learning how to “teach” a computer how to solve problems via code one of the best ways? I think yes as well.

In Definitions of “Code” and “Programmer”: Response to “Please Don’t Learn to Code”, Mark Guzdial points out

Most people who write code are not trying to create code solutions.  Most people who write code are trying to find solutions or create non-code solutions.  By “most people,” I do mean quantitatively and I do mean all people, not just professional programmers.  We know that there are many more people who write code to accomplish some task, as compared to professional programmers.

The point of the coding-for-all movement is that there are lots of times when a small amount of coding or scripting on a computer can solve an immediate problem without calling in a professional programmer.  Little snippets of throwaway code can be enormously useful for getting data into a form suitable for thinking about a problem, and the ability to create those snippets quickly is a very valuable skill.  I know I would feel very constrained if I had to wait for someone else to understand what I was trying to do and implement it for me every time I wanted to plot some data or model something.  I try to get the biologists and bioengineers that I teach to have some coding ability—enough to fit models to data, reformat data so that it is usable by other programs, and do simple analyses.  I don’t expect most of them to become professional coders (not even all the bioinformaticians need to be expert programmers, though most should be), but they all need enough skills to do the little tasks (the equivalent of clearing sink traps in plumbing) and to know when they need to call in the professionals.

Mark Guzdial takes particular exception to Atwood’s claim “You should be learning to write as little code as possible. Ideally none.”

And people who want to do interesting, novel things with computers should just wait until a software developer gets around to understanding what they want and coding it for them?  I could not disagree more.  That’s like saying that the problem with translating the Bible is that it made all that knowledge accessible to lay people, when they should have just waited for the Church to explain it to them.  Please don’t learn to code” can be interpreted as “Please leave the power of computing to us, and we’ll let you know when we’ll make some available to you.”

As may be clear by now, I tend to side with those who would teach programming skills (and math) to everyone, even though not everyone will end up particularly good at programming or math.  I believe that I have enough skills and intelligence that I’m not threatened by an increase in the skills of others, so I don;t see any benefit in choking off education for others.

On the other hand, I don’t think that the coding-for-all movement will be any more successful than the math-for-all movement has been for the past century.  Math is taught to everyone and people are required to get through algebra and some geometry to get a high school diploma, but huge portions of the American adult population are still functionally innumerate. Even after ten years of learning math, many adults can’t add fractions or figure out that lottery tickets are a sucker bet.

The coding-for-all movement is starting from a much lower base—almost no elementary schools and very few high schools teach programming, and those that do generally have only one course in Java syntax, which will not get people very far in learning to solve problems.  So even if the coding-for-all movement is wildly successful and creates tens of thousands of teachers (coming from where, exactly?) teaching high-schoolers how to program, the fraction of people who are even marginally competent programmers will remain pretty small.  The online courses like CodeAcademy and CodeHS try to get around the shortage of teachers by having a computer do the work of teaching, but they are pretty miserable failures at teaching to even the low level of high school programming courses.  It’s nice that there are resources that will allow dedicated students to get around the curricular limitations of their high schools (current or past), but they are not going to lead to a world of universal coding competence.

2012 December 7

On grading programs

Filed under: Uncategorized — gasstationwithoutpumps @ 10:01
Tags: , , , , , ,

One of our senior grad students sent me an e-mail today:

Subject: Pedagogy question
Date: Thu, 6 Dec 2012 22:07:34 -0800

I was talking about 205 with one of the first year students and it
occurred to me that I didn’t know how you tested people’s code. The
student was sure that you actually read the code and I always imagined
you had a pipeline that used unit testing on the submissions and only
read the code when things went wrong.

How do you do it? Thanks

The answer is that for most assignments I do both.  I have a Makefile that runs each student’s assignment on a number of test cases, and compares the output to the desired output.  For some assignments, where the output is not unique (for example, in sequence alignment, where there may be multiple correct alignments, I do some postprocessing of the outputs to get comparable values (for alignments, I rescore their output alignments and compare sequence lengths and scores, rather than the alignments themselves). I’m doing simple I/O testing, not unit tests, as unit tests need to be designed into the programs as they are built.  I’m not giving the students scaffolds to build their programs around, not even library specifications, so I can’t have a generic set of unit tests for their programs.

I often have to put student-specific code into the Makefile to correct for minor student errors, like misnaming a command-line option for the program or having set the default values for options wrong.  Sometimes I have to make a copy of a program and edit it (for example, to remove MS-DOS carriage-return characters from the source code) before I can get it to run, but I try to avoid doing that after the first couple of assignments.

Some assignments do not lend themselves to simple I/O comparisons (such as the simulation tests to determine the frequency of long ORFs on the reverse strand of a gene). For those, I don’t run the programs, but rely on the student-reported histograms and model fits for the output check.

Without the I/O tests, it would be very difficult for me to grade the programs well, as there are often subtle bugs in student code that can only be teased out by testing unusual inputs—I certainly don’t have the days it would take to do a thorough reading and debugging of each student’s code.  Each year I try to improve at least one of the automated tests to do a more thorough job of testing—sometimes this improvement involves modifying the assignment to provide more clearly specified or more testable formats, sometimes it is just the addition of some more corner cases to the test suite, and sometimes it is better postprocessing to do more thorough checking of the output.  I reuse nearly the same assignments each year (though 2 assignments this year were used for the first time), so that the testing improves gradually from year to year.

After doing the I/O checks, I then read all the programs. I start with the programs that did not pass I/O tests, trying to provide debugging help.  That debugging help is usually the most time-consuming part of the grading.  On all the programs I try to provide some feedback on the documentation (which is usually awful, though I had one student this year who really got the point of documentation and did a better job of it than I usually do).

In addition to the documentation feedback, I try to provide suggestions to make the Python more efficient or more idiomatic. For example, I had one student this year who always used complicated “while” loops where simple “for” loops would have been much easier to read, and lots of times people would write multi-line loops than could be more easily expressed with a list comprehension.  Students who wrote very good, idiomatic Python got many fewer comments from me than students who were struggling, though I always tried to find at least one useful thing to say to them.

The code-reading is rarely fun—maybe 10% of the students program well enough to make reading their code pleasant rather than painful, but I think that the feedback the students get from it is one of the most important parts of the course pedagogically.  Most of the students have never had such detailed feedback on their programming, because it is expensive to provide.  It takes me an average of 10–20 minutes per student to do the code reading (depending on the complexity of the assignment), which is barely feasible for a class of 20 once a week and would be prohibitive for a larger class or  with more frequent assignments. The I/O checks generally only take about 10 minutes per student, and could be reduced substantially if I just failed students who didn’t pass the I/O checks, rather than trying to patch my test or their code to allow almost working code to be tested.

I spend much more time on the weaker programmers than on the good ones, which may be why the senior grad student does not remember much of the feedback (he also took the course when we were still using Perl, rather than Python, and I provided less feedback on good programming style and idioms—it is damned hard to write a good program in Perl, and many Perl idioms are nasty, ugly hacks).

By the end of the course, everyone who passes is at least a minimally competent Python programmer and can write the sort of data-wrangling code that every computational biologist needs.  I think that this year students all ended up with a decent grasp of using tuples as keys or values for hashes and of using generators (made with “yield” statements) for doing input parsing.

Several of them also learned how to collaborate without copying. I had several students who talked to each other about each assignment, helping each other learn Python and the algorithms of the course, while writing distinctly separate code.  They were also very good about acknowledging their collaborators—a habit that more courses should be trying to develop. There was only one student I had to chide about copying code he did not understand (and that wasn’t working anyway), and even he had properly cited the original author of the code, so was not in any danger of an academic integrity violation.

Most of the students also can do substantially better documentation than when they started the course.    Over half the class is now routinely commenting on the meanings of their variables and the return values of their functions, though not always as clearly as I would like.

I’m considering rewriting my old “document-this-code” assignment from when I taught technical writing, updating it for Python and adding it to the course, which is already pretty full with 7 programs, a fellowship application, and a research paper, in addition to the “content” material about bioinformatic models and algorithms.  The workload is high for a 5-unit course, which should total only about 120 hours, including the 35 hours of class time (I suspect that the workload varies from 100 to  150 hours already), and so I’m hesitant to add another assignment. It seems that many of the students have never seen a decently commented program and have no idea what I mean when I complain about the vagueness of their comments. They understand when I complain about the lack of comments, but don’t know what they should put in the comments.

All the students in my course have had previous programming courses, often several such courses.  (I had a couple of students start the course this year without prior programming courses, and drop after the first two assignments, with the intent of trying again after taking some programming courses.)  If I remember right, only one of the students started the course with a good documentation style.

I understand why the huge CS courses can’t provide the detailed feedback needed to get students to document well, but I think that it is a shame.  Writing programs is like writing papers in many ways, with the same concerns about organization at different scales and the need for clarity, completeness, correctness, and conciseness (the four Cs of technical writing—I was going to write a blog post about that over a year ago, and never finished it—one of my 167 unfinished draft posts).  Programming classes should be taught like writing classes, with detailed feedback from experienced programmers, but I’m afraid that administrators are so in love with mass production that they are more likely to want to make programming courses bigger with less feedback to the students rather than move to a high feedback, high cost approach that could actually produce good programmers.

Of course, administrators would love to convert the writing courses into mass-production classes also. Writing classes used to have only 20 students per instructor, in order to provide adequate feedback, but the continued defunding of instructional activity in favor of administrative bloat and constructing new research buildings has resulted in writing classes having more like 30 students per instructor, with the consequent decrease in the quantity and quality of feedback to the students.  It is only a matter of time before administrators decide that MOOCs with “peer feedback” are good enough for the peons, and eliminate small classes and professional feedback from writing courses also.

 

 

 

 

2012 September 30

Learnable programming is not necessarily visual

Filed under: Uncategorized — gasstationwithoutpumps @ 20:35
Tags: , , ,

Everybody seems to be blogging about the multi-media essay Learnable Programming by Bret Victor.

I read it and found some of it interesting, but it seemed rather narrow-minded and dogmatic to me.  Already in the 3rd paragraph, there was a statement ringing alarm bells for me:

People understand what they can see. If a programmer cannot see what a program is doing, she can’t understand it.

If that were really true, then blind people would be incapable of programming, but this is demonstrably false.  Blind programmers may be rare, but they have certainly been around for the last 30–40 years.

If Bret had said “If a programmer cannot imagine what a program is doing, she can’t understand it,” then I would have nodded my head and agreed with him.  But he specifically wants to argue that all programming instruction and perhaps all programming should be visual, a conclusion that I do not support.  I’m not even certain that the visual representations of data that he regards as essential are even helpful.

Other than his insistence on visual modes of thinking and interacting as the only valid modes, he has some pretty good ideas, which he outlines as a set of design principles:

The environment should allow the learner to:

  • read the vocabulary– what do these words mean?
  • follow the flow– what happens when?
  • see the state– what is the computer thinking?
  • create by reacting– start somewhere, then sculpt
  • create by abstracting– start concrete, then generalize

The language should provide:

  • identity and metaphor – how can I relate the computer’s world to my own?
  • decomposition – how do I break down my thoughts into mind-sized pieces?
  • recomposition – how do I glue pieces together?
  • readability – what do these words mean?

One aspect of the “essay” that I found irritating was the frequent embedding of  things that looked like video play buttons, but which did not seem to do anything except disappear when clicked on.  I examined them with Firefox’s “Inspect Element” tool, and found that they were Chrome-specific extensions to make videos.  I viewed a couple of them using the Chrome browser, and found that they just slowed the essay down without adding much to the content.  Still, it seems strange to me that someone who wants to be read would deliberately hide parts of his content in non-standard formats.  Perhaps Bret is more enamored of flashy features than he claims to be, or perhaps he thinks that the flamboyant visual style of his essay is essential to understanding it—I found the extreme typography more an irritant than an aid.

I doubt that Bret would get far as a bioinformatician, since he strongly holds the view that “only visually understandable data is considered sound”, but most of our data is too voluminous to handle with purely visual understanding.  We have to trust abstractions that we can’t see, because there is no way that we can visualize the terabytes or petabytes of data that make up our databases.

Of course, Bret is right that visualizing data is a very powerful metaphor, much more powerful than visualizing programs.  Huge amounts of effort go into coming up with new ways to visualize genomes, interaction graphs, protein structures, signalling pathways, metabolic networks, alignments, and other computational artifacts of bioinformatics. The visualizations are often extremely valuable in viewing small parts of the data.

Better visualizations do allow better views of the data: for example, sequence logos allow a summary view of an alignment with tens of thousands of sequences in it, showing what is conserved through evolution clearly. But viewing all the individual sequences (as earlier visualization tools did) is totally useless.

But visualization of data is just a metaphor, and, like all metaphors, it breaks down sometimes.  Some of the things we deal with frequently (like neural network weight matrices and parameters of SVM machines) are not particularly amenable to visual interpretation, and I would argue that they don’t need to be.  We can understand them well enough without seeing them, and seeing them wouldn’t add to our understanding.

Bret’s essay is an interesting one and worth the time to read, but far from convincing to me.  I don’t want students to “debug a program into existence”, which is essentially what his “create by reacting” and “create by abstracting” processes are. I want students to think before they act, at least much of the time, whereas Bret wants them to think after they act.

Some of the user interface issues he describes are interesting design challenges (like a graphics library designed for auto-completion), but I doubt that the design challenges could be met by a programmer who programmed in pure versions of the “create by reacting” and “create by abstracting” modes that Bret describes.

Next Page »

Theme: Rubric. Blog at WordPress.com.

Follow

Get every new post delivered to your Inbox.

Join 147 other followers

%d bloggers like this: