Greg Wilson wrote a nice piece recently on the big picture for his Software Carpentry course. His first paragraph captures an idea that is key to the notion of "programming for all" that I and others have been talking about lately:
One of the lessons we learned ... is that most scientists don't actually want to learn how to program--they want solve scientific problems. To many, programming is a tax they have to pay in order to do their research. To the rest, it's something they really would find interesting, but they have a grant deadline coming up and a paper to finish.
Most people don't care about programming. If they do care, they don't like it, or think they don't. They want to do something. Programming has to be a compelling tool, something that makes their lives better as they do the thing they like to do. If it changes how they think about problems and solutions, all the better. When we teach programming to people who are non-CS types, we should present it as such: a compelling tool that makes their lives better. If we teach programming qua programming, we will lose them before we have a chance to make a difference for them.
It turns out that all this is true of CS students, too. Most of them want to do something. And several of the lessons Wilson describes for working with scientists learning to program apply to CS students, such as:
This issue is close to the surface for me as I work on my work on my software engineering course. Undergraduate courses don't usually expose students to the kind of software development projects that are likely to give the right context for learning many of the "big picture" ideas. An in-course project can help, but contemporaneous experience often runs out of sync with the software engineering content of the course. Next semester, they will take a project course in which they can apply what they learn in this course, but little good that does us now!
(Idea for later: Why not teach the project course first and follow with course that teaches techniques that depend on the experience?)
Fortunately, most students trust their professors and give them some leeway when learning skills that are beyond their experience to really grok -- especially when the skills and ideas are a known part of the milieu in which they will work.
Software Engineering this semester offers another complication. There is a wide spread in the level of software and programming experience between the most and least experienced students in the course. What appeals to students at one end of the spectrum often won't appeal students on the other. More fun for the professor...
In closing, I note that many of specific ideas from Wilson's course and Udell's conception of computational thinking apply to a good Software Engineering course for majors. (Several of Wilson's extensions to the body of CT apply less well, in part because they are part of other courses in the CS curriculum and in part because they go beyond the CT that every person probably needs.) I should not be surprised that these basic ideas apply. Wilson is teaching a form of software engineering aimed at a specific audience of developers, and computational thinking is really just a distillation of what all CS students should be learning throughout their undergraduate careers!
... two weeks can make.
Then: I do the second week of 4x800m repeats. My times are in the target range, but on the high end. The recoveries are slow and hard. I feel bad for several days afterward.
Now: I do a second week of 5x800m repeats. My times are fast, even below the target range. The recoveries are steady, controlled, and in good time. I am tired that day but otherwise feel good.
Then: I run a 16-miler in rain, wind, and then steamy sun. The run starts badly and gets worse. It is a challenge just to finish. My time is slow, and I feel bad for several days afterward.
Now: I run a 16-miler under a cool sun, with a gentle northern breeze. The run starts on stiff legs but feels good within a mile or so. I feel a spring in my step at 8 miles. I give my pace a little bump at 12 miles. For the last mile, I finish strong and steady, even a little faster. Overall, I run 30 seconds per mile faster than last time. I am tired and stiff, but mentally I feeling good.
Then: 39 miles. I am not sure I will be able to go much higher in the coming weeks.
Now: 40 miles. I'm feeling like I might want to throw in an extra mile in the coming week, though caution talks back. The thought of 18 miles next Sunday sounds like a challenge, not a punishment.
A couple of weeks ago, I must have had a cold or some other bug that slowed me. I've recovered. Right now, I am wondering how to get more sleep. This good habit is coming back more slowly than other training habits. Mostly, though, I feel hope.
A few days ago, I tweeted:
Everything looks worse in black and white.
Including course designs.
It is easy to have fantasies about a new course in the bloom of summer. There are no constraints. I am perfect. My students are perfect. Campus life is perfect. The course is... perfect.
It's important to stop dreaming. But I have never been good at mapping out a new course in its entirety. Beforehand, I'm still learning what I want to say and how to say it. I still need to learn if how I want to say what I think I need to say will work. The best way for me to go is to start teaching.
Before the course starts, I run my own version of the Planning Game. This helps me to develop a high-level picture of the topics I think are essential to cover and the activities I think are essential for students to do. The result is something akin to a System Metaphor and a set of user stories. I prioritize the topics and select the topics that should come at the beginning of the course. This is akin to Release Planning and prepares me for my first release, which is a one-or two-session unit.
Then I implement. Teaching the first week grounds all that thinking I've been doing in reality. The act of meeting the first session, seeing the students, and interacting with them helps me to commit to certain courses of action and gives me a basis for making other decisions as we go along. Initial feedback to a simple survey helps me to prioritize topics.
With a new prep, especially a course outside my usual teaching range, agile course development is even more important for me. Feedback and adaptation are about the only way I can feel confident that the course has a chance to succeed.
While at Agile 2009, I think, Brian Marick tweeted:
1/2: Agile often requires greybeards to admit how much snotty-nosed 20-year-olds have to teach them.
This is true of the agile community, and so it is true for me to the extent that I engage in agile. It is also true of teaching at a university, so it is true for me on another dimension, too. Finding the boundary between where the professor needs to lead where the students need to lead is the key.
One bit of good news from my first week in class. I have reason to believe that this group of students is willing to participate in the daily business of class and, I suspect, in leading when they can and should. That almost always leads to a better course for them, and a better course -- and experience -- for me.
Thinking about teaching software engineering is going to be interesting. I love to make software, and I love to think about it. Now that is more a part of my day job. There is an extra trade-off to make: spending time explicitly preparing for class versus spending time blogging about what I'm thinking along the way!
Mark Guzdial blogged this morning about a bug slipped through into the latest release of JES, the Jython IDE that his group has created to support courses and workshops in media computation. The bug was the result of a simple variable renaming in which n-1 of the uses was changed. (That nth always comes back to haunt us.) Mark uses this bug as an opportunity to discuss some bigger issues involving process, language, and the nature of CS1. He is taking some heat from a couple of pro-Python commenters, but I'm glad he wrote the article. People too rarely share mistakes when they are made, and besides Mark offers some interesting ideas both in his post and in his responses to comments.
Should we use a different kind of language when we program for others than when we program for ourselves? A compiler would have found this simple error at the time JES was built and saved everyone the grief of a new release. But so would running the test suite that the JES team has built. The difference is that developers have a choice of running the test suite or not, whether they use a compiled language or an interpreted one, but they have to compile their program when they use a compiled language.
People make mistakes. I am certainly not in a position to look down on the poor developer who opted not to run the unit tests after making what seemed like a trivial change. I have made similar mistakes before, and I'm sure I'll make another like it soon. And at least one thing is true about teaching university courses: students will find my mistakes!
I like it when a compiler catches errors like this for me, but... Still, I'm uneasy to give up the freedom that a language like Smalltalk, Scheme, or Ruby gives me when I am writing code. Even when the value of Mark's f() rises. What is someone like me to do?
The compiler is a tool that helps me find a certain kind of error. But there are other tools that help me find this and other kinds of error. The unit tests are one. A refactoring browser is another. If the JES developer had had at his or her disposal a refactoring browser for Python, it would have at least been able to point out possible effects of renaming the variable behind this bug. Dynamic languages pose a particular challenge for building really useful static analysis tools, but we can still build tools to help.
But the developer might not use the refactoring browser. The change is so simple, a quick romp in emacs or vi is all we need, right? The compiler is a build tool; the programmer has to run it to create the executable. One approach that developers using dynamic languages can take is to use a build system that always runs the test suite. Another is to tool the version control system to run the tests before accepting the code at check-in. These tools more closely fulfill the role played by the compiler.
In response to another comment on his entry, Mark mentions a trade-off between process and language, a lá the familiar space-time trade-off among algorithms and data structures. This, I think, is the most interesting implication of his post. But the language in which we write code is just one tool that we use in building software. The compiler is another. So are editors, browsers, version control systems, build systems, and testing frameworks. The trade-off is between processes and tools.
This trade-off is one that seems to fly under most people's radar. The authors of the Agile Manifesto wrestle with the trade-off between caring for "individuals and interactions" and caring for "processes and tools". They come down on the side of individuals and interactions. But as I wrote a few weeks ago, valuing people over tools makes having the right tools even more important. I should probably have said "the right tools and process", because the process by which one works is just as important a part of the infrastructure that any programmer or creator needs. The question then becomes: In supporting individuals and interactions, how do we find the right balance between tools and process?
People characterize the different kinds of process available to programmers in a number of ways:
Some people assume that the righthand side of these choices require more discipline than the left, because the lefthand-style processes provide more rules to follow. That's not right. Discipline is, at best, orthogonal to this distinction. I think that the agile, lightweight, and low-ceremony approaches usually require more discipline, not less. In XP, you have to code in pairs, even if you think you don't need to. You have to run the tests. You have to refactor frequently and, on occasion, vigorously. You have to integrate code frequently. You have to take what you learn from all the practices and feed that back into the code. Easy? Not at all. Undisciplined? Not if you are practicing what you preach.
This sort of disciplined approach only works when the practices are at the level of granularity where they can become habit, part of one's muscle memory. It also works well only when supported by tools that make the process comfortable, almost disappear from conscious thought. Good tools shift as much of the burden of details and administrivia off of the programmer's mind and onto the tools that we use to write, build, test, share, and deliver our code.
I understand why many people want to use a compiler to support their process. But I still prefer to use languages that give me other kinds of freedom -- along with other tools that support my creative process.
In my previous entry, I talked about how hard teaching is. When you consider everything -- from the human psychology to human communication, from differences in student background to differences in student temperament, from home life to campus life, oh yeah, and course content -- students and teachers face a big challenge. That's why I liked the pair of Lost in Syntax articles so much. They remind teachers about all of the other things students face. Even people who teach face these challenges when they become students.
Mark Guzdial also blogged after reading "Lost in Syntax". He focused on the source of a particular disconnect that students and teachers may experience in the classroom: what the course content means. Some students want to build things, and for them meaning comes down to a set of practical skills and a set of engineering practices. Some students want to explore, and for them meaning comes down to a different set of practical skills and a way of thinking about questions and experiments. When the instructor of a course adopts one of these stances and uses its language, she connects well with one group of students and often leaves the other group confused and disoriented.
Some people, even a certain kind of university prof, think all this talk of meaning is falderol. You take a course, you learn the content, and you move on. That attitude ignores reality. Even when all the things Wicked Teacher talks about go right, people learn best when they are motivated. And people are most motivated when they know why they are learning what they are learning, and when that "why?" fits the meaning they seek.
The best teachers start (or try to) with what a course means for students and build the learning experience from there. They also start with what the students already know, or think they know, about the course material. By using the students as the baseline for the course, instructors are more able to motivate students and more likely to engage them in a way that creates real learning. When we use the abstractions of our discipline or our own interests as the baseline, we may well teach a course that excites us, but it will often fail to teach students much of anything.
Good teachers start with what a course means for students, but they don't stop there. The teacher's job is to lead students forward, to help students see bigger ideas than they can initially conceive. Even at the level of practical skills and tools, we need to draw students forward to skills and tools they don't yet appreciate when they first enter the class. Starting with what students know and care about is the way that we build the foundation -- and the trust -- they need to learn beyond their imagination. That's what education is.
This is a tall order for any teacher and why I called my previous entry "Teaching is Hard". It is a whole lot easier to build a course atop the discipline's abstractions or one's own interests than to try to understand the students' minds. Even even when we try to start with the students, it is not an easy task.
Some people say that starting anywhere but the intellectual foundation for the discipline is pandering to the students. But starting with student interests and motivations is not pandering at all -- unless we stop there.
Earlier this summer, Wicked Teacher of the West attended a week-long professional development workshop and wrote a two-part reflection on her experience, called "Lost in syntax" [ part 1 | part 2 ]. I have written occasionally here about how useful it is for me as a teacher to be in the learner's shoes every so often in such areas as piano, running, and starting over. Those experiences are analogs, but they require a mapping onto learning computer science. I found Wicked Teacher's reflections especially helpful because she was in the classroom learning CS. I recognize a lot of the symptoms she describes from my students' behaviors in the past. She even captures her bad feelings in a series of object lessons for us teachers.
Great. All I need to do design my course so that it does the right things (such as explaining the big picture) and avoids the obvious pitfalls (such as giving compliments that can be interpreted as indicators of inability), and then watch for signs of problems that are outside my control (such as trouble at home or an unwillingness to ask questions). Simple enough, right?
Right. Much of this is easy in the abstract, but when you get into the rush of the semester, with other courses and other duties tugging at you, a room full of students all in different places, and lots of material to cover in too little time -- well, it suddenly feels a lot harder. Last year, I found myself in the middle of a tough semester and didn't recognize quickly enough that students were not asking questions when they didn't understand. When I am slow to recognize a situation, I am slow to respond. When I am slow to respond, I sometimes miss opportunities to address the issue. Sometimes, I run out of time.
It's a wonder that most teachers don't have the same persistent sense of dread that is expressed in these articles' subtitles: "OMG I'm going to cry in front of all these people".
Still, reflecting in this way -- and reading other peoples' reflections from similar experiences -- is immensely valuable. Simply keeping these lessons in mind over the course of a semester, especially when particular troubles arise, is a good first step toward addressing them in a meaningful way. A little empathy and a little conscious course design can go a long way. The rest is largely a matter of staying alert. I cannot fix every problem or even recognize them all, but paying attention and getting feedback frequently can help me do as well as I can.
I think it is valuable for students to read essays such as Wicked Teacher's. Ultimately, learning is in their hands, and if they can recognize the things that they do which interfere with their own learning, they will be better off. If I can give only one piece of advice from these two reflections, it would be: Ask questions. Ask plenty of questions. Ask them now. Your instructor almost surely wants you to ask. Both of you will be better off if you do.
Yesterday morning, I ran 16 miles, for the first time since training for my 2007 marathon. Historically, this has been a tough distance for me. Up to 12 miles seems easy enough, even when I was first building up. 18 miles and more isn't "easy", but it is long enough to intimidate me a bit; as a result, I run slower and prepare more carefully. Runs of 14-16 miles are caught in middle. Even after a few years experience, there feels like a crossover for me.
My two fourteens so far this year were a mixed bag. The first felt great, and the second did not, though I ran just a touch slower. Yesterday's sixteen was my toughest run in a long time. It was rainy and windy at the outset, and I was struggling by the 2-mile mark. Later the sun came out and warmed things up, with the wind staying strong. My legs were sore throughout. I finished uphill into a headwind. For the next four hours or so, I was in a bit of a daze, sore and tired and unsettled. I finally snapped back and felt good by the end of the day.
Some people think that shorter runs are easy, or at least easier than the long runs. For me there is a crossover point in the 14- to 16-mile range, but even then there is no magic tipping point, where runs go from being easy to a marathon distance being hard. In one sense, all distances are difficult. Yesterday's was less comfortable than I enjoy feeling. It's important to keep in mind that this a key point of training. In order to race a marathon, I need to run when I am tired, to prepare to run when I am tired or sore or uninterested on a race day.
When I'm first building up my mileage, most runs are difficult because of their distance: they make me work more than I am used to working. I am back in this beginner's phase now after a year of diminished capacity. When I'm further along in my training, most runs are hard because I expect more and want to run a faster pace for a longer distance: they make me work harder than I am used to working. Both of these are good preparation for the marathon, when I will want to run a long distance at a faster pace than I usually train at long distances. The idea is to get the body ready for the stresses a marathon will place on it -- and to get the mind ready for the challenge of a goal that stretches me.
I experienced another milestone this week. I have finally worked myself up to a 39-mile week. A number like this often impresses my non-running friends, but when I am healthy and in good shape I like to run 38 miles or more every week -- that's my maintenance mileage, what I do for fun, even throughout the winter. I've been rebuilding my base slowly from ground zero in hopes of staying healthy enough to stay on an upward path. So far, I am doing okay, though the last two weeks have been increasingly tough. By this point in training for a fall marathon, I would usually be at 48-50 miles on my way to a 60-mile or so week. This year, I'll slowly raise my mileage to a max of 48 or so at the beginning of October.
If the rest of my long training runs leave me feeling as I did yesterday, I'll have a question to answer: Will I make it? Right now, I say yes.
I've been thinking a lot about the Software Engineering course I'm teaching this fall, which commences a week from Tuesday. Along the way, I have been looking at a lot of books and articles with "software engineering" in the title. It's surprising how few of them get any where near code. I know I shouldn't be surprised. I remember taking courses on software engineering, and I've stayed close enough to the area all these years to know what matters. There are issues other than programming that we need to think about while building big systems. And there is plenty of material out there about programming and programming tools and the nuts and bolts of programming.
Still, I think it is important when talking about software engineering to keep in mind what the goal is: a working program, or collection of programs. When we forget that, it's too easy to spin off into a land of un-reality. It's also important to keep in mind that someone has to actually write code, or no software will ever be engineered. I hope that the course I teach can strike a good balance.
In the interest of keeping code in mind, I share with you an assortment of programming news. Good, bad, ugly, or fun? You decide.
Hiding the Rainforest. Mark Guzdial reports that Georgia Tech is eliminating yet another language from its computing curriculum. Sigh. Thought experiments notwithstanding, variety in language and style is good for programmers. On a pragmatic note, someone might want to tell the GT folks that programming for the JVM may soon look more like Lisp and feel more like ML than Java or C++.
Programming meets the Age of Twitter. A Processing programming contest with a twist: all programs must be 200-characters or less. I'll give extra credit for any program that is a legal tweet.
Power to the Programmer! Phil Windley enjoys saving $60 by writing his own QIF->CSV converter. But the real hero is the person who wrote Finance::QIF.
Why Johnny Can't Read Perl. Courtesy of Lambda the Ultimate comes news we all figured had to be true: a formal proof that Perl cannot be parsed. Who said the Halting Theorem wasn't useful? I guess I'll stop working on my refactoring browser for Perl.
Via Jason Yip, this dandy story from a hospital president who favors process improvement Lean-style. It features Hideshi Yokoi, who is president of a Toyota production system support center in Kentucky:
... At one point, we pointed out a new information system that we were thinking of putting into place to monitor and control the flow of certain inventory. Mr. Yokoi's wise response, suggesting otherwise, was:
"When you put problem in computer, box hide answer. Problem must be visible!"
I have had many experiences, both personal and professional, in which putting something in a computer hides the problem from view and complicates finding the answer. Too often, when I decide to improve my process by putting data into my computer, I get so caught up in the rest of my tasks that I forget all about the problem. Tasks to do get lost in an ever-growing text file. Concerns about how we allocate merit pay get lost behind complex formulas in a spreadsheet that implement our current method. Scheduling and budget issues are lost in the last-minute details of readying this semester's spreadsheet for the next step in a university we don't control.
When you lose sight of a problem, it's hard to solve it. Moving things out of the daily clutter too easily becomes moving them out of our attention altogether.
I agree with Mr. Yokoi. A problem must be visible! But that cannot mean not using technology to automate and improve a process. Instead it means that we have to find ways to make the problem visible. JUnit was, for me, a great model. We needed to improve how we tested our programs, so we make the tests code. Rather than leave that code sitting lonely on disk, no better than textual documentation, we use a tool that runs the tests for us and tells what passes and what fails. Rather than leave that tool sitting lonely on disk, gathering dust because we forget to run the tests, we build running the tool into our development tools, where the tests can be run every time we save our changes or build our program. Make things visible.
We can avoid much of Mr. Yokoi's valid concern by changing our tools and our practices to ensure that problems don't disappear when we automate processes. That allows us to use computers to make us better.
Last month, in honor of the Apollo 11 mission's fortieth anniversary, Google Code announced the open-sourcing of code for the mission's command and lunar modules. Very cool indeed. This project creates opportunities for many people. CS historians can add this code to their record of computing and can now study computing at NASA in a new way. Grady Booch will be proud. He has been working for many years on the task of preserving code and other historic artifacts of our discipline that revolve around software.
Software archeologists can study the code to find patterns and architectural decisions that will help us understand the design of software better. What we learn can help us do more, just as the Apollo 11 mission prepared the way for future visitors to the moon, such as Charles Duke of Apollo 16 (pictured here).
This code could help CS educators convince a few students to assembly language programming seriously. This code isn't Java or even C, folks. Surely some young people are still mesmerized enough by space travel that they would want to dig in to this code?
As a person who appreciates assembly-level programming but prefers working at a higher level, I can't help but think that it would be fun to reverse-engineer these programs to code at a more abstract level and then write compilers that could produce equivalent assembly that runs on the simulator. The higher-level programs created in this way would be a great way for us to record the architecture and patterns we find in the raw source.
Reading this code and about the project that surrounds it, I am in awe of the scale of the programming achievement. For a computer scientist, this achievement is beautiful. I'd love to use this code to share the excitement of computing with non-computer scientists, but I don't know how. It's assembly, after all. I'm afraid that most people would look at this code and say, "Um, wow, very impressive" while thinking, "Yet another example of how computer science is beyond me."
If only those people knew that many computer scientists feel the same way. We are in awe. At one level, we feel like this is way over our heads, too. How could these programmers done so much with so little? Wow. But then we take a breath and realize that we have the tools we need to dig in and understand how this stuff works. Having some training and experience, we can step back from our awe and approach the code in a different way. Like a scientist. And anyone can have the outlook of a scientist.
When I wonder how could the programmers of the 1960s could have done so much with so little, I feel another emotion, too: sheepishness. How far have we as a discipline progressed in forty years? Stepping back from the sheepishness, I can see that since that time programmers have created some astoundingly complex systems in environments that are as harsh or harsher than the Apollo programmers faced. It's not fair to glorify the past more than it deserves.
But still... Wow. Revisiting this project forty years later ought to motivate all of us involved with computer science in 2009 -- software professionals, academics, and students -- to dream bigger dreams and tackle more challenging projects.
The software engineering tip Every line of code is a user interface expresses several important ideas. Design matters. Names matter. Separating business logic from system wiring matters. Programs are read by people, so the code you write matters.
As I think about it, though, it embodies another important idea that is right up agile development's alley. We all know that programs tend to evolve over time, as user's needs and wants change. As developers, we also know that, as we build more systems in the same domain, we can evolve one-off programs toward a common framework. The framework generalizes over the separate programs, pulling the wiring out for maintenance in one place and for use in creating new programs in the same domain later.
What's interesting to me about the police database system described in that article is that it needed to evolve away from its built-in wiring and toward a more generic framework created in the outside world:
Specifically it wasn't Microsoft Access we had to worry about, but Ruby on Rails that provided 99% of all the infrastructure we'd built ourselves for an HTML-fronted database application.
It didn't have to be Rails, because web frameworks in other languages would probably have done as well for their shop. The point is, when the frameworks came along, their code was too tangled to easily take advantage of them. On the business side, another company could come along, replicate the business logic on top of one of the frameworks that provided the 99% infrastructure, and compete right away.
Is your design clean enough?
I mentioned David Ogilvy's Confessions of an Advertising Man in a recent entry. Another passage from the book set of the alarm in my brain that watches for examples of shorter-than-usual iterations and continuous feedback:
Most young men in big corporations behave as if profit were not a function of time. When Jerry Lambert scored his first breakthrough with Listerine, he speeded up the whole process of marketing by dividing time into months. Instead of locking himself into annual plans, Lambert reviewed his advertising and his profits every month.
I guess that Lambert wasn't satisfied with halving his project length; he went straight to a factor of twelve. Feedback matters in the advertising game. In the same chapter of Confessions, Ogilvy talks about the importance of testing campaigns in front of real users. He claims that 24 out of 25 ideas will fail, so it's better to find out in testing than in production -- which both costs more and exposes the company to public failure. (Reputation matters a lot in the advertising game.)
Lambert's approach went further by monitoring projects that had already been deployed on a much shorter cycle and making decisions based on more frequent feedback about the projects. This reminded me of the approach suggested by Ricardo Semler in his talk Leading by Omission. Semler says that long-term plans, even yearly plans, are simply too large-grained to be useful. He advocates continuous feedback and monitoring.
Time is related to evolution, of course. When we operate at smaller units of time, we can evolve -- through both failure and success -- that much faster.
You don't need (or have to be) a special kind of leader, which Lambert and Semler seem to be, to benefit from this style. A disciplined process such as XP can guide you, and a team of developers operating from a set of agile principles can work to achieve similar goals.
In my entry about advice on my advice to students interested in web development, I quoted an alum who dared suggest that undergrads study one language in depth for four years. This seems extreme to me, but it is often useful to examine the axioms on which we base our curricula. Wade's idea fits well with the idea that we would like to teach students enough that they can scratch an itch. I think that this approach overvalues what we can learn from a single language, and any language that takes four years to master is probably the wrong language for undergrads. Even if we accept that our goal is to help students scratch their own itches in the service of motivation, can't we do better? I think so.
My goal here is not to add to the seemingly endless cacophony about which first language(s) we should use in CS1. But I was impressed by a comment Terry Chay made on the entry of his to which I linked in my "itch to scratch" post, about textbooks. Although he is a proponent of PHP for web development, he argues that it isn't suitable for people learning their first programming language. One of the reasons is the the best books about PHP assume too much background.
Consider Welling and Thomson's PHP and MySQL Web Development. It is about web programming and so assumes that students are familiar with HTML, starting and restarting Apache, activating PHP, installing and setting up MySQL, and all the editor- and OS-specific details of writing, storing, and running scripts. That's a lot of hidden prerequisites, and it is one of the challenges we face anytime we try to embed CS1 in a context. Context is context, and students have to have it before they move on.
However, Chay claims that, after its first chapter, PHP and MySQL Web Development "offers more 'immersion' gratification (at the least cost) than any other language's textbook." But it's too late. The first chapter is what beginners see first and what they must make sense of before moving on. Unfortunately,
It's that first chapter that does the first timer in.
Many people who don't teach CS1 and who have never tried writing for that audience underestimate just how important this is, and just how difficult an obstacle it is to overcome. I occasionally see really good books about programming written to solve problems in a specific domain or context that might work well for beginners -- but only as a second course, after someone has taught a course that gets them through the introduction.
Right now I have examination copies of three books sitting on my desk or desktop that are relevant to this discussion.
I'm disappointed that I haven't taken the time to study these in detail. I am familiar with drafts of Practical Programming after having reviewed them in the books early stages and know it to be a well-written book. But that's not enough to say whether it works as well as I hope. Severance's book also promises big things, but I need to dig deeper to see how well it works. O'Kane's looks like the most traditional CS1 book of the bunch, with a twist: if-statements don't arrive until Chapter 7, and loops until Chapter 9.
Gotta make time! But then there is my own decidedly non-freshman course to think about. Fifteen days and counting...
An Addition to My News Aggregator
Thanks to John Cook, I came across the blog of Dan Meyers, a high school math teacher. Cook pointed to an entry with a video of Meyer speaking pecha kucha-style at OSCON. One of the important messages for teachers conveyed in this five minutes is Be less helpful. Learning happens more often when people think and do than when they follow orders in a well-defined script.
While browsing his archive I came across this personal revelation about the value of the time he was spending on his class outside of the business day:
I realize now that the return on that investment of thirty minutes of my personal time isn't the promise of more personal time later. ... Rather it's the promise of easier and more satisfying work time now.
Time saved later is a bonus. If you depend on that return, you will often be disappointed, and that feeds the emotional grind that is teaching. Kinda like running in the middle. I think it also applies more than we first realize to reuse and development speed in software.
Learning and Doing
One of the underlying themes in Meyers's writing seems to be the same idea in this line from Gerd Binnig, which I found at Physics Quote of Day:
Doing physics is much more enjoyable than just learning it. Maybe 'doing it' is the right way of learning ....
Programming can be a lot more fun than learning to program, at least the way we often try to teach it. I'm glad that so many people are working on ways to teach it better. In one sense, the path to better seems clear.
Knowing and Doing
One of the reasons I named by blog "Knowing and Doing" was that I wanted to explore the connection between learning, knowing, and doing. Having committed to that name so many years ago, I decided to stake its claim at Posterous, which I learned about via Jake Good. Given some technical issues with using NanoBlogger, at least an old version of it, I've again been giving some thought to upgrading or changing platforms. Like Jake, I'm always tempted to roll my own, but...
I don't know if I'll do much or anything more with Knowing and Doing at Posterous, but it's there if I decide that it looks promising.
A Poignant Convergence
Finally, a little levity laced with truth. Several people have written to say they liked the name of my recent entry, Sometimes, Students Have an Itch to Scratch. On a whim, I typed it into Translation Party, which alternately translates a phrase from English into Japanese and back until it reaches equilibrium. In only six steps, my catchphrase settles onto:
Sometimes I fear for the students.
Knowing how few students will try to scratch their own itches with their new-found power as a programmer, and how few of them will be given a chance to do so in their courses on the way to learning something valuable, I chuckled. Then I took a few moments to mourn.
An excerpt from an interview at Gaping Void:
Some days, the work is tedious, labour-intensive and as repetitive as a production line in a factory. ... The key is having a good infrastructure. ...
But none of it works without discipline. Early on in my career, I was told that success demanded one thing above all others: turning up. Turning up every bloody day, regardless of everything.
This was said by artist Hazel Dooney, but it could just as well been said by a programmer -- or a university professor. One thing I love about the agile software world is its willingness to build new kinds of tools to support the work of programmers. Isn't it ironic? Valuing people over tools makes having the right tools even more important.
His indecision about careers and school is worthy of its own post; I've seen it in so many other 20- and 30-somethings who are unhappy with their first careers and not sure of where to go next.
Many advisees, traditional and non-traditional students alike, seem to want me -- or anyone, for that matter -- to tell them what to do. Which major should I choose? Which classes should I take? This can be a healthy sort of questioning. One of the roles played by university professors is that of academic advisor, in which we help students explore and develop their interests, refine their goals, and choose a path that will help them. Most of us really like this part of our jobs, and it tends to be underutilized by students.
These same questions can also indicate an unhealthy need for answers. Some students seem to want to surrender the power of choice, and the responsibility that comes with wrong choices. We do the world a huge disservice if our schools or culture create a significant number of young people so unable to control their own destiny, unwilling even to try.
In retrospect, I probably should not write a whole post on this topic. I have no expertise or special insight. Maybe what I report here is not a significant problem, merely the result of a sampling bias or a memory bias. But it feels like a pattern, and sometimes it concerns me.
The real reason I decided not to write much more on this was a response sent to me by a computer science alumnus of ours, David Schmüdde. David is not a professional computer scientist; he is a filmmaker, composer, and teacher, not to mention a blogger worth following. (I mentioned his senior project in a long-ago blog entry.) His e-mail message did not deal with the technical details of my request for advice. It was a personal essay on his experiences learning to program at my university, on studying with me, and on now teaching college students. He reminded me that interest and aptitude are not enough. Students also need confidence that they can succeed and the will to commit to the present moment. All the aptitude in the world can be diluted to nothingness by a lack of confidence or a lack of commitment.
What role does the professor play in this? They can inspire trust. As David wrote, it is really hard for people to hand over two or four years of their lives to a university, even to a program of study. They need to be able trust that what they are doing is worthwhile and has a reasonable chance of leading to happiness or some other form of success.
As much as we like to build up our departments and universities in the eyes of the world, we must remember that people do not trust schools. Not really. They trust people. Sometimes the people they trust are parents or friends or teachers from their high schools. But when committing to a course of study in college, often the people they need to trust are the faculty. The advisors they see at summer orientation. The professors they meet when they seek out more advice. The instructors they see in the classroom.
David hoped that his message would not come across as if he were lecturing me, because surely much of what he was saying must have occurred to me before. Sure, but as I write here on occasion, I often need to be reminded. In this case, I needed to be reminded that what we professors do is not just technical. Perhaps it's not even mostly technical. It's about helping people to grow. Every once in a while, it is good for me to have someone tell me to step back and look at what matters. Thanks to David for taking the time to write me a letter doing just that.
So perhaps the best thing I can do for students who seeks so much direction is to recognize their lack of confidence as natural to the human condition, work to build their trust, and then try to assure them that their efforts will bear fruit -- maybe not the fruit they expect when they start, but fruit worthy of the effort. The key is to commit to a course of action and invest one's mind in it.
What a good time to be having this conversation, with a new academic year on its way!
Thanks to everyone who responded to my call for advice on what advice I should give to a student interested in studying at the university with a goal of becoming a web developer. People interpreted the article in lots of different ways and so were able to offer suggestions in many different ways.
In general, most confirmed the gist of my advice. Learn a broad set of technical skills from the spectrum of computer science, because that prepares one to contribute to the biggest part of the web space, or study design, because that's they part the techies tend to do poorly. A couple of readers filled me in on the many different kinds of web development programs being offered by community colleges and technical institutes. We at the university could never compete in this market, at least not as a university.
Mike Holmes wrote a bit about the confusion people have about computer science, with a tip of the hat to Douglas Adams. This confusion does play a role in prospective students' indecision about pursuing CS in college. People go through phases where they think of the computer as replacing an existing technology or medium: calculator, typewriter and printing press, sketchpad, stereo, television. Most of us in computer science seem to do one of two things: latch onto the current craze, or stand aloof from the latest trend and stick with theory. The former underestimates what computing can be and do, while the latter is so general that we appear not to care about what people want or need. It is tough to balance these forces.
In some twittering around my request, Wade Arnold tweeted about the technical side of the issue:
@wallingf Learn Java for 4 years to really know one language well. Then they will pick up php, ruby, or python for domain specific speed
The claim is that by learning a single language really well, a person really learns how to program. After that, she can learn other languages and fill in the gaps, both language-wise and domain-wise. This advice runs counter to what many, many people say, myself included: students should learn lots of different languages and programming styles in order to really learn how to program. I think Wade agrees with that over the long term of a programmer's career. What's unusual in his advice is the idea that a student could or should spend all four years of undergrad study mastering one language before branching out.
A lot of CS profs will dismiss this idea out of hand; indeed, one of the constant complaints one hears in certain CS ed circles is that too many schools have "gone Java" to the exclusion of all other languages and to the lasting detriment of their students. My department's curriculum has, since before I arrived, required students to study a single language for their entire first year, in an effort to help students learn one language well enough that they learn how to program before moving on to new languages and styles. When that language was, say, Pascal, students could pretty well learn the whole language and get a lot of practice using it. C is simple enough for that purpose, I suppose, but C++, Ada, and Java aren't. If we want students to master those languages at a comparable level, we might well need four years. I think that says more about the languages we use than about students learning enough programming in a year to be ready to generalize and fill in gaps with new languages and styles.
This entry has gotten longer than I expected, yet I have more to say. I'll write more in the days to come.
Mark Guzdial recently wrote:
It's interesting is how the contextualized approach [to teaching intro CS] impacted future student choice. Did we convince students that computing is interesting? I don't think so. Instead, we convinced students that computing was relevant to the things that they already had value for, that it had utility for them. Thus, we had students who were willing to take "More Media Computation" classes (as long as we kept explaining the utility), but not "More Computer Science" classes.
This came back to mind while I was reading Terry Chay's 5 million, which was recommended to me by alumnus Tony Bibbs in response to my recent request for assistance. While discussing how to recommend what language programmers should learn first, Chay wrote something in the same vein. I have cleaned up what I assume to be a typographical glitch in what he posted:
You know you can learn it in a classroom, but immersion is a much faster way to learn.
The best way to learn to program is to have an itch that needs scratching.
Together, these passages brought to mind advice that Alistair Cockburn once gave for introducing agile software development ideas into an organization. I recall his advise as this: Don't go into an organization talking about your solutions. Ask them about the problems they are having producing software. What causes them pain? Then look for a change they could make that would reduce or eliminate the pain. Often times, an agile practice will be the ticket, and this will serve as an opportunity to help them do something that helps them, not something that merely pulls a play from the playbook you are trying to sell.
I once ran across a quote on a blog at JavaRanch that seems not to exist anymore> which talked about the change in mindset that should accompany adopting Alistair's advice:
Changing other people in ways that I deem appropriate, that's hard. Asking people how they want to change, and how I can help them change, that's easy. Why don't I do more of the latter?
Those of us who teach students to program and who hope to attract creative and interested minds to CS cannot rely just on scratching the itches that students have, but that does seem like a useful prong in a multi-pronged effort. As Mark points out, many students interested in programming within a context are really interested in that context, not in programming or CS more generally. That's okay. Teaching a broad set of people how to do media computation is valuable on its own. But there are students like the ones Terry Chay describes who will immerse themselves in programming to scratch their own itches and then find they want to go deeper or broader than the one context.
Even with all the thinking out loud I do here, I am not sure yet which students will be the ones who go all the way with CS or how we can begin to identify them. Perhaps the best thing we can do is to draw them in with their own interests and see what happens. Teaching a generic, CS-centric intro sequence is not the best way to reach all students, even the ones who come in thinking they want to do CS. Empowering students to solve problems that matter to them seems like a promising way for us to approach the issue.
One reader commented on my CS/basketball fantasy that a CS1 course built around an obsession with sports would be a frivolous waste of time. That is probably true, but I have seen a fair number of students over the years in our CS1 courses and in Basic programming courses who invested significant numbers of hours into writing programs related to football, baseball, and basketball. I'm glad that those students engaged themselves with a programming language and set out to solve problems they cared about. If I could engage such students with my assignments, that would be an excellent use of our time in class, not a frivolous waste. I may not want to build an entire course around a particular student's interest in ranking NFL teams, but I am always looking for ways to incorporate student interests into what we need to do anyway.
Among other things, teachers need to keep in mind that students have itches, too. It never hurts to ask them every once in a while what those itches are.
I have been reading David Ogilvy's Confessions of an Advertising Man. I have found it to be quite enjoyable. It is a slim volume, written charmingly in a style we don't see much anymore. It is about not only advertising but also leading a team, creating and guiding an organization, and running a business. There are elements of all these is my job as department head, and even as a faculty member. Many of Ogilvy's essons won't surprise you; he recommends the old-fashioned virtues. Hard work. Quality. Fairness. Honesty. Integrity. High standards. Candor.
Ogilvy describes how to build and run a great agency, but at heart he is a great believer in the individual, especially when it comes to creative acts:
Some agencies pander to the craze for for doing everything in committee. They boast about "teamwork" and decry the role of the individual. But no team can write an advertisement, and I doubt whether there is a single agency of any consequence which is not the lengthened shadow of one man.
I sometimes wonder whether greatness can be achieved by a group of competent or even above-average individuals, or if an outstanding individual is an essential ingredient. In an advertising agency, there are the somewhat distinct acts of creating campaigns and running the agency. Perhaps the latter is more amenable to being led by a team. But even when it comes to great works, I am aware that teams have produced excellent software. How much of that success can be attributed to the vision and leadership of one individual on the team, I don't know.
As I mentioned at the top of a recent entry, a university task force I chaired submitted its final report at the beginning of July. After working so long with this group, I am feeling a little seller's remorse. Did we do a good enough job? If acted upon, will our recommendations effect valuable change? Can they be acted upon effectively at a time of budget uncertainties? The report we wrote does not advocate revolutionary change, at least not on the surface. It is more about creating structures and practices that will support building trust and communication. In a community that has drifted in recent years and not always had visionary leadership, these are prerequisites to revolutionary changes. Still, I am left wondering what we might have done more or differently.
The report is most definitely the product of a committee. I suspect that several of the individuals in the group might well have been able to produce something as good or better by working solo, certainly something with sharper edges and sharper potential -- at higher risk. Others on the group could not have done so, but that was not the nature of their roles. In the end, the committee rounded off the sharp edges, searched for and found common ground. The result is not a least common denominator, but it is no longer revolutionary. If that sort of result is what you need, a committee is not your best agent.
Part of my own remorse comes back to Ogilvy's claim. Could I have led the group better? Could I have provided a higher vision and led the group to produce a more remarkable set of recommendations? Did I cast a long enough shadow?
The shadows of summer are lengthening. One of the reasons that I have always liked living in the American Midwest is the changing of the seasons. Here we have not four seasons but eight, really, as the blending of summer to autumn, or winter to spring, each has its own character. Academia, too, has its seasons, and they are part of what attracted me to professional life at a university. From the outside looking in, working in industry looked like it could become monotonous. But the university offers two semesters and a summer, each with a brand new start, a natural life, and a glorious end. Whatever monotony we experience happens at a much larger time scale, as these seasons come and go over the years.
Like the weather, academia has more than the obvious seasons we name. We have the break between semesters over Christmas and New Year's Day, a short period of change. When school ends in May, it is like the end of the year, and we have a period of changing over to a summer of activity that is for many of us much different than the academic year. And finally, we have the transition between summer and the new academic year. For me, that season begins about now, on the first day of August, as thoughts turn more and more to the upcoming year, the preparation of classes, and the return of students. This is a change that injects a lot of energy into our world and saves us from any monotony we might begin to feel.
So, as the long shadows of summer begin to fall, we prepare for the light of a new year. What sort of shadow will I cast?