... an author never does more damage to his readers
than when he hides a difficulty.
-- Évariste Galois
Like many of the aphorisms we quote for guidance, this one is true, but not quite true if taken with the wrong sense of its words or at the wrong scale.
First, there are different senses of the word "difficulty". Some difficulties are incidental, and some are essential. An author should indeed hide incidental difficulties; they only get in the way. However, the author must not hide essential difficulty. Part of the author's job is to help the readers overcome the difficulty.
Second, we need to consider the scale of revelation and hiding. Authors who expose difficulties too soon only confuse their readers. Part of the author's job is to prepare the reader, to explain, inspire, and lead readers from their initial state into a state where they are ready to face the difficulty. At that moment, the author is ready to bring the difficulty out into the open. The readers are ready.
What if the reader has already uncovered the difficulty before meeting the author? In that time, the author must not try to hide it, to fool his readers. He must attack it head on -- perhaps with the same deliberation in explaining, inspiring, and leading, but without artifice. It is this sense in which Galois has nailed a universal truth.
If we replace "author" with "teacher" in this discussion we still have truths. The teacher's job is to eliminate incidental difficulties while exposing essential ones. Yet the teacher must be deliberate, too, and prepare the reader, the student, to overcome the difficulty. Indeed, a large part of the teacher's craft is the judicious use of simplification and unfolding, leading students to a deeper understanding.
Sometimes, we teachers can use difficulty to our advantage. As I discussed recently, the brain often learns best when it it encounters its own limitations. Some say that is the only way we learn, but I don't think I believe the notion when taken to this extreme. But I think that difficulty is often the teacher's best source of leverage. Confront students with difficulty, and then help them to find resolution.
Ben Blum-Smith expresses a similar viewpoint in his recent nugget on teaching students to do proofs in mathematics. He launches his essay with remarks by Paul Lockhart, whose essay I discussed last summer. Blum-Smith's teaching nugget is this:
The impulse toward rigorous proof comes about when your intuition fails you. If your intuition is never given a chance to fail you, it's hard to see the point of proof.
This is just as true for us as we learn to create programs as it is when we learn to create proofs. If our intuition and our current toolbox never fail us, it's hard to see the point of learning a new tool -- especially one that is difficult to learn.
Blum-Smith then quotes Lockhart:
Rigorous formal proof only becomes important when there is a crisis -- when you discover that your imaginary objects behave in a counterintuitive way; when there is a paradox of some kind.
This quote doesn't inspire cool thoughts in me the way so many other passages in Lockhart's paper do, but one word stands way out on this reading: crisis. It inspires Blum-Smith as well:
... what happens is that when kids reach a point in their mathematical education where they are asked to prove things, they find
- that they have no idea how to accomplish what is being asked of them, and
- that they don't really get why they're being asked to do it in the first place.
The way out of this is to give them a crisis. We need to give them problems where the obvious pattern is not the real pattern. What you see is not the whole story! Then, there is a reason to prove something.
We need to give our programming students problems in which the obvious solution, the solution that flows naturally from their fingers onto the keyboards, doesn't feel right, or maybe even doesn't work at all. There is more to the story; there is reason to learn something new.
Teachers who know a lot and can present useful knowledge to students can be quite successful, and every teacher really needs to be able to play this role sometime. But that is not enough, especially in a world where increasingly knowledge is a plentiful commodity. Great teachers have to know how to create in the minds of their students a crisis: a circumstance in which they doubt what they know just enough to spur the hard work needed to learn.
A good writer can do this in print, but I think that this is a competitive advantage available to classroom teachers: they operate in a more visceral environment, in which one can create safe and reliably effective crises in their students minds. If face-to-face university courses with domain experts are to thrive in the new, connected world, it will be because they are able to exploit this advantage.
~~~~
Postscript: Galois, the mathematician quoted at the top of this article, was born on October 25. That was the date of one of my latest confrontations with difficulty. Let me assure you: You can run, but you cannot hide!
One of the fun parts of teaching software engineering this semester has been revisiting some basic patterns in the design part of the course, and now as we discuss refactoring in the part of the course that deals with implementation and maintenance. 2009 is the 15th anniversary of the publication of Design Patterns, the book that launched software patterns into the consciousness of mainstream developers. Some folks reminisced about the event at OOPSLA this year, but I wasn't able to make it to Orlando. OOPSLA 2004 had a great 10th-anniversary celebration, which I had the good fortune to attend and write about.
I wasn't present at OOPSLA in 1994, when the book created an unprecedented spectacle in the exhibit hall; that just predates my own debut at OOPSLA. But wish I had been!
InformIT recently ran a series of interviews with OO and patterns luminaries, sharing their thoughts on the book and on how patterns have changed the landscape of software development. The interview with Brian Foote had a passage that I really liked:
InformIT: How has Design Patterns changed your impressions about the way software is built?
The vision of reuse that we had in the object-oriented community in hindsight seems like a God that Failed. Just as the Space Shuttle never lived up to its promised reuse potential, libraries, frameworks, and components, while effective in as far as they went, never became foundations of routine software reuse that many had envisioned and hoped.
Instead, designs themselves, design ideas, patterns became the loci of reuse. We craft our ideas, by hand, into each new artifact we build.
This insight gets to the heart of why patterns matter. Other forms of reuse have their place and use, but they operate at a code level that is ultimately fragile in the face of the different contexts in which our programs operate. So they are, by necessity, limited as vehicles for reuse.
Design ideas are less specific, more malleable. They apply in a million contexts, though never in quite the same way. We mold them to the context of our program. The patterns we see in our designs and tests and implementations give us the abstract raw material out of which to create our programs. We still strive for reuse, but at a different level of thinking and working.
Read the full interview linked above. It is typical Brian Foote: entertaining and full of ideas presented slightly askew from the typical vantage point. That twist helps me to think differently about things that may have otherwise become commonplace. And as so often happens, I had to look a word up in the dictionary before I reached the end. I always seem to learn something from Brian!
Yesterday I introduced refactoring in my software engineering course. Near the beginning of my code demo, I got sidetracked a bit when I mentioned that I would be using JUnit to run some automated tests. We have not talked about testing yet, automated or otherwise, and I thought that refactoring might be a good way to show its value.
One student wondered why he should go to the trouble; why not just write a few lines of code to do his own testing? My initial response turned too quickly to the idea of automation, which seemed natural given the context of refactoring. Automating tests is essential when we are working in a tight cycle of code-test-refactor-test. This wasn't all that persuasive to the student, who had not seen us refactor yet. Fortunately, another student, who has used testing frameworks at work, jumped in to point out the real flaw in what the first student had proposed: interspersing test code and production code. I think that was more persuasive to the class, and we moved on.
That got me to thinking about a different way to introduce both testing frameworks and refactoring next time. The key pedagogical idea is to focus on students' current experience and why they need something new. Necessity gives birth not only to invention but also to the desire to learn.
Somedays, I think the web is magic. This popped into newsfeed when I refreshed this morning:
whenever possible, introduce new skills and new knowledge as the solution to the limitations of old skills and old knowledge
Meyer, who teaches HS math, has a couple of images contrasting the typical approach to lesson planning (introduce concept, pay "brief homage to workers who use it", work sample problems) to an approach based on the limitations of old skills:
I like to teach design patterns using a more active version of this approach:
I need to remember to use this strategy with more of the new skills and techniques. It's hard to do this in the small for all techniques, but when I can tie the new idea to an error students make or a difficulty they have, I usually have better success. (My favorite success story with this approach was helping students to learn selection patterns -- ways to use if statements -- in CS1 back in the mid-1990s.)
A few years ago I blogged when my university colleague Roy Behrens won a faculty excellence award in his home College of Humanities and Fine Arts. That entry, Teaching as Subversive Inactivity, taught me a lot about teaching, though I don't yet practice it very well. Later, I blogged about A Day with Camouflage Scholars, when I had the opportunity to talk about how a technique of computer science, steganography, related to the idea of camouflage as practiced in art and the military. Behrens is an internationally recognized expert on camouflage who organized an amazing one-day international conference on the subject here at my humble institution. To connect with these scholars, even for a day, was a great thrill. Finally, I blogged about Feats of Association when Behrens gave a mesmerizing talk illustrating "that the human mind is a connection-making machine, an almost unwilling creator of ideas that grow out of the stimuli it encounters."
As you can probably tell, I am a big fan of Behrens and his work. Today, I had a new chance to hear him speak, as he gave a talk associated with his winning another award, this time the university's Distinguished Scholar Award. After hearing this talk, no one could doubt that he is a worthy recipient, whose omnivorous and overarching interest in camouflage reflects a style of learning and investigation that we could all emulate. Today's talk was titled "Unearthing Art and Camouflage" and subtitled my research on the fence between art and science. It is a fence that more of us should try to work on.
The talk wove together threads from Roy's study of the history and practice of camouflage with bits of his own autobiography. It's a style I enjoyed in Kurt Vonnegut's Palm Sunday and have appreciated at least since my freshman year in college, when in an honors colloquium at Ball State University I was exposed to the idea of history from the point of view of the individual. As someone who likes connections, I'm usually interested in how accomplished people come to do what they do and how they make the connections that end up shaping or even defining their work.
Behrens was in the first generation of his family to attend college. He came from a small Iowa town to study here at UNI, where he first did research in the basement of the same Rod Library where I get my millions. He held his first faculty position here, despite not having a Ph.D. or the terminal degree of discipline, an M.F.A. After leaving UNI, he earned an M.A. from the Rhode Island School of Design. But with a little lucky timing and a publication record that merited consideration, he found his way into academia.
From where did his interest in camouflage come? He was never interested in military, though he served as a sergeant in the Vietnam-era Marine Corps. His interest lay in art, but he didn't enjoy the sort of art in which subjective tastes and fashion drove practice and criticism. Instead, he was interested in what was "objective, universal, and enduring" and as such was drawn to design and architecture. He and I share an interest in the latter; I began mu undergraduate study as an architecture major. A college professor offered him a chance to do undergraduate research, and his result was a paper titled "Perception in the Visual Arts", in which he first examined the relationship between the art we make and the science that studies how we perceive it. This paper was later published in major art education journal.
That project marked his first foray into perceptual psychology. Behrens mentioned a particular book that made an impression on him, Aspects of Form, edited by Lancelot Law Whyte. It contained essays on the "primacy of pattern" by scholars in both the arts and the sciences. Readers of this blog know of my deep interest in patterns, especially in software but in all domains. (They also know that I'm a library junkie and won't be surprised to know that I've already borrowed a copy of Whyte's book.)
Behrens noted that it was a short step from "How do people see?" to "How are people prevented from seeing?" Thus began what has been forty years of research on camouflage. He studies not only the artistic side of camouflage but also its history and the science that seeks to understand it. I was surprised to find that as a RISD graduate student he already intended to write a book on the topic. At the time, he contacted Rudolf Arnheim, who was then a perceptual psychologist in New York, with a breathless request for information and guidance. Nothing came of that request, I think, but in 1990 or so Behrens began a fulfilling correspondence with Arnheim that lasted until his death in 2007. After Arnheim passed away, Behrens asked his family to send all of his photos so that Behrens could make copies, digitize them, and then return the originals to the family. They agreed, and the result is a complete digital archive of photographs from Arnheim's long professional life. This reminded me of Grady Booch's interest in preservation, both of the works of Dijkstra and of the great software architectures of past and present.
While he was at RISD, Behrens did not know that the school library had 455 original "dazzle" camouflage designs in its collection and so missed out on the opportunity to study them. His ignorance of these works was not a matter of poor scholarship, though; the library didn't realize their significance and so had them uncataloged on a shelf somewhere. In 2007, his graduate alma mater contacted him with news of the items, and he has now begun to study them, forty years later.
As grad student, Behrens became in interested in the analogical link between (perceptual) figure-ground diagrams and (conceptual) Venn diagrams. He mentioned another book that helped him make this connection, Community and Privacy, by Serge Chermayeff and Christopher Alexander, whose diagrams of cities and relationships were Venn diagrams. This story brings to light yet another incidental connection between Behrens's work and mine. Alexander is, of course, the intellectual forebear of the software patterns movement, through his later books Notes On The Synthesis Of Form, The Timeless Way Of Building, A Pattern Language, and The Oregon Experiment.
UNI hired Behrens in 1972 into a temporary position that became permanent. He earned tenure and, fearing the lack of adventure that can come from settling down to soon, immediately left for the University of Wisconsin-Milwaukee. He worked there ten years and earned his tenure anew. It was at UW-M where he finally wrote the book he had begun planning in grad school. Looking back now, he is embarrassed by it and encouraged us not to read it!
At this point in the talk, Behrens told us a little about his area of scholarship. He opened with a meta-note about research in the era of the world wide web and Google. There are many classic papers and papers that scholars should know about. Most of them are not yet on-line, but one can at least find annotated bibliographies and other references to them. He pointed us to one of his own works, Art and Camouflage: An Annotated Bibliography, as an example of what is now available to all on the web.
Awareness of a paper is crucial, because it turns out that often we can find it in print -- even in the periodical archives of our own libraries! These papers are treasures unexplored, waiting to be rediscovered by today's students and researchers.
Camouflage consists of two primary types. The first is high similarity, as typified by figure-ground blending in the arts and mimicry in nature. This is the best known type of camouflage and the type most commonly seen in popular culture.
The second is high difference, or what is often called figure disruption. This sort of camouflage was one of the important lessons of World War I. We can't make a ship invisible, because the background against which it is viewed changes constantly. A British artist named Norman Wilkinson had the insight to reframe the question: We are not trying to hide a ship; we are trying to prevent the ship from being hit by a torpedo!
(Redefining one problem in terms of another is a standard technique in computer science. I remember when I first encountered it as such, in a graduate course on computational theory. All I had to do was find a mapping from a problem to, say, 3-SAT, and -- voilá! -- I knew a lot about it. What a powerful idea.)
This insight gave birth to dazzle camouflage, in which the goal came to be break an image into incoherent or imperceptible parts. To protect a ship, the disruption need not be permanent; it needed only to slow the attackers sufficiently that they were unable to target it, predict its course, and launch a relatively slow torpedo at it with any success.
Behrens offered that there is a third kind of camouflage, coincident disruption, that is different enough to warrant its own category. Coincident disruption mixes the other two types, both blending into the background and disrupting the viewer's perception. He suggested that this may well be the most common form of camouflage found in nature using the Gabon viper, pictured here, as one of his examples of natural coincident disruption.
Most of Behrens' work is on modern camouflage, in the 20th century, but study in the area goes back farther. In particular, camouflage was discussed in connection to Darwin's idea of natural selection. Artist Abbott Thayer was a preeminent voice on camouflage in the 19th century who thought and wrote on both blending and disruption as forms in nature. Thayer also recommended that the military use both forms of camouflage in combat, a notion that generated great controversy.
In World War I, the French ultimately employed 3,000 artists as "camoufleurs". The British and Americans followed suit on a smaller scale. Behrens gave a detailed history of military camouflage, most of which was driven by artists and assisted by a smaller number of scientists. He finds World War II's contributions less interesting but is excited by recent work by biologists, especially in the UK, who have demonstrated renewed interest in natural camouflage. They are using empirical methods and computer modeling as ways to examine and evaluate Thayer's ideas from over a hundred years ago. Computational modeling in the arts and sciences -- who knew?
Toward the end of his talk, Behrens told several stories from the "academic twilight zone", where unexpected connections fall into the scholar's lap. He called these the "unsung delights of researching". These are stories best told first hand, but they involved a spooky occurrence of Shelbyville, Tennessee, on a pencil he bought for a quarter from a vending machine, having the niece and nephew of Abbott Thayer in attendance at a talk he gave in 1987, and buying a farm in Dysart, Iowa, in 1992 only then to learn that Everett Warner, whom he had studied, was born in Vinton, Iowa -- 14 miles away. In the course of studying a topic for forty years, the strangest of coincidences will occur. We see these patterns whether we like to or not.
Behrens's closing remarks included one note that highlights the changes in the world of academic scholarship that have occurred since he embarked on his study of camouflage forty years ago. He admitted that he is a big fan of Wikipedia and has been an active contributor on pages dealing with the people and topics of camouflage. Social media and web sites have fundamentally changed how we build and share knowledge, and increasingly they are being used to change how we do research itself -- consider the Open Science and Polymath projects.
Today's talk was, indeed, the highlight of my week. Not only did I learn more about Behrens and his work, but I also ended up with a couple of books to read (the aforementioned Whyte book and Kimon Nicolaïdes's The Natural Way to Draw), as well as a couple of ideas about what it would mean for software patterns to hide something. A good way to spend an hour.
Update: I've added a link to a known use.
(A pattern I've seen in running that applies more broadly.)
You are developing a physical skill or an ability that will take you well beyond your current level of performance. Perhaps you are a non-runner preparing for a 5K, or a casual runner training for a marathon, or an experienced runner coming back from a layoff.
To succeed, you will need endurance, the ability to perform steadily over a long period. You will also need strength, the ability to perform at a higher speed or with greater power over a shorter period of time. Endurance enables you to last for an amount of time longer than usual. It requires you to develop your slow-twitch muscles and your aerobic capacity, which depends on effective delivery of oxygen to your muscles. Strength enables you to work faster or harder, such as uphill or against an irregular force. It requires you to develop your fast-twitch muscles and your anaerobic capacity, which depends on muscles working effectively in the absence of oxygen.
You might try to develop strength first. Strength training involves many repetitions of intense work done for short durations. When you are beginning your training, you can handle short durations more easily than long ones. The high intensity will be uncomfortable, but it won't last for long. This does not work very well. First, you won't be able to work at an intense enough level to train your muscles properly, which means that your training sessions will not be as effective as you'd hope. Second, because your muscles are still relatively week, subjecting them to intense work even for short periods greatly increases the risk of injury.
You might try to develop strength and endurance in parallel. This is a strategy commonly tried by people who are in a hurry to reach a specific level of performance. You do longer periods of low-intensity work on some days and longer periods of high-intensity work on others. This strengthens your both your slow- and fast-twitch muscles and allows you to piggyback growth in one area on top of growth in the other. Unfortunately, this does not work well, either. There is a small decrease in the risk of injury from your strength training, but not as much as you might think. Our bodies adapt to change rather slowly, which means that your muscles don't grow stronger fast enough to prepare them for the intensity of strength training. Even when you don't injure yourself, you increase the risk of plateauing or fatigue.
Therefore, build a strong aerobic base first. Train for several weeks or even months at a relatively low level of intensity, resting occasionally to give your body a chance to adapt. This will build endurance, with slower speed or less power than you might want, but also strengthen your muscles, joints, and bones. Only then add to your regimen exercises that build your anaerobic capacity through many repetitions of high-intensity, short-duration activities. These will draw on the core strength developed earlier.
Continue to do workouts focused on endurance. These will give your body a chance to recover from the higher intensity workouts and time to adapt to those stresses in the form of more speed or power. For all but the most serious athletes, one or two strength workouts a week are sufficient. Doing more increases the risk of injury, fatigue, or loss of interest in training. As in so many endeavors, steady, regular practice tends to be much more valuable than occasional or spotty practice. This is especially true when the goal requires a long period of preparation, such as a marathon.
Examples. Every training program I have ever seen for runners, from 5Ks up to marathons, emphasizes the need for a strong aerobic base before before worrying about speed or other forms of power. This is especially true for beginners. Some beginners are eager to improve quickly and often don't realize how hard training can be on their bodies. Others fear that is they are not working "hard enough" they are not making progress. Low-intensity endurance training does work your body hard enough, just not in short bursts that make you strain.
Greg McMillan describes the usual form this pattern takes as well as a variation in Time To Rethink Your Marathon Training Program?. In its most common form, a runner first builds aerobic base, then works on strength in the form of hills and tempo runs, and finally works on speed. Gabriele Rosa, whom McMillan calls "arguably the world's greatest marathon coach", structures his training programs differently. He still starts his athletes with a significant period building aerobic base (Lengthen) followed by by a period that develops anaerobic capability (Strengthen). But he starts the anaerobic phase with short track workouts that develop the runners speed, down to 200m intervals, and only then has the runner move to strength workouts. Rosa's insight is that "the goal in marathon training is to fatigue the athlete with the duration of the workouts and not the speed, so speed needed to be developed first". This variation may not work well for runners coming back from injuries or who are otherwise prone to injury, because the speed workouts stress the body in a more extreme way than the tempo and cruise workouts of longer-distance strength work.
Lengthen, then Strengthen applies even to more experienced runners coming back from periods of little or no training. Many such runners assume that they can quickly return to the level they were at before the layoff, but the body will have adapted to the lower level of exertion and require retraining. Elite athletes returning from injury usually take several months to build their aerobic base before resuming hard training regimens.
I have written this pattern from the perspective of running, but it applies to other physical activities, too, such as biking and swimming. The risk of injury in some sports is lower than in running, due to less load on muscles, joints, and bones, but the principles of endurance and strength are the same.
Related Ideas. I think this pattern is also present in some forms of learning. For example, it is useful to build attention span and vocabulary when learning learning a new discipline before trying to build critical skills or deep expertise. The gentler form of learning provides a base of knowledge that is required for expert analysis or synthesis.
I realize that this application of the pattern is speculative. If you have any thoughts about it, or the pattern more generally, please let me know.
In trying to understand the role patterns and pattern languages play both in developing software and in learning to develop software, I often look for different angles from which to look at patterns. I've written the idea of patterns as descriptive grammar and the idea of patterns as a source of freedom in design. Both still seem useful to me as perspectives on patterns, and the latter is among the most-read articles on my blog. The notion of patterns-as-grammar also relates closely to one of the most commonly-cited roles that patterns play for the developer or learner, that of vocabulary for describing the meaningful components of a program.
This weekend, I read Brian Hayes's instructive article on compressive sensing, The Best Bits. Hayes talks about how it is becoming possible to imagine that digital cameras and audio recorders could record compressed streams -- say, a 10-megapixel camera storing a 3MB photo directly rather than recording 30MB and then compressing it after the fact. The technique he calls compressive sensing is a beautiful application of some straightforward mathematics and a touch of algorithmic thinking. I highly recommend it.
While reading this article, though, the idea of patterns as vocabulary came to mind in a new way, triggered initially by this passage:
... every kind of signal that people find meaningful has a sparse representation in some domain. This is really just another way of saying that a meaningful signal must have some structure or regularity; it's not a mere jumble of random bits.
Programs are meaningful signals and have structure and regularity beyond the jumble of seemingly random characters at the level of the programming level. The chasm between random language stuff and high-level structure is most obvious when working with beginners. They have to learn that structure can exist and that there are tools for creating it. But I think developers face this chasm all the time, too, whenever they dive into a new language, a new library, or a new framework. Where is the structure? Knowing it is there and seeing it are too different matters.
The idea of a sparse representation is fundamental to compression. We have to find the domain in which a signal, whether image or sound, can be represented in as few bits as possible while losing little or even none of the signal's information. A pattern language of programs does the same thing for a family of programs. It operates at a level (in Hayes' terms, in a domain) at which the signal of the program can be represented sparsely. By describing Java's I/O stream library as a set of decorators on a set of concrete streams, we convey a huge amount of information in very few words. That's compression. If we say nothing else, we have a lossy compression, in that we won't be able to reconstruct the library accurately from the sparse representation. But if we use more patterns to describe the library (such as Abstract Class and "Throw, Don't Catch"), we get a representation that pretty accurately captures the structure of the library, if not the bit-by-bit code that implements it.
This struck me as a useful way to think about what patterns do for us. If you've seen other descriptions of patterns as a means for compression, I'd love to hear from you.
Sometimes it pays to keep reading. Last time, I commented on breaking rules and mentioned a thread on the XP mailing list. I figured that I had seen all I needed there and was on the verge of skipping the rest. Then I saw a message from Laurent Bossavit and decided to read. I'm not surprised to learn something from Laurent; I have learned from him before.
Laurent's note introduced me to the legal term bright line. In the law, a bright-line rule is...
... a clearly defined rule or standard, composed of objective factors, which leaves little or no room for varying interpretation. The purpose of a bright-line rule is to produce predictable and consistent results in its application.
As Laurent says, Bright lines are important in situations where temptations are strong and the slope particularly steep, a well-known example is alcoholics' high vulnerability to even small exceptions. Test-driven development, or even writing tests soon after code and thus maintaining a complete suite of automated tests, requires a bright line for many developers. It's too easy to slide back into old habits, which for most developers are much older and stronger. Staying on the right side of the line may be the only practical way to Live Right.
This provides a useful name for what teachers often do in class: create bright lines for students. When students are first learning a new concept, they need to develop a new habit. A bright-line rule -- "Thou shalt always write a test first." or "Thou shalt write no line of code outside of a pair." -- removes from the students' minds the need to make a judgment that they are almost always not prepared to make yet: "Is this case an exception?" While learning, it's often better to play Three Bears and overdo it. This gives your mind a chance to develop good judgment through experience.
(For some reason, I am reminded of one way that I used to learn to play a new chess opening. I'd play a bazillion games of speed chess using it. This didn't train my mind to think deeply about the positions the opening created, but it gave me a bazillion repetitions. I soon learned a lot of patterns that allowed me to dismiss many bad alternatives and focus my attention on the more interesting positions.)
I often ask students to start with a bright line, and only later take on the challenge of a balancing test. It's better to evolve toward such complexity, not try to start there.
The psychological benefits of a bright-line test are not limited to beginners. Just as alcoholics have to hold a hard line and consider every choice consciously every day, some of us need a good "Thou shalt.." or "Thou shalt not..." in certain cases. As much as I like to run, I sometimes have to force myself out of bed at 5:00 AM or earlier to do my morning work-out. Why not just skip one? I am a creature of habit, and skipping even one day makes it even harder to get up the next, and the difficulty grows until I have a new habit.
(This has been one of the most challenging parts of trying to get back up to my old mileage after several extended breaks last year. I am proud finally to have done all five of my morning runs last week -- no days off, no PM make-ups. A new habit is in formation.)
If you know you have a particular weakness, draw a bright line for yourself. There is no shame in that; indeed, I'd say that it shows professional maturity to recognize the need and address it. If you need a bright line for everything, that may be a problem...
Sometimes, I adopt a bright line for myself because I want everyone on the team to follow a practice. I may feel comfortable exercising judgment in the gray area but not feel the rest of the team is ready. So we all play by the rules rather than discuss every possible judgment call. As the team develops, we can begin having those discussions. This is similar to how I teach many practices.
This may sound too controlling to you, and occasionally a student will say as much. But nearly everyone in class benefits from taking the more patient road to expertise. Again, from Laurent:
Rules which are more ambiguous and subtle leave more room for various fudge factors, and that of course can turn into an encouragement to fudge, the top of a slippery slope.
Once learners have formed their judgment, they are ready to balance forces. Until then, most are more likely to backslide out of habit than to make an appropriate choice to break the rule. And time spent arguing every case before they are ready is time not spent learning.
Shh.
I have a secret.
When I am writing a program, I will on occasion add a new piece of functionality without writing a test.
I am whispering because I have seen the reaction on the XP mailing list and on a number of blogs that Kent Beck received to his recent article, To Test or Not to Test? That's a Good Question. In this short piece, Kent describes his current thinking that, like golf, software development may have "long game" and "short game", which call for different tools and especially mentalities. One of the differences might be whether one is willing to trade automated testing for some other value, such as delivering a piece of software sooner.
Note that Kent did not say that in the long game he chooses not to test his code; he simply tested manually. He also didn't say that he plans never to write the automated tests he needs later; he said he would write them later, either when he has more time or, perhaps, when he has learned enough to turn 8 hours of writing a test into something much shorter.
Many peoples' public reactions to Kent's admission have been along these lines: "We test you to make this decision, Kent, but we don't trust everyone else. And by saying this is okay, you will contribute to the delinquency of many programmers." Now you know why I need to whisper... I am certainly not in the handful of programmers so good that these folks would be willing to excuse my apostasy. Kent himself is taking a lot of abuse for it.
I have to admit that Kent's argument doesn't seem that big a deal to me. I may not agree with everything he says in his article, but at its core he is claiming only that there is a particular context in which programmers might choose to use their judgment and not write tests before or immediately after writing some code. Shocking: A programmer should use his or her judgment in the course of acting professionally. Where is the surprise?
One of the things I like about Kent's piece is that he helps us to think about when it might be useful to break a particular rule. I know that I'll be breaking rules occasionally, but I often worry that I am surrendering to laziness or sloppiness. Kent is describing a candidate pattern: In this context, with these goals, you are justified in breaking this rule consciously. We are balancing forces, as we do all the time when building anything. We might disagree with the pattern he proposes, but I don't understand why developers would attack the very notion of making a trade-off that results in breaking a rule.
In practice, I often play a little loose with the rules of XP. There are a variety of reasons that lead me to do so. Sometimes I pay for not writing a test, and when I do I reflect on what about the situation made the omission so dangerous. If the only answer I can offer is "You must write the test, always.", then I worry that I have moved from behaving like a professional to behaving like a zealot. I suspect that a lot of developers make similar trade-offs.
I do appreciate the difficulty this raises for those of us who teach XP, whether at universities or in industry. If we teach a set of principles as valuable, what happens to our students' confidence in the principles when we admit that we don't follow the rules slavishly? Well, I hope that my students are learning to think, and that they realize any principle or rule is subject to our professional judgment in any given circumstance.
Of course, in the context of a course, I often ask students to follow the rules "slavishly", especially when the principles in question require a substantial change in how they think and behave. TDD is an example, as is pair programming. More broadly, this idea applies when we teach OOP or functional programming or any other new practice. (No assignment statements or sequences until Week 10 of Programming Languages!) Often, the best way to learn a new practice is to live it for a while. You understand it better then than you can from any description, especially how it can transform the way you think. You can use this understanding later when it comes to apply your judgment about potential trade-offs.
Even still, I know that, no matter how much an instructor encourages a new practice and strives to get students to live inside it for a while, some students simply won't do it. Some want to but struggle changing their habits. I feel for them. Others willfully choose not to try the something new and deny themselves the opportunity to grow. I feel for them, too, but in a different way.
Once students have had a chance to learn a set of principles and to practice them for a while, I love to talk with them about choices, judgment, and trade-offs. They are capable of having a meaningful discussion then.
It's important to remember that Kent is not teaching novices. His primary audience is professional programmers, with whom he ought to be able to have a coherent conversation about choices, judgment, and trade-offs. Fortunately, a few folks on the P list have entertained the "long game versus short game" claim and related their own experiences making these kind of decisions on a daily basis.
If we in the agile world rely on unthinking adherence to rules, then we are guilty of proselytizing, not educating. Lots of folks who don't buy the agile approaches love when they see examples of this rigidity. It gives them evidence to support their tenuous position about the whole community. From all of my full-time years in the classroom, I have learned that perhaps the most valuable asset I can possess is my students' trust in my goals and attitudes. Without that, little I do is likely to have any positive effect on them.
Kent's article has brought to the surfaced another choice agilistas face most every day: the choice between dogma and judgment. We tend to lose people when we opt for unthinking adherence to a rule or a practice. Besides, dogmatic adherence is rarely the best path to getting better every day at what we do, which is, I think one of the principles that motivate the agile methods.
I am coming to a newfound respect for Robert's Rules of Order these days. I've usually shied away from that level of formality whenever chairing a committee, but I've experienced the forces that can drive a group in that direction.
For the last year, I have been chairing a campus-wide task force. Our topic is one on which there are many views on campus and for which there is not currently a shared vision. As a result, we all realized that our first priority was communication: discussing key issues, sharing ideas, and learning what others thought. I'll also say that I have learned a lot about what I think from these discussions. I've learned a lot about the world that lies outside of my corner of campus.
With sharing ideas and building trust as our first goals, I kept our meetings as unstructured as possible, even allowing conversations to drift off topic at times. That turned out well sometimes, when we came to a new question or a new answer unexpectedly.
We are nearing the end of our work, trying to reach closure on our descriptions and recommendations. This is when I see forces pushing us toward more structure. It is easy to keep talking, to talk around a decision so much that we find ourselves doubting a well-considered result, or even contradicting the it. At this point, we are usually cover well-trod ground. A little formality -- motion, second, discussion, vote, repeat -- may help. At least I now have some first hand experience of what might have led Mr. Robert to define his formal set of rules.
It occurs to me that Robert's Rules are a little like the heavyweight methodologies we often see in the software development world. We agile types are sometimes prone to look down on big formal methodologies as obviously wrong: too rigid, too limiting, too unrealistic. But, like the Big Ball of Mud, these methodologies came into being for a reason. Most large organizations would like to ensure some level of consistency and repeatability in their development process over time. That's hard to do when you have a 100 or a 1000 architects, designers, programmers, and testers. A natural tendency is to formalize the process in order more closely to control it. If you think you value safety more than discovery, or if you think you can control the rate of change in requirements, then a big process looks pretty attractive.
Robert's Rules looks like a solution to a similar problem. In a large group, the growth in communication overhead can outpace the value gained by lots of free-form discussion. As a group grows larger, the likelihood of contention grows as well, and that can derail any value the group might gain from free-form discussion. As a group reaches the end of its time together, free-form discussion can diverge from consensus. Robert's Rules seek to ensure that everyone has a chance to talk, but that the discussion more reliably reach a closing point. They opt for safety and lowering the risk of unpredictability, in lieu of discovery.
Smaller teams can manage communication overhead better than large ones. This is one of the key ideas behind agile approaches to software development: keep teams small so that they can learn at the same time they are making steady process toward a goal. Agile approaches can work in large organizations, too, but developers need to take into account the forces at play in larger and perhaps more risk-averse groups. That's where the sort of expertise we find in Jutta Eckstein's Agile Software Development in the Large comes in so handy.
While I sense the value of running a more structured meeting now, I don't intend to run any of my task force or faculty meetings using Robert's Rules any time soon. But I will keep in mind the motivation behind them and try to act in the spirit of a more directed discussion when necessary. I would rather still value people and communication over rules and formalisms, to the greatest extent possible.
William Stafford's Writing the Australian Crawl includes several essays on language, words, and diction in poetry. Words and language -- he and others say -- are co-authors of poems. Their shapes and sounds drive the writer in unexpected ways and give rise to unexpected results, which are the poems that they needed to write, whatever they had in mind when they started. This idea seems fundamental to the process of creation for most poets.
We in CS think a lot about language. It is part of the fabric of our discipline, even when we don't deal in software. Some of us in CS education think and talk way too much about programming languages: Pascal! Java! Ada! Scheme!
But even if we grant that there is art in programming and programs, can we say that language drives us as we build our software? That language is the co-author of our programs? That its words and shapes (and sounds?) drive the programmer in unexpected ways and gives rise to unexpected results, which are the programs we need to write, whatever we have in mind when we start? Can the programmer's experience resemble in any way the poet's experience that Stafford describes?
[Language] begins to distort, by congealing parts of the total experience into successive, partially relevant signals.... [It] begins to enhance the experience because of a weird quality of language: the successive distortions of language have their own cumulative potential, and under certain conditions the distortions of language can reverberate into new experiences more various, more powerful, and more revealing than the experiences that set off language in the first place.
Successive distortions with cumulative potential... Programmers tend not to like it when the language they use, or must use, distorts what they want to say, and the cumulative effects of such distortions in a program that can give us something that feels cumbersome, feels wrong, is wrong.
Still... I think of my experiences coding in Smalltalk and Scheme, and recall hearing others tell similar tales. I have felt Smalltalk push me towards objects I wasn't planning to write, even to objects of a kind I had previously been unaware. Null objects, and numbers as control structures; objects as streams of behavior. Patterns of object-oriented programs often give rise to mythical objects that don't exist in the world, which belies OOP's oft-stated intention to build accurate models of the world. I have felt Scheme push me toward abstractions I did not know existed until just that moment, abstractions so abstract that they make me -- and many a programmer already fearful of functional style -- uncomfortable. Yet it is simply the correct code to write.
For me: Smalltalk and Lisp and Scheme, yes. Maybe Ruby. Not Java. C?
Is my question even meaningful? Or am I drowning in my own inability to maintain suitable boundaries between things that don't belong together?
At the Rebooting Computing Summit, one exercise called for us to interview each other and then report back to the group about the person we interviewed. The reports my partner and I gave, coupled with some self-reported experiences later in the day, reminded me of a pattern I've experienced in other contexts. Here is a rough first draft. Let me know what you think.
Second-Hand Story
When we need to know a person's story, our first tendency is often to ask him to tell us. After all, he know it best, because he lived it. He has had a chance to reflect on it, to reconsider decisions, and to evaluate what the story "means".
This approach can disappoint us. Sometimes, the person is too close to the experience and attaches accidental emotions and details. Sometimes, even though he has had a chance to reflect on his experience, he hasn't reflected enough -- or perhaps not at all! Telling the story may be the first time he has thought about some of those experiences in a long time. While trying to tell the story and summarize its meaning at the same time, the storyteller may reach for an easily-found answer. The result can be trite, convenient, or self-protective. Maybe the person is simply too close to an experience to see its true meaning.
Therefore, ask the person to tell his story to someone else, focusing on "just the facts". Then, ask the interviewer to tell the story, perhaps in summary form. Let the interviewer and the listeners look for patterns and themes.
The interviewer has distance and an opportunity to listen objectively. She is less likely to impose well-rehearsed personal baggage over the story.
The result can still be trite. If the listener does not listen carefully, or is too eager to stereotype the story, then the resulting story may well be worse than the original, because it is not only sanitized but sanitized by someone without intimate connection to it.
It can be refreshing to hear someone else tell your own story, to draw conclusions, to summarize what is most important. A good listener can pick up on essential details and remove the shroud of humility or disappointment that too often obscures your own view. You can learn something about yourself!
This technique depends on two people's ability to tell a story, not one. The original story-teller must be open, honest, and willing to describe situations more than evaluate them too much. (A little evaluation is unavoidable and also useful. The listener learns something about the story-teller from that party of the story, too.) The interviewer must be a careful listener and have a similar enough background to be able to put the story into context and form reasonable abstractions about it.
Examples. I found the interviewer's reports at the Rebooting Computing summit to be insightful, including the ones that Joe Carthy and I gave on one another. Hearing someone else "tell my story" let me hear it more objectively than if I had told it myself. Occasionally I felt let like chiming in to correct or add something, but I'm not sure than anything I said could have done a better job introducing myself to the rest of the group. Something Joe said during his interview of me made me think more about just how my non-CS profs helped lead me into CS, something I had never thought much about before that.
Later that day, we heard several self-reported stories, and those stories -- told by the same people who had reported on others earlier -- sounded flat and trite. I kept thinking, "What's the real story?" Maybe someone else could have told it better!
Related Ideas. I am reminded of several techniques I learned as an architecture major while studying Betty Edwards's Drawing on the Right Side of the Brain:
This pattern and these exercises are all examples of techniques for indirect learning. This is is perhaps the first time I realized just how well indirect learning can work in a social setting.
Early last week, I spent the last couple of days before Christmas wrapping up the grades on my Programming Languages course for fall semester. While grading the final exam, I seemed surprised by something on almost every problem. Here are a few that stand out:
cons and list
... are not the same. We spent some time early in the semester looking at how cons allocates a single new cell, and list allocates one cell per argument. Then we used them in a variety of ways throughout the rest of the course. After fifteen weeks programming in Scheme, how can so many people confuse them?
Overuse of accumulator variables
... is endemic to undergraduate students learning to program functionally. Two of the exam problems asked for straightforward procedures following the structural recursion pattern. These problems were about as simple examples of structural recursion as you can find: The largest value in a binary tree is the larger of
The zip of two lists is a list with a list of their cars consed into the zip of their cdrs. Many students used an accumulator variable to solve both problems. Some succeeded, with unnecessarily complex code, and some solutions buckled under the weight of the complexity.
Habits are hard to break. I have colleagues who tell me that OOP is easy. I look at their code and say, "yes, but...." The code isn't really OO; it just bears the trappings of classes and methods. Sequential, imperative programming habits run deep. An accumulator variable is often a crutch used by a sequential programmer to avoid writing a functional solution. I see that in my own code occasionally -- the accumulator is as often a code smell as a solution.
At a time when the world is looking to parallel computing in a multicore world, we need to find a way to change the habits programmers form, either by teaching functional programming better or by teaching functional programming sooner so that students form different habits.
Scheme procedure names
... are different than primitive procedure names in most other languages. They are bound to their values just like every other symbol. They can be re-bound, either locally or globally, using the same mechanisms used to bind values to any other names. This means that in this code:
(lambda (f g)
(lambda (x)
(+ (f x) (g x))))
the + symbol is a free variable, bound at the top level to the primitive addition operator. After we talked about this idea several times through the semester, I threw the students a bone on the final with a question that asked students to recognize + symbol as a free variable in a piece of code just like this one. The bone sailed past most of them.
Bound and free variables
... remain a tough topic for students to grasp, at least from my teaching. We spent several days in class talking about the idea of bound and free variables, and then writing code that could check a piece of code for bound and free variables. One of those sessions made a point of pointing out that occurs bound does not equal does not occur free, and that occurs free does not equal does not occur bound. For one thing, a variable could occur both bound and free in the same piece of code. For another, it might not occur at all! Yet when a final exam problem asked students to define an occurs-bound? procedure, several of them wrote the one-liner (not (occurs-free? x exp)). If only they knew how close they were... But they wrote that one-liner without understanding.
Syntactic abstraction
... is an idea that befuddles many of my students even after half a semester in which we work with the idea. Our Quiz 3 is tough for many of the students; it is often their lowest quiz grade of the course. In past semesters, though, students seemed to go home after being disappointed with their Quiz 3 score, hit the books, and come away with some understanding. This semester, several students came to the final exam with the same hole in their knowledge -- including students with two of the top three scores for the course. This makes me sad and disappoints me.
I can't do much to ensure that students will care enough to hit the books to overcome their disappointments, but I can change what I do. The next time I teach this course, I will probably have them start by working with for and while constructs in their own favorite languages. Maybe by stripping away the functional programming wrapping and the Scheme code we use to encounter these ideas, they will feel comfortable in a more familiar context and see the idea of syntactic abstraction to be really quite simple.
Postlude
Am I romanticizing the good old days, when men were men and all students went home and learned it all? Maybe a little, but I had a way to ground my nostalgia. I went back and checked the grades students earned in recent offerings of this course, which had very much the same content and structure. The highest score this semester was higher than the top score in the two most recent offerings, by 2-4%. Overall, through, grades lower. In fact, after the top score, the entire group had shifter down a whole letter grade. I don't think the students of the recent past were that much smarter or better prepared than this group, but I do think they had different attitudes and expectations.
One piece of evidence for this conclusion was that this semester there were far more 0s in the final grid of grades. I even had a couple of 0s on quizzes, where students simply failed to show up. This is, of course, much worse than simply scoring lower, because one things students can control is whether they do their work and submit assignments. As I wrote recently, each person must control what he or she can control. I am not sure how best to get juniors and seniors in college to to adopt this mindset, but maybe I'll need to bring Twyla Tharp -- or Bobby Knight -- into my classroom.
Some days, things go well, beyond expectation. Enjoy them! Today was one for me.
I've been thinking a lot about how students learn a new style of programming or a language that is quite different from their experience. Every class has its own personality, which includes interaction style, interest in Big Ideas, and curiosity. Last night it occurred to me that another important part of that personality is trust.
I was grading a quiz and suddenly felt a powerful personal connection to Gunnery Sergeant Foley from one of my favorite movies, An Officer and a Gentleman. There is a scene halfway through the film when he catches the protagonist, Zack Mayo, running an illegal contraband operation out of his barracks. The soldiers are in their room one afternoon when Foley walks in and declaims, "In every class, there's always one guy who thinks he's smarter than me. In this class, that's you, Mayo." He then dislodges a ceiling tile to reveal Mayo's stash of contraband and lets everyone know the jig is up.
Beyond the occasional irrational desire I have to be Lou Gossett breaking the spirits of cocky kids and building them back up from scratch, while grading solutions to a particular exam problem I couldn't help but think, "In every class, there's always one guy who thinks he's smarter than me..." Some of the students seemed to be going out of their ways not to use the technique we had learned in class, which resulted in them writing complex, often incorrect code. More practically for them, they ended up writing more code than they needed, which spent extra time they didn't have the luxury of spending. I felt bad for them grade-wise, but also a little sad that they seemed to have missed out on the beautiful idea beyond the programming pattern they were not using.
(Don't worry, class. This irrational desire of mine is fleeting. I don't want your DOR. Quite the contrary; I am looking for ways help you succeed!)
Sometimes, I wonder if the problem is that students don't really trust me. Why should they? Sure, I'm the teacher, but they feel pretty good about their programming skills, and the patterns I show them may be different and complex enough that they'd rather trust their own skills than my claim that, say, mutual recursion makes life better. They'll learn that with enough experience, and then they may realize that they can trust me after all.
In many ways, though, a bigger part of the problem may be a failure of storytelling. On my side are the stories I tell to engage students in an idea and its use. To paraphrase Merlin Mann paraphrasing Cliff Atkinson, I need to tell a story that makes the students feel like an character with a problem they care about and then show how our new way of solving their problem -- their problem -- makes them winners in the end. I think I do a better job of this now than I did ten years ago in this course, but I always wonder how I can do better.
On their side is, perhaps, a failure of their own storytelling -- not just about bugs, as Guzdial writes, but about the problem domain itself, the data types at play, and the kind of problem they are solving. I suspect writing code over nested symbolic lists that represent programs is so different from the students' experience that many of them have a hard time getting a real sense of what is going on. As long as the domain and task remain completely abstract in the mind, the problems look almost like random markings on the page. Where to start? That disorientation may account for not starting in what seems to me to be the obvious location.
As a teacher, failures in their storytelling become failures in my storytelling. I need to reconsider how I communicate the "big picture" behind my course. Asking students to create their own examples is one micro-step in this direction. But I also need to think about the macro-level -- something like XP's notion of metaphor. That practice has proved to be a stumbling block for XP, and I expect that it will remain a challenge for me.
On the way out of class today, I ran into the colleague who teaches in the room after me. I apologized for being slow to get out of the room and told him that I had talked more than usual today. From the looks on the faces of my students, I gathered that they needed a bit more. What they really needed was more time with same material. Most of all, they needed me to slow down -- rather than cover more material, they needed a chance to think more about what they had just learned. My way of doing that was to keep talking about the current example.
I told my colleague that there is probably a pedagogical pattern called Shut Up. And if not, then maybe there should be.
He said that the real pattern is Ask a Question.
I bowed down to him.
We talked a bit more, about how we both desire to use the Ask a Question pattern more often. We don't, out of habit and out of convenience. Professors lecture. It's what we do. The easiest thing to do is almost always: just keep talking, saying what I had planned to say.
I give myself some credit for how I ended class today. At the very least, I realized that I should not introduce new material. I was able to Let the Plan Go [1]
Better than sticking to a plan that is off track for my students is to keep talking, but about same stuff, only in a different way. This can sometimes be good. It gives me a chance to show students another side of the same idea, so that they might understand the idea better by seeing it from different perspectives.
Is Shut Up better than that? Sometimes. There are times when students just need... time -- time for the idea to sink in, time to process.
Is Ask a Question better still? Yes, in most cases. Even if I show students an idea, rather than telling them something, they remain largely passive in the process. Asking a question engages them in the idea. More and different parts of their brain can go to work. Most everything we know about how people learn says that this is A Good Thing.
Now, I do give myself a little credit here, too. I know about the Active Student pattern [2] and have changed my habits slowly over time. I try to toss in a question for students every now and then, if only to shut myself up for a while. But my holding pattern today probably didn't use enough questions. I was under time pressure (class is almost over!) and didn't have the presence of mind to turn the last few minutes into an exercise. I hope to do better next time.
~~~~~
[1] You can read the Let the Plan Go pattern in Seminars, an ambitious pattern language by Astrid Fricke and Markus Völter.
[2] The Active Student pattern is documented in Joe Bergin's paper "Some Pedagogical Patterns". There is a lot of good stuff in this one!
The latest issue of ACM's on-line pub Ubiquity consists of Chauncey Bell's My Problem with Design, an article that first appeared on his blog a year ago. I almost stopped reading it early on, distracted by other things and not enamored with its wordiness. (I'm one to talk about another writer's wordiness!) I'm glad I read the whole article, because Bell has an inspiring take on design for a world that has redefined the word from its classic sense. He echoes a common theme of the software patterns and software craftsmanship crowd, that in separating design from the other tasks involved in making an artifact we diminish the concept of design, and ultimately we diminish the quality of the artifact thus made.
But I was especially struck by these words:
The distinctive character of the designer shapes each design that affects us, and at the same time the designer is shaped by his/her inventions. Successful designs shape those for whom they are designed. The designs alter people's worlds, how they understand those worlds, and the character and possibilities of inhabiting those worlds. ...Most of our contemporaries tell a different story about designing, in which designers fashion or craft artifacts (including "information") that others "use." One reason that we talk about it this way, I think, is that it can be frightening to contemplate the actual consequences of our actions. Do we dare speak a story in which, in the process of designing structures in which others live, we are designing them, their possibilities, what they attend to, the choices they will make, and so forth?
(The passage I clipped gives the networked computer as the signature example of our era.)
Successful designs shape those for whom they are designed. In designing structures for people, we design them, their possibilities.
I wonder how often we who make software think this sobering thought. How often do we simply string characters together without considering that our product might -- should?! -- change the lives of its users? My experience with software written by small, independent developers for the Mac leads me to think that at least a few programmers believe they are doing something more than "just" cutting code to make a buck.
I have had similar feelings about tools built for the agile world. Even if Ward and Kent were only scratching their own itches when they built their first unit-testing framework in Smalltalk, something tells me they knew they were doing more than "making a tool"; they were changing how they could write Smalltalk. And I believe that Kent and Erich knew that JUnit would redefine the world of the developers who adopted it.
What about educators? I wonder how often we who "design curriculum" think this sobering thought. Our students should become new people after taking even one of our courses. If they don't, then the course wasn't part of their education; it's just a line on their transcripts. How sad. After four years in a degree programs, our students should see and want possibilities that were beyond their ken at the start.
I've been fortunate in my years to come to know many CS educators for whom designing curriculum is more than writing a syllabus and showing up 40 times in a semester. Most educators care much more than that, of course, or they would probably be in industry. (Just showing up out there pays better than just showing up around here, if you can hold the gig.) But even if we care, do we really think all the time about how our courses are creating people, not just degree programs? And even if we think this way in some abstract way, how often do we let it seep down into our daily actions. That's tough. A lot of us are trying.
I know there's nothing new here. Way back, I wrote another entry on the riff that "design, well done, satisfies needs users didn't know they had". Yet it's probably worth reminding ourselves about this every so often, and to keep in mind that what we are doing today, right now, is probably a form of design. Whose world and possibilities are we defining?
This thought fits nicely with another theme among some CS educators these days, context. We should design in context: in the context of implementation and the other acts inherent in making something, yes, but also in the context of our ultimate community of users. Educators such as Owen Astrachan are trying help us think about our computing in the context of problems that matter to people outside of the CS building. Others, such as Mark Guzdial, have been preaching computing in context for a while now. I write occasionally on this topic here. If we think about the context of our students, as we will if we think of design as shaping people, then putting our courses and curricula into context becomes the natural next step.
When I was in grad school, my advisor sent me to a series of swank conferences on expert systems in business, finance, and accounting. Among the things these conferences did for me was to give a chance to stay at Ritz Carlton hotels. This Midwestern boy had never been treated so well.
At the 1990 conference, I heard a talk by Gary Ribar from KPMG Peat Marwick, one of the Big Six accounting consulting firms of the time. Ribar described LoanProbe, a program that evaluated the collectibility of commercial loans. LoanProbe was a rule-based system organized in a peculiar way, with its 9000 rules separated into thirty-three separate "knowledge bases". It was a significant application that interacted with sixty external programs and two large data bases. Peat Marwick took LoanProbe a step further and used its organizational technique to build a knowledge acquisition program that enabled non-programmers to create systems with a similar structure.
I was so excited. I recognized this technique as what we in our lab called structured matching, a remarkably common and versatile pattern in knowledge-based systems. LoanProbe looked to me like the largest documented application of structured matching, which I was working on as a part of my research. Naturally, I wanted to make a connection to this work and share experiences with the speaker.
After the talk, I waited in line to speak with him. When my turn came, I gushed that their generic architecture was very cool and that "we do something just like that in our lab!". I expected camaraderie, but all I received back was an icy stare, a curt response, and an end to the conversation.
I didn't understand. Call me naive. For a while, I wondered if Mr. Ribar was simply an unfriendly guy. Then I realized that he probably took my comment not as a compliment -- We do that, too! -- but as a claim that the work he described was less valuable because it was not novel. I realized that I had violated one of the basic courtesies of research by telling him that his work was known already.
These days, I think fondly of Ribar, that talk, and that conference. He was behaving perfectly reasonably, given the culture in which he worked. Novelty is prized.
A few years after that conference, I came across PLoP and the software patterns community. This group of people valued discovering, documenting, and sharing common solutions, the patterns that make our software and our programming lives better. Structured Matcher did that, and it appeared in programs from all sorts of domain.
Jeff Patton has described this feature of the patterns community nicely in his article on emerging best practices in user experience:
If you tell someone a great idea, and they say "Yes, we do something like that too!", that's a pattern.
Documenting and sharing old, proven solutions that expert practitioners use may not get you a publication in the best research journal (though it might, if you are persistent and fortunate), but it will make the world better for programmers and software users. That is valuable, too.
My semester has started with a busy bang, complicated beyond usual by a colleague's family emergency, which has me teaching an extra course until he returns. The good news is that my own course is programming languages, so I am getting to think about fun stuff at least a couple of days a week.
Teaching Scheme to a typical mix of eager, indifferent, and skeptical students brought to mind a blog entry I read recently on Fluent Builders in Java. This really is a neat little design pattern for Java or C++ -- a way to make those code written in these languages look and feel so much better to the reader. But looking at the simple example:
Car car = Car.builder()
.year(2007)
.make("Toyota")
.model("Camry")
.color("blue")
.build();
... can't help me think about the old snark that we are reinventing Smalltalk and Lisp one feature at a time. A language extension here, a design pattern there, and pretty soon you have the language people want to use. Once again, I am turning into an old curmudgeon before my time.
As the author points out in a comment, Ruby gives us an more convenient way to fake named parameters: passing a hash of name/value pairs to the constructor. This is a much cleaner hack for programmers, because we don't have to do anything special; hashes are primitives. From the perspective of teaching Programming Languages this semester, what like most about the Ruby example is that it implements the named parameters in data, not code. The duality of data and program is one of those Big Ideas that all CS students should grok before they leave us, and now I have a way to talk about the trade-off using Java, Scheme, and an idiomatic construction in Ruby, a language gaining steam in industry.
Of course, we know that Scheme programmers don't need patterns... This topic came up in a recent thread on the PLT Scheme mailing list. Actually, the Scheme guys gave a reasonably balanced answer, in the context of a question that implied an unnecessary insertion of pattern-talk into Scheme programming. How would a Scheme programmer solve the problem that gives rise to fluent builders? Likely, write a macro: extend the language with new syntax that permits named parameters. This is the "pattern as language construct" mentality that extensible syntax allows. (But this leaves other questions unanswered, including: When is it worth the effort to use named parameters in this way? What trade-offs do we face among various ways to implement the macro?)
Finally, thinking ahead to next semester's compilers class, I can't help but think of ways to use this example to illustrate ideas we'll discuss there. A compiler can look for opportunities to optimize the cascaded message send shown above into a single function call. A code generator could produce a fluent builder for any given class. The latter would allow a programmer to use a fluent builder without the tedium of writing boilerplate code, and the former would produce efficient run-time code while allowing the programmer to write code in a clear and convenient way. See a problem; fix it. Sometimes that means creating a new tool.
Sometimes I wonder whether it is worth blogging ideas as simple as these. What's the value? I have a new piece of evidence in favor. Back in May 2007, I wrote several entries about a paper on the psychology of security. It was so salient to me for a while that I ended up suggesting to a colleague that he might use the paper in his capstone course. Sixteen months later, it is the very same colleague's capstone course that I find myself covering temporarily, and it just so happens that this week the students are discussing... Schneier's paper. Re-reading my own blog entries has proven invaluable in reconnecting with the ideas that were fresh back then. (But did I re-read Schneier's paper?)
I once wrote that extreme programming is a self-help system. This generalizes pretty well to other software methodologies, too. As we step away from developing software to personal hygiene, there is an entire ecosystem around the notion of life hacks, self-help for managing information and combatting data overload. Programmers and techies are active players in the lifehacking community because, well, we love to make tools to solve our problems and we love self-help systems. In the end, sometimes, we spend more time making tools and playing with them than actually solving our problems.
One of the popular lifehacking systems among techies is David Allen's Getting Things Done, or GTD. I've never read the book or adopted the system, but I've read about it and borrowed some of its practices in trying to treat my own case of information overload. The practices I have borrowed feel a lot like XP and especially test-driven development. Maybe that's why they appeal to me.
Consider this post on the basic concepts of GTD. Here is why GTD makes me think of TDD:
This is not a perfect match. In GTD, a goal from Step 1 may require many next actions, executed in sequence. In TDD, we decompose such big goals into smaller steps so that we can define a very clear next action to perform. And in GTD, Step 3 isn't really refactoring of a system. It's more a global check of where you are and how your lists of projects and next actions need to be revised or pruned. What resonates, though, is its discipline of regular review of where you are headed and how well your current 'design' can get you there.
It's not a perfect match, but then no metaphor is. Yet the vibe feels undeniably similar to me. Each has a mindset of short-term accountability through tests, small steps to achieve simple, clear goals, and regular review and clean-up of the system. The lifehackers who play with GTD even like to build tools to automate as much as they can so that they stay in the flow of getting things done as much as possible and trust their tools to help them manage performance and progress.
Successful patterns recur. I shouldn't be surprised to find these similarities.
Greg Wilson relates an observation by Michael Feathers: "refactoring pure functional code is a lot easier than refactoring imperative code". In one sense, this ought not to surprise us. When we eliminate side effects from our code, dependencies among functions flow through parameters, which make individual functions more predictably independent of one another. Without side effects, we don't have sequences of statements, which encourages smaller functions, which also makes it easier to understand the functions.
(A function call does involve sequencing, because arguments are evaluated before the function is invoked. But this encourages small functions, too: Deeply-nested expressions can be quite hard to read.)
There is another force counteracting this one, though. Feathers has been playing a lot with Haskell, which is strongly-typed through manifest types and type inferencing. Many functional languages are dynamically-typed, and dynamic typing makes it harder to refactor functional programs -- at least to guarantee that a particular refactoring does not change the program's behavior.
I'm a Scheme programmer when I use a functional language, so I encounter the conflict between these two forces. My suspicion from personal experience is that functional programmers need less support, or at least different kinds of support, when it comes to refactoring tools. The first key step is to identify refactorings from FP practice. From there, we can find ways to automate support for these refactorings. This is a longstanding interest of mine. One downside to my current position is a lack of time to devote to this research project...
Ralph Johnson pointed me to a design idea for very large databases called a shard. This is a neat little essay for several reasons. First, its author, Todd Hoff, explains an architecture for massive, distributed databases that has grown up in support of several well-known, high-performance web sites, including Flickr, Google, and LiveJournal. Second, Hoff also wrote articles that describe the architectures of Flickr, Google, and LiveJournal. Third, all four pages point to external articles that are the source of the information summarized. Collectively, these pages make a wonderful text on building scalable data-based web systems.
I've posted this entry in my Patterns category because this recurring architecture has all the hallmarks of a design pattern. It even has great name and satisfies Rule Of Three, something I've mentioned before -- and what a fine three it is. Each implementation uses the idea of a shard slightly differently, in fitting with the particular forces at play in the three companies' systems.
Buried near the bullet list on the Google page was an item worth repeating:
Don't ignore the Academy. Academia has a lot of good ideas that don't get translated into production environments. Most of what Google has done has prior art, just not prior large scale deployment.
This advice is a bit different from some advice I once shared for entrepreneurs, looking for Unix commands that haven't been implemented on the web yet, but the spirit is similar. Sometimes I hear envious people remark that Google hasn't done anything special; they just used a bunch of ideas others created to build a big system. Now, I don't think that is strictly true, but I do think that many of the ideas they used existed before in the database and networking worlds. And to the extent that is true, good for them! They paid attention in school, read beyond their assignments, and found some cool ideas that they could try in practice. Isn't that the right thing to do?
In any case, I recommend this article and encourage others to write more like it.
I recently started reading The Art of Possibility, by Roz and Ben Zander, and it brought to mind a pattern I have seen many times in literature and in life. Early on, the Zanders explain that this book is "not about making incremental changes that lead to new ways of doing things based on old beliefs". It is "geared toward causing a total shift of posture [and] perceptions"; it is "about transforming your entire world".
That's big talk, but the Zanders are not alone in this message. When talking to companies about creating new products, reaching customers, and running a business, Guy Kawasaki uses the mantra Revolution, Then Evolution. Don't try to get better at what you are doing now, because you aren't always doing the right things. But also don't worry about trying to be perfect at doing something new, because you probably won't be. Transform your company or your product first, then work to get better.
This pattern works in part because people need to be inspired. The novelty of a transformation may be just what your customers or teammates need to rally their energies, when "just" trying to get better will make them weary.
It also works despite running contrary to our fixation these days with "evolving". Sometimes, you can't get there from here. You need a mutation, a change, a transformation. After the transformation, you may not be as good as you would like for a while, because you are learning how to see the world differently and how to react to new stimuli. That is when evolution becomes useful again, only now moving you toward a higher peak than was available in the old place.
I have seen examples of this pattern in the software world. Writing software patterns was a revolution for many companies and many practitioners. The act of making explicit knowledge that had been known only implicitly, or the act of sharing internal knowledge with others and growing a richer set of patterns, requires a new mindset for most of us. Then we find out we are not very good, so we work to get better, and soon we are operating in a world that we may not have been able even to imagine before.
Adopting agile development, especially a practice-laden approach such as XP, is for many developers a Revolution, Then Evolution experience. So are major lifestyle changes such as running.
Many of you will recognize an old computational problem that is related to this idea: hill climbing. Programs that do local search sometimes get stuck at a local maximum. A better solution exists somewhere else in the search space, but the search algorithm makes it impossible for the program to get out of the neighborhood of the local max. One heuristic for breaking out of this circumstance is occasionally to make a random jump somewhere else in the search space, and see where hill climbing leads. If it leads to a better max, stay there, else jump back to the starting point.
In AI and computer science more generally, it is usually easier to peek somewhere else, try for a while, and pop back if it doesn't work out. Most individuals are reluctant to make a major life change that may need to be undone later. We are, for the most part, beings living in serial time. But it can be done. (I sometimes envy the freer spirits in this world who seem built for this sort of experimentation.) It's even more difficult to cause a tentative radical transformation within an organization or team. Such a change disorients the people involved and strains their bonds, which means that you had better well mean it when you decide to transform the team they belong to. This is a major obstacle to Revolution, Then Evolution, and one reason that within organizations it almost always requires a strong leader who has earned everyone's trust, or at least their respect.
As a writer of patterns, I struggle with how to express the context and problem for this pattern. The context seems to be "life", though there are certainly some assumptions lurking underneath. Perhaps this idea matters only when we are seeking a goal or have some metric for the quality of life. The problem seems to be that we are not getting better, despite an effort to get better. Sometimes, we are just bored and need a change.
Right now, the best I can say from my own experience is that Revolution, Then Evolution applies when it has been a while since I made long-term progress, when I keep finding myself revisiting the same terrain again and again without getting better. This is a sign that I have plateaued or found a local maximum. That is when it is time to look for a higher local max elsewhere -- to transform myself in some way, and then begin again the task of getting better by taking small steps.
While reading this morning I came across a link to this essay. College students should read it, because it points out many of the common anti-patterns in the essays that we professors see -- even in papers written for computer science courses.
Of course, if you read this blog, you know that my writing is a poster child for linguistic diffidence, and pat expressions are part of my stock in trade. It's sad to know that these anti-patterns make up so much of my word count.
This web page also introduced me to Roberts's book Patterns in English. With that title, I must check it out. I needed a better reason to stop by the library than merely to return books I have finished. Now I have one.
I ran across a pattern today that reminded of another I encountered while at ChiliPLoP. Both help developers deal with side effects, changes to a program's state. Let me share these patterns with you all, with a common explanation of their value.
Most programs written these days are in a style where setting and changing the values of one or more variables, via a sequence of imperative statements. Side effects are a common source of programmers' misunderstanding when reading code. A program can change a variable's state almost anywhere, and that makes reading any bit of code uneasy: "Do I really know what this variable means right now?" Using only local variables only in the context of a small procedure is one way to localize effects. Even still, problems can arise.
I won't try write full patterns for these. I'll write short patlets and give you links to the articles I read, which do a good job talking about the ideas.
Mutual Recursion with Side Effects
In Solving Every Sudoku Puzzle, Peter Norvig builds a Python program for the title task. About 40% of the way in, he says:
If you have two mutually-recursive functions that both alter the state of an object, try to move almost all the functionality into just one of the functions. Otherwise you will probably end up duplicating code.
Duplicate code is usually a bad thing, because it creates a problem for programmers keeping the copies in sync. Duplicate code that modifies state is especially bad, because it brings in the extra complication of making another procedure harder to understand.
Side Effects and Python's Default Parameters
Coincidentally, the second pattern involves Python, too. This time the pattern is Python-specific, addressing an issue with a language feature.
Context: You are writing a procedure with a default parameter.
Problem: The procedure needs to modify the default parameter. Python evaluates a default parameter's initial value only on the first call to the procedure.
Solution: Whenever the parameter is missing, initialize it within the method.
Tim Ottinger gives his implementation technique in Python's Mutable Default Problem:
def function( item, stuff=None ): stuff = stuff or [] # ... modify stuff, etc.
This pattern allows the user to take advantage of the default parameter when he has no collection to send. It does so by following a principle laid out in the article Ottinger references: In Python, "don't use mutable objects as function defaults."
This pattern may not be Python-specific, because there may be other languages with this initialize-once behavior. It seems like a bug to me, not a feature, but I'm not a Python programmer and so can't speak authoritatively. But I am glad that Ruby doesn't do this.
~~~~~
Postscript: While preparing this article, I learned something new about Ruby, unrelated to this issue. It is possible to extract from a class a new class that has a subset of the original class's protocol. Very nice indeed!)
I have another million to my credit, and it was a marvelous little surprise.
Popular culture is full of all sorts of literary references with which you and I are supposed to be familiar. Every year brings another one or two. The Paradox of Choice. The Tipping Point. The Wisdom of Crowds. Well-read people are expected, well, to have read the books, too. How else can we expect to keep up with our friends when they discuss these books, or to use the central wisdoms they contain in knowing ways?
I have a confession. I have read only two or three chapters of The Wisdom of Crowds. I have read only an excerpt from The Tipping Point that appeared in the New Yorker or some other literary magazine. And while I've seen a Google talk by Barry Schwartz on-line, I may not have read anything more than a short precis of the work. Of course, I have learned a lot about them from my friends, and by reading about them in various other contexts. But, strictly speaking, I have not read any of them.
To be honest, I feel no shame about this state of affairs. There are so, so many books to read, and these just have not seemed important enough to displace others from my list. And in the case of The Wisdom of Crowds, I found that one or two chapters told me pretty much all I needed to understand the Big Idea it contained. Much as Seth Godin has said about many popular business books, many books in the popular canon can be boiled down to much shorter works in their essence, with the rest being there for elaboration or academic gravitas.
For airplane reading on my trip to the workshop at Google, I took Pierre Bayard's How to Talk About Books You Haven't Read. Bayard's thesis is that neither I nor anyone else should feel shame about not having read any given book, even if we feel a strong compulsion to comment, speak, or write about it. In not reading and talking anyway, we are part of a grand intellectual tradition and are, in fact, acting out of necessity. There are simply too many books to read.
This problem arises even in the most narrow technical situation. When I wrote my doctoral dissertation, I surely cited works with which I was familiar but which I had not "read", or, having read them, had only skimmed them for specific details. I recall feeling a little bit uneasy; what if some party of the book or dissertation that I had not studied deeply said something surprising or wrong? But I knew a lot about these works in context: from other people's analyses, from other works by the same author, and even from having discussed the work with the author him- or herself. But in an important way, I was talking about a work I "had not read".
How I could cite the work anyway and still feel I was being intellectually honest gets to one of the central themes of Bayard's book: the relationships between ideas are often more important than the ideas themselves. To understand a work in the context of the universal library means more than just to know the details of the work, and the details themselves are often so affected by conditions outside of the text that they are less reliable than the bigger picture anyway.
First, let me assure you. Bayard wrote this book with a wink in his eye. At times, he speaks with a cavalier sarcasm. He also repeats himself in places; occasional paragraphs sound as if they have been lifted verbatim from previous chapters.
Second, this book fits Seth Godin's analysis of popular business books pretty well. Two or three chapters were sufficient to express the basic idea of this book. But such a slim product would have missed something important. How to Talk About Books You Haven't Read started as a joke, perhaps over small talk at a cocktail party, but as Bayard expanded on the idea he ended up with an irreverent take on reading, thinking, and understanding that carries a lot more truth than I might first have imagined. Readers of this blog who are software patterns aficionados might think of Big Ball of Mud in order to understand just what I mean: antipattern as pattern, when looked at from a different angle.
This book covers a variety of books that deal in some way with not reading books but talking about them. Along the way, Bayard explores an even wider variety of ideas. Many of these sound silly, even wrong, at first, and he uses this to weave a lit-crit tale that is perfect parody. But as I read, I kept saying, "Yeah, but..." in a way, this really is true.
For example, Bayard posits that reading too much can cause someone to lose perspective in the world of ideas and to lose one's originality. In a certain way, the reader subordinates himself to the writer, and so reading too much means always subordinating to another rather than creating ideas oneself. We could read this as encouragement not to read (much), which would miss his joke. But there is another level at which he is dead-on right. I knew quite a few graduate students who learned this firsthand when they got into a master's program and found that they preferred to immerse themselves in the research of others than to do creative research of their own. And there many blogs which do a fine job reporting on other people's work but which never seem to offer much new. (I struggle with that danger each time I write in this blog.)
Not reading does not mean that we cannot have an opinion. My friends and I are examples of this. Students are notorious for this, and Bayard, a lit professor, discusses the case of students in class at some length. But I was most taken by his discussion of Laura Bohannan's experience telling the story of Hamlet to the Tiv people of West Africa. As she told the story, the Tiv elders interpreted the story for her, correcting her -- and Western culture, and Shakespeare -- along the way. One of the interpretations was a heterodoxy that has a small but significant following among Shakespeare scholars. The chief even ventured to predict how the story ended, and did a pretty good job. Bayard used this as evidence that not reading a book may actually leave our eyes open to new possibilities. Bohannan's story is available on-line, and you really should read it -- it is delightful.
Bayard talks about so many different angles on our relationship with books and stories about them, including
One chapter focuses on our encounters with writers, and the ticklish situations they create for the non-reader and for the writer. In another, Bayard deals with the relationship among professors, students, and books. It made me think about how students interpret the things I say in class, whether about our readings or the technical material we are learning. Both of these chapters figure in a second entry I'm writing about this book, as well as chapters on the works of Montaigne and Wilde.
One chapter uses as his evidence the campus novels of David Lodge, of whom I am a big fan. I've never blogged about them, but I did use the cover of one of his books to illustrate a blog entry. Yet another draws on Bill Murray's classic Groundhog Day, an odd twist in which actually reading books enters into Bayard's story and supports his thesis. I have recommended this film before and gladly do so again.
As in so many situations, our fear of appearing weak or unknowledgable is what prevents us from talking freely about a book we haven't read, or even to admit that we have not read it. But this same fear is also responsible for discouraging us from talking about books we have read and about ideas we have considered. This is ultimately the culprit that Bayard hopes to undermine:
But our anxiety in the face of the Other's knowledge is an obstacle to all genuine creativity about books. The idea that the Other has read everything, and thus is better informed than us, reduces creativity to a mere stopgap that non-readers might resort to in a pinch. In truth, readers and non-readers alike are caught up in an endless process of inventing books, whether we like it or not, and the real question is not how to escape that process, but how to increase its dynamism and its range.
Bayard's book is worth reading just for his excerpts of other books and for his pointer to the story about the Tiv. I should probably feel guilt at not having read this book yet when so many others have, but I'm just happy to have read it now.
While reading on the plane coming home, I glanced across the aisle and noticed another passenger reading Larry Niven's Ringworld. I smiled and thought "FB++", in Bayard's rating system. I could talk about it nonetheless.
In his recent bestseller The Black Swan: The Impact of the Highly Improbable, Nassim Nicholas Taleb uses the term narrative fallacy to describe man's penchant for creating a story after the fact, perhaps subconsciously, in order to explain why something happened -- to impute a cause for an event we did not expect. This fallacy derives from our habit of imposing patterns on data. Many view this as a weakness, but I think it is a strength as well. It is good when we use it to communicate ideas and to push us into backing up our stories with empirical investigation. It is bad when we let our stories become unexamined truth and when we use the stories to take actions that are not warranted or well-founded.
Of late, I've been thinking of the narrative fallacy in its broadest sense, telling ourselves stories that justify what we see or want to see. My entry on a response to the Onward! submission by my ChiliPLoP group was one trigger. Those of us who believe strongly that we could and perhaps should be doing something different in computer science education construct stories about what is wrong and what could be better; we're like anyone else. That one OOPSLA reviewer shed a critical light on our story, questioning its foundation. That is good! It forces us to re-examine our story, to consider to what extent it is narrative fallacy and to what extent it matches reality. In the best case, we now know more about how to tell the story better and what evidence might be useful in persuading others. In the worst, we may learn that our story is a crock. But that's a pretty good worst case, because it gets us back on the path to truth, if indeed we have fallen off.
A second trigger was finding a reference in Mark Guzdial's blog to a short piece on universal programming literacy at Ken Perlin's blog. "Universal programming literacy" is Perlin's term for something I've discussed here occasionally over the last year, the idea that all people might want or need to write computer programs. Perlin agrees but uses this article to consider whether it's a good idea to pursue the possibility that all children learn to program. It's wise to consider the soundness of your own ideas every once in a while. While Perlin may not be able to construct as challenging a counterargument as our OOPSLA reviewer did, he at least is able to begin exploring the truth of his axioms and the soundness of his own arguments. And the beauty of blogging is that readers can comment, which opens the door to other thinkers who might not be entirely sympathetic to the arguments. (I know...)
It is essential to expose our ideas to the light of scrutiny. It is perhaps even more important to expose the stories we construct subconsciously to explain the world around us, because they are most prone to being self-serving or simply convenient screens to protect our psyches. Once we have exposed the story, we must adopt a stance of skepticism and really listen to what we hear. This is the mindset of the scientist, but it can be hard to take on when our cherished beliefs are on the line.
I've tried to explain the idea of software patterns in a lot of different ways, to a lot of different kinds of people. Reading James Tauber's Grammar Rules reminds me of one of my favorites: a pattern language is a descriptive grammar. Patterns describe how (good) programmers "really speak" when they are working in the trenches.
Talking about patterns as grammar creates the potential for the sort of misunderstanding that Tauber discusses in his entry. Many people, including many linguists, think of grammar rules as, well, rules. I was taught to "follow the rules" in school and came to think of the rules as beyond human control. Linguists know that the rules of grammar are man-made, yet some still seem to view them as prescriptive:
It is as if these people are viewing rules of grammar like they would road rules--human inventions that one may disagree with, but which are still, in some sense, what is "correct"...
Software patterns are rarely prescriptive in this sense. They describe a construct that programmers use in a particular context to balance the forces at play in the problem. Over time, they have been found useful and so recur in similar contexts. But if a programmer decides not to use a pattern in a situation where it seems to apply, the programmer isn't "wrong" in any absolute sense. But he'll have to resolve the competing forces in some other way.
While the programmer isn't wrong, other programmers might look at him (or, more accurately, his program) funny. They will probably ask "why did you do it that way?", hoping to learn something knew, or at least confirm that the programmer has done something oddly.
This is similar to how human grammar works. If I say, "Me wrote this blog", you would be justified in looking at me funny. You'd probably think that what I speaking incorrectly.
Tauber points out that, while I might be violating the accepted rules of grammar, I'm not wrong in any absolute sense:
... most linguists focus on modeling the tacit intuitions native speakers have about their language, which are very often at odds with the "rules of grammar" learnt at school.
He gives a couple of examples of rules that we hear broken all of the time. For example, native speakers of English almost always say "It's me", not "It's I", though that violates the rules of nominative and accusative case. Are we all wrong? In Sr. Jeanne's 7th-grade English class, perhaps. But English grammar didn't fall from the heavens as incontrovertible rules; it was created by humans as a description of accepted forms of speech.
When a programmer chooses not to use a pattern, other programmers are justified in taking a second look at the program and asking "why?", but they can't really say he's guilty of anything more than doing things differently.
Like grammar rules, some patterns are more "right" than others, in the sense that it's less acceptable to break some than others. I can get away with "It's me", even in more formal settings, but I cannot get away with "Me wrote this blog", even in the most informal settings. An OO programmer might be able get away with not using the Chain of Responsibility pattern in a context where it applies, but not using Strategy or Composite in appropriate contexts just makes him look uninformed, or uneducated.
A few more thoughts:
So, patterns are not like a grammar for programming language, which is prescriptive. To speak Java at all, you have to follow the rules. They are like the grammar of a human language, which model observations about how people speak in the wild.
As a tool for teaching and learning, patterns are so useful precisely because they give us a way to learn accepted usages that go beyond the surface syntactic rules of a language. Even better, the pattern form emphasizes documenting when a construct works and why. Patterns are better than English grammar in this regard, at least better than the way English grammar is typically taught to us as schoolchildren.
There are certainly programmers, software engineers, and programming language theorists who want to tell us how to program, to define prescriptive rules. There can be value in this approach. We can often learn something from a model that has been designed based on theory and experience. But to me prescriptive models for programming are most useful when we don't feel like we have to follow them to the letter! I want to be able to learn something new and then figure out how I can use it to become a better programmer, not a programmer of the model's kind.
But there is also a huge, untapped resource in writing the descriptive grammar of how software is built in practice. It is awfully useful to know what real people do -- smart, creative people; programmers solving real problems under real constraints. We don't understand programming or software development well enough yet not to seek out the lessons learned by folks working in the trenches.
This brings to mind a colorful image, of software linguists venturing into the thick rain forest of a programming ecosystem, uncovering heretofore unexplored grammars and cultures. This may not seem as exotic as studying the Pirahã, but we never know when some remote programming tribe might upend our understanding of programming...
The Small Doses pattern I wrote up in my previous entry was triggered almost exclusively by the story I heard from Carl Page. The trigger lives on in the text that runs from "Often times, the value of Small Doses..." to the end, and in the paragraph beginning "There is value in distributing...". The story was light and humorous, just the sort of story that will stick with a person for twenty or more years.
As I finally wrote the pattern, it grew. That happens all the time when I write. It grew both in size and in seriousness. At first I resisted getting too serious, but increasingly I realized that the more serious kernel of truth needed telling. So I gave it a shot.
The result of this change in tone and scope means that the pattern you read is not yet ready for prime time. Rather than wait until it was ready, though, I decided to let the pattern be a self-illustration. I have put it out now, in its rough form. It is rough both in completeness and in quality. Perhaps my readers will help me improve. Perhaps I will have time and inspiration soon to tackle the next version.
In my fantasies, I have time to write more patterns in a Graduate Student pattern language (code name: Chrysalis), even a complete language, and cross-reference it with other pattern languages such as XP. Fantasies are what they are.
Update: Added a known use contributed by Joe Bergin. -- 05/19/08.
Also Known As Frequent Releases
From Pattern Language Graduate Student
You are writing a large document that one or more other people must read and provide feedback on before it is distributed externally.
The archetype is a master's thesis or doctoral dissertation, which must be approved by a faculty committee.
You want to give your reviewers the best document possible. You want them to give you feedback and feel good about approving the document for external distribution.
You want to publish high-quality work. You would also like to have your reviewers see only your best work, for a variety of reasons. First, you respect them and are thankful for their willingness to help you. Second, they often have the ability to help you further in the future, in the form of jobs or recommendations. Good work will impress your reviewers more than weaker work. A more complete and mature document is more likely to resemble the final result than a rougher, earlier version.
In order to produce a document of the highest quality, you need time -- time to research, write, and revise. This delays your opportunity to distribute it to your reviewers. It also delays their opportunity to give you feedback.
Your reviewers are busy. They have their own work to do and are often volunteering their time to serve you.
Big tasks require a lot of time. If a task takes a lot of time to do, some people face a psychological barrier to starting the task.
A big task decomposed into several smaller tasks may take as much time as the big task, or more, but each task takes a smaller time. It is often easier to find time in small chunks, which makes it easier to start on the task in the first place.
The sooner your reviewers are able to read parts of the document, the sooner they will be able to give you feedback. This feedback helps you to improve the document, both in the large (topic, organization) and the small (examples, voice, illustrations, and so on).
Therefore:
Distribute your document to reviewers periodically over a relatively drawn out period. Early versions can be complete parts of the document, or rough versions of the entire document.
In the archetypal thesis, you might give the reviewers one chapter per week, or you might give a whole thesis in which each part is in various stages of completeness.
There is certainly a trade-off between the quality of a document and the timeliness of delivery. Don't worry; this is just a draft. You are always free to improve and extend your work. Keep in mind that there is also a trade-off between the quality of a document and the amount of useful feedback you are able to incorporate.
There is value in distributing even a very rough or incomplete document at regular intervals. If reviewers read the relatively weak version and make suggestions, they will feel valuable. If they don't read it, they won't know or mind that you have made changes in later versions. Furthermore, they may feel wise for not having wasted their time on the earlier draft!
With the widespread availability of networks, we can give our reviewers real-time access to an evolving document in the form of an-line repository. In such a case, Small Doses may take the form of comments recorded as each change is committed to the repository. It is often better for your reviewers if you give them periodic descriptions of changes made to the document, so that they don't have to wade through minutiae and can focus on discrete meaningful jumps in the document.
I have seen Small Doses work effectively in a variety of academic contexts, from graduate students writing theses to instructors writing lecture notes and textbooks for students. I've seen it work for master's students and doctoral students, for text and code and web sites. Joe Bergin says that this pattern is an essential feature of the Doctor of Professional Studies program at Pace University. Joe has documented patterns for succeeding in the DPS program. (If you know of particularly salient examples of Small Doses, I'd love to hear them.)
Often times, the value of Small Doses is demonstrated best in the results of its applying its antipattern, Avalanche. Suppose you are nearing a landmark date, say, the deadline for graduation or the end of spring semester, when faculty will scatter for the summer. You dump a 50-, 70-, or 100+-page document on your thesis committee. In the busy time before the magic date, committee members have a difficulty finding time to read the whole document. Naturally, they put off reading it. Soon they fall way behind and have a hard time meeting the deadline -- and they blame you for the predicament, for unrealistic expectations. Of course, had you given the committee a chapter at a time for 5 or 6 weeks leading up to the magic date, some committee members would still have fallen behind reading it, because they are distracted with their own work. But then you could blame the them for not getting done!
Related Patterns Extreme Programming and other agile software methodologies encourage Short Iterations and Frequent Releases. Such frequent releases are the Small Doses of the software development world. They enable more continuous feedback and allow the programmers to improve the quality of the code based on what they learn. The Avalanche antipattern is the source of many woes in the world of software, in large part due to the lack of feedback they afford from users and clients.
I learned the Small Doses pattern from Carl Page, my Artificial Intelligence II professor at Michigan State University in 1987. Professor Page was a bright guy and very good computer scientist, with an often dark sense of humor. He mentored his students and advisees with sardonic stories like Small Doses. He was also father to another famous Page, Larry.
This week I ran across Jonathan Edwards's review of Gregor Kiczales's OOPSLA 2007 keynote address, "Context, Perspective and Programs" (which is available from the conference podcast page). Having recently commented on Peter Turchi's keynote, I figured this was a good time to go back and listen to all of Gregor's again. I first listened to part of it back when I posted it to the page, but I have to admit that I didn't understand it all that well then. So a second listen was warranted. This time I had access to his slides, which made a huge difference.
In his talk, Kiczales tries to bring together ideas from philosophy, language, and our collective experience writing software to tackle a problem that he has been working around his whole career: programs are abstractions, and any abstraction represents a particular point of view. Over time, the point of view changes, which means that the program is out of sync. Software folks have been thinking about ways to make programs capable of responding naturally as their contexts evolve. Biological systems have offered some inspiration in the last decade or so. Kiczales suggests that computer science's focus on formality gets in the way of us finding a good answer to our problem.
Some folks took this suggestion as meaning that we would surrender all formalism and take up models of social negotiation as our foundation. Roly Perera wrote a detailed and pointed review of this sort. While I think Perera does a nice job of placing Kiczales's issues in their philosophical context, I do not think Kiczales was saying that we should go from being formal to being informal. He was suggesting that we shouldn't have to go from being completely formal to being completely informal; there should be a middle ground.
Our way of thinking about formality is binary -- is that any surprise? -- but perhaps we can define a continuum between the two. If so, we could write our program at an equilibrium point for the particular context it is in and then, as the context shifts, allow the program to move along the continuum in response.
Now that I understand a little better what Kiczales is saying, his message resonates well with me. It sounds a lot like the way a pattern balances the forces that affect a system. As the forces change, a new structure may need to emerge to keep the code in balance. We programmers refactor our code in response to such changes. What would it be like for the system to recognize changes in context and evolve? That's how natural systems work.
As usual, Kiczales is thinking thoughts worth thinking.
While catching up on some work at the office yesterday -- a rare Saturday indeed -- I listened to Peter Turchi's OOPSLA 2007 keynote address, available from the conference podcast page. Turchi is a writer with whom conference chair Richard Gabriel studied while pursuing his MFA at Warren Wilson College. I would not put this talk in the same class as Robert Hass's OOPSLA 2005 keynote, but perhaps that has more to do with my listening to an audio recording of it and not being there in the moment. Still, I found it to be worth listening as Turchi encouraged us to "get lost" when we want to create. We usually think of getting lost as something that happens to us when we are trying to get somewhere else. That makes getting lost something we wish wouldn't happen at all. But when we get lost in a new land inside our minds, we discover something new that we could not have seen before, at least not in the same way.
As I listened, I heard three ideas that captured much of the essence of Turchi's keynote. First was that we should strive to avoid preconception. This can be tough to do, because ultimately it means that we must work without knowing what is good or bad! The notions of good and bad are themselves preconceptions. They are valuable to scientists and engineers as they polish up a solution, but they often are impediments to discovering or creating a solution in the first place.
Second was the warning that a failure to get lost is a failure of imagination. Often, when we work deeply in an area for a while, we sometimes feel as if we can't see anything new and creative because we know and understand the landscape so well. We have become "experts", which isn't always as dandy a status as it may seem. It limits what we see. In such times, we need to step off the easy path and exercise our imaginations in a new way. What must I do in order to see something new?
This leads to the third theme I pulled from Turchi's talk: getting lost takes work and preparation. When we get stuck, we have to work to imagine our way out of the rut. For the creative person, though, it's about more about getting out of a rut. The creative person needs to get lost in a new place all the time, in order to see something new. For many of us, getting lost may seem like as something that just happens, but the person who wants to be lost has to prepare to start.
Turchi mentioned Robert Louis Stevenson as someone with a particular appreciation for "the happy accident that planning can produce". But artists are not the only folks who benefit from these happy accidents or who should work to produce the conditions in which they can occur. Scientific research operates on a similar plane. I am reminded again of Robert Root-Bernstein's ideas for actively engaging the unexpected. Writers can't leave getting lost to chance, and neither can scientists.
Turchi comes from the world of writing, not the world of science. Do his ideas apply to the computer scientist's form of writing, programming? I think so. A couple of years ago, I described a structured form of getting lost called air-drop programming, which adventurous programmers use to learn a legacy code base. One can use the same idea to learn a new framework or API, or even to learn a new programming language. Cut all ties to the familiar, jump right in, and see what you learn!
What about teaching? Yes. A colleague stopped by my office late last week to describe a great day of class in which he had covered almost none of what he had planned. A student had asked a question whose answer led to another, and then another, and pretty soon the class was deep in a discussion that was as valuable, or more, than the planned activities. My colleague couldn't have planned this unexpectedly good discussion, but his and the class's work put them in a position where it could happen. Of course, unexpected exploration takes time... When will they cover all the material of the course? I suspect the students will be just fine as they make adjustments downstream this semester.
What about running? Well, of course. The topic of air-drop programming came up during a conversation about a general tourist pattern for learning a new town. Running in a new town is a great way to learn the lay of the land. Sometimes I have to work not to remember landmarks along the way, so that I can see new things on my way back to the hotel. As I wrote after a glorious morning run at ChiliPLoP three years ago, sometimes you run to get from Point A to Point B; sometimes, you should just run. That applies to your hometown, too. I once read about an elite women's runner who recommended being dropped off far from your usual running routes and working your way back home through unfamiliar streets and terrain. I've done something like this myself, though not often enough, and it is a great way to revitalize my running whenever the trails start look like the same old same old.
It seems that getting lost is a universal pattern, which made it a perfect topic for an OOPSLA keynote talk.
I can talk about something other than science. As I write this, I am at a talk called "What is a Tree?", by computational artist Ira Greenberg. In it, Greenberg is telling his story of going from art to math -- and computation -- and back.
Greenberg started as a traditional artist, based in drawing and focused in painting. He earned his degrees in Visual Art, from Cornell and Penn. His training was traditional, too -- no computation, no math. He was going to paint.
In his earliest work, Greenberg was caught up in perception. He found that he could experiment only with the motif in front of him. Over time he evolved from more realistic natural images to images that were more "synthetic", more plastic. His work came to be about shape and color. And pattern.
Alas, he wasn't selling anything. Like all of us, he needed to make some money. His uncle told him to "look into computers -- they are the future". (This is 1993 or so...) Greenberg could not have been less interested. Working with computers seemed like a waste of time. But he got a computer, some software, and some books, and he played. In spite of himself, he loved it. He was fascinated.
Soon he got paying gigs at places like Conde Nast. He was making good money doing computer graphics for marketing and publishing folks. At the time, he said, people doing computer graphics were like mad scientists, conjuring works with mystical incantations. He and his buddies found work as a hired guns for older graphic artists who had no computer skills. They would stand over his should, point at the screen, and say in rapid-fire style, "Do this, do this, do this." "We did, and then they paid us."
All the while, Greenberg was still doing his "serious work" -- painting -- on side.
But he got good at this computer stuff. He liked it. And yet he felt guilty. His artist friends were "pure", and he felt like a sell-out. Even still, he felt an urge to "put it all together", to understand what this computer stuff really meant to his art. He decided to sell out all the way: to go to NYC and sell these marketable skills for big money. The time was right, and the money was good.
It didn't work. Going to an office to produce commercial art for hire changed him, and his wife notice. Greenberg sees nothing wrong with this kind of work; it just wasn't for him. Still, he liked at least one thing about doing art in the corporate style: collaboration. He was able to work with designers, writers, marketing folks. Serious painters don't collaborate, because they are doing their own art.
The more he work with computers in the creative process, the more he began to feel as if using tools like Photoshop and LightWave was cheating. They provide an experience that is too "mediated". With any activity, as you get better you "let the chaos guide you", but these tools -- their smoothness, their engineered perfection, their Undo buttons -- were too neat. Artists need fuzziness. He wanted to get his hands dirty. Like painting.
So Greenberg decided to get under the hood of Photoshop. He started going deeper. His artist friends thought he was doing the devil's work. But he was doing cool stuff. Oftentimes, he felt that the odd things generated by his computer programs were more interesting than his painting!
He went deeper with the mathematics, playing with formulas, simulating physics. He began to substitute formulas inside formulas inside formulas. He -- his programs -- produced "sketches".
At some point, he came across Processing, "an open source programming language and environment for people who want to program images, animation, and interactions". This is a domain-specific language for artists, implemented as an IDE for Java. It grew out of work done by John Maeda's group at the MIT Media Lab. These days he programs in ActionScript, Java, Flash, and Processing, and promotes Processing as perhaps the best way for computer-wary artists to get started computationally.
With his biographical sketch done, he moved on to the art that inspired his talk's title. He showed a series of programs that demonstrated his algorithmic approach to creativity. His example was a tree, which was a double entendré for his past as a painter of natural scenes and also for his embrace of computer science.
He started with the concept of a tree in a simple line drawing. Then he added variation: different angles, different branching factors. These created asymmetry in the image. Then he added more variation: different scales, different densities. Then he added more variation: different line thickness, "foliage" at the end of the smallest branches. With randomness elements in the program, he gets different outputs each time he runs the code. He added still more variation: color, space, dimension, .... He can keep going along as many different conceptual dimensions as he likes to create art. He can strive for verisimilitude, representation, abstraction, ... any artistic goal he might seek with a brush and oils.
Greenberg's artistic medium is code. He writes some code. He runs it. He change some things, and runs it again. This process is interactive with the medium. He evolves not a specific work of art, but an algorithm that can generate an infinite number of works.
I would claim that in a very important sense his work is the algorithm. For most artists, the art is in the physical work they produce. For Greenberg, there is a level of indirection -- which is, interestingly, one of the most fundamental concepts of computer science. For me, perhaps the algorithm is the artistic work! Greenberg's program is functional, not representational, and what people want to see is the art his programs produce. But code can be beautiful, too.
Context You are in an Interactive Performance, perhaps a play, using Scripted Dialogue.
Problem The performer speaking before you delivers a line incorrectly. The new line does not change the substance of the play, but it interrupts the linguistic flow.
Example Instead of saying "until the first of the year", the performer says as "for the rest of the year".
Forces You know your lines and want to deliver them correctly.
The author wrote the dialogue with a purpose in mind.
Delivering the line as you memorized it is the safest way for you to proceed, and also the safest route back on track.
BUT... Delivering the scripted line will call attention to the error. This may disconcert your partner. It will also break the mood for the audience.
So: Adapt your line to the set up. Respond in a way that is seamless to the audience, retains the key message of the story, and gets the dialogue back on track.
That is, catch what you are thrown.
Example Change your line to say "for the rest of the year?" instead of "until the first of the year?"
Related Patterns If the performer speaking before you misses a line entirely, or gets off the track of the Scripted Dialogue, deliver a Redirecting Line.
----
Postscript: This category of my blog is intended for software patterns and discussion thereof, but this is a pattern I just learned and felt a strong desire to right. I may well try to write Redirecting Line and maybe even the higher-level Scripted Dialogue and Interactive Performance patterns, if the mood strikes me and the time is available. I never thought of pattern language of performance when I signed on for this gig... And just so you know, I was the performer who mis-delivered his line in the example given above, where I first encountered Catch What You're Thrown.
Last Sunday was my fourth rehearsal as a newly-minted actor. It was our first run-through of the entire play on stage, and the first time the director had a chance to give notes to the entire cast. The whole afternoon, my mind was making connections between plays and programs -- and I don't mean the playbill. These thoughts follow from my experiences in the play and my experiences as a software developer. Here are a few.
Scenes and Modularity Each scene is a like a module that the director debugs. In some plays, the boundaries between scenes are quite clean, with a nice discrete break from one to the next. With a play on stage, the boundaries between scenes may be less clear.
In our play, scenes often blend together. Lights go down on one part of the stage and up on another, shifting the audience's attention, while the actors in the first scene remain in place. Soon, the lights shift back to the first and the action picks up where it left off. Plays work this way in part because they operate in limited real estate, and changing scenery can be time-consuming. But this also
It is easier to debug scenes that are discrete modules. Debugging scenes that run together is difficult for the same reasons that debugging code modules with leaky boundaries is. A change in one scene (say, repositioning the players) can affect the linked scene (say, by changing when and where a player enters).
Actors and Code If the director debugs a scene, then maybe the actors, their lines, and the props are like the code. That just occurred to me while typing the last section!
Time Constraints It is hard to get things right in a rush. Based on what he sees as the play executes, the director makes changes to the content of the show. He also refactors: rearranging the location of a prop or a player, either to "clean things up" or to facilitate some change he has in mind. It takes time to clean things up, and we only know that something needs to be changed as we watch the play run, and think about it.
Mock Objects and Stand-Ins When rehearsing a scene, if you don't have the prop that you will use in the play itself, then use something to stand in its place. It helps you get used to the the fact that something will be there when you perform, and it helps the director remember to take into account its use and placement. You have to remember to have it at the right time in the right place, and return it to the prop table when it's not in use.
A good mock prop just needs to have some of the essential features of the actual prop. When rehearsing a scene in which I will be carrying some groceries to the car, I grabbed a box full of odds and ends out of some office. It was big enough and unwieldy enough to help me "get into the part".
Conclusion for Now The relationship between software and plays or movies is not a new idea, of course. I seem to recall a blog entry a couple of years ago that explored the analogy of developing software as producing a film, though I can't find a link to it just now. Googling for it led me to a page on Ward's wiki and to two entries on the Confused of Calcutta blog. More reading for me... And of course there is Brenda Laurel's seminal Computers As Theatre. You really should read that!
Reading is a great way to learn, but there is nothing quite like living a metaphor to bring it home.
The value that comes from making analogies and metaphors comes in what we can we learn from them. I'm looking forward to a couple of weeks more of learning from this one -- in both directions.
Gerald Weinberg's recent blog Setting (and Character): A Goldilocks Exercise describes a writing exercise that I've mentioned here as a programming exercise, a pedagogical pattern many call Three Bears. This is yet another occurrence of a remarkably diverse pattern.
Weinberg often describes exercises that writers can use to free their minds and words. It doesn't surprise me that "freeing" exercises are built on constraints. In one post, Weinberg describes The Missing Letter, in which the writer writes (or rewrites) a passage without using a randomly chosen letter. The most famous example of this form, known as a lipogram, is La disparition, a novel written by Georges Perec without an using the letter 'e' -- except to spell the author's name on the cover.
When I read that post months ago, I immediately thought of creating programming exercises of a similar sort. As I quoted someone in a post on a book about Open Court Publishing, "Teaching any skill requires repetition, and few great works of literature concentrate on long 'e'." We can design a set of exercises in which the programmer surrenders one of her standard tools. For instance, we could ask her to write a program to solve a given problem, but...
Recursion is the usual path for students to learn how to repeat actions without a for statement, but I don't think most students get recursion the way most folks teach it. Learning it with a rich data type makes a lot more sense.
Of course, one can start with an language that provides only the most meager set of base types, thus forcing one to build up nearly all the abstractions demanded by a problem. Scheme feels like that to most students, but only a few of mine seem to grok how much they can learn about programming by working in such a language. (And it's of no comfort to them that Church built everything out of functions in his lambda calculus!)
This list operates at the level of programming construct. It is just the beginning of the possibilities. Another approach would be to forbid the use of a data structure, a particularly useful class, or an individual base type. One could even turn this idea into a naming challenge by hewing close to Weinberg's exercise and forbidding the use of a selected letter in identifiers. As an instructor, I can design an exercise targeted at the needs of a particular student or class. As a programmer, I can design an exercise targeted at my own blocks and weaknesses. Sometimes, it's worth dusting off an old challenge and doing it for it's own sake, just to stay sharp or shake off some rust.
Back in 2002, I had a sabbatical (which are, for political reasons, called "professional development assignments" here) to document some of the patterns of programs that are written in a functional style. So much good work had been done by then on object-oriented patterns, and a few people had begun to describe OO patterns that were motivated by functional programming techniques. But few people had begun to document functional programming patterns. I had a feeling that something useful could come from moving into that space. In the end I didn't make the sort of progress I had hoped, but I did learn a lot that has continued to influence my teaching and research.
One of the areas explored as a part of that project was refactoring functional programs. I believe that refactorings are the behavioral side of patterns, and by looking at work on existing work on functional refactorings I hoped to speed my search for patterns. There hadn't been much work done on refactoring functional programs at that time, but I wasn't alone in thinking of it -- Simon Thompson and Claus Reinke were just beginning their quite productive research program on the same topic. That work, like most of the work that deals with patterns and refactoring in functional programming, focused more on the language-processing side of the topic, considering refactorings as program transformation in the vein of compiler optimizations. What seems to me still to be missing is a look at refactoring of functional programs from the software developer's perspective: I have a piece of code that I want to restructure in order to improve its design, or in order to facilitate the next addition to the program. What do I do next?
Noel Welsh recently wrote a blog entry called Refactoring Functional Programs that makes a very nice contribution in the space. Noel is just the sort of person who should be documenting FP patterns and refactorings, a practicing developer who works primarily in a functional or mostly functional language and who is growing a significant software system over time. His essay talks about a sequence of refactorings that he applied to his system, a web application framework, which moved one of its modules from a long-ish, overly complex, repetitive piece of code to something shorter, simpler, and well-factored. You will enjoy reading the article even if you don't program in Scheme, because Noel explains the thinking he did as he attacked this piece of code, including an alternative step that he considered but rejected due to the forces that affect his system.
For the record, his three refactorings were these. The names are part mine, part his:
One of the things I like about this story is how it makes a "round-trip" to CPS and back, using the trip to change the program's design in a way that might have been inaccessible otherwise. I teach my students a similar "refactoring pattern" when teaching them functional programming, make a round-trip through Mutual Recursion, by way of Program Derivation, to convert a messy one-procedure solution into a clean and one-elegant one-procedure solution.
I hope that other developers using functional programming in the trenches will follow Noel's lead and document some of the patterns and refactorings that they discover in their code and process. More than anything else, this sort of pragmatic, nuts-and-bolts writing will help to increase the accessibility of functional programming style to a wider audience of programmers.
Browsing through several overflowing mailboxes from various agile software development lists -- thank the mail gods for procmail -- I ran across three messages that made save them for later reflection or use in a class.
On the extreme programming mailing list, Laurent Bossavit wrote:
> How do you deal with [a change breaks lots of tests]?See it as an opportunity. A single change breaking a lot of tests means that your design has excessive coupling, *or* that your unit tests are written at too low a level of abstraction. This is an important and valuable thing to have learned about your code and tests.
Most of the time, we treat unexpected obstacles as problems -- either problems to solve, or problems to avoid. When we operate under time pressure, we usually try to avoid such obstacles. Students often find themselves in a bind for time and so seek to avoid problems, rather using them as an opportunity to make their programs better. This is another reason to start assignments early: to have time to be opportunistic on unexpected chances to learn!
Time pressure isn't the only reason students avoid problems. Some are driven by grades, in order to impress potential employers. (Maybe this will change in a world not driven by "getting a job".) Others are simply afraid to take the risk. Our school system does a pretty good job of beating risk-taking behavior out of students by the time they reach the university, and universities often don't do enough to undo this before they graduate into professional careers.
On the agile content of Laurent's comment, he is spot-on, of course. All those broken tests are excellent feedback on a weakness in either the system or the tests. Listen to the code.
On the Crystal Clear mailing list (dedicated to discussing "the ultralight Crystal Clear software development methodology"), methodology creator Alistair Cockburn wrote:
"Deciding what to build" is my new replacement phrase for "requirements". The word "requirements" tends to imply
- that [someone can] correctly locate and pluck them,
- that they are "true"
None of those are correct. They don't already pre-exist so they can't be "plucked", [no one is] in that unique position [to locate and pluck them], and they aren't "true".
which is why I nowadays prefer to talk about "deciding what to build".
I wish that more people -- software engineers, programmers, and consumers of software and software development services alike -- would think like this! "Gathering requirements" is a metaphor that goes wrong both on 'gathering' and on 'requirements'. "Deciding what to build" creates a completely different mental image and sets up a completely different set of performance expectations. As Alistair tells it, "deciding what to build" is a negotiation, not an exam question about Platonic ideals that has a correct answer. A negotiation can take into account many factors, including benefits, costs, preferences, and time.
The developer and customer can then record the results of their negotiation in a "contract" of whatever form they prefer. If they are so inclined, the contract can take the form of a set of tests that captures what the developer will deliver, say, FIT tests. When one side needs to "break the contract", the negotiation should have specified relative preferences that enable the parties to arrive at a new understanding of the system to be built. More negotiation -- not "adding a requirement" or "not delivering a requirement".
Finally, for a touch of humor, I give you this passage from a message to the refactoring mailing list from Buddha Buck:
Our team is considering implementing the refactoring "Replace C++ With Language With Good Refactoring Tool Support". It's a major refactoring, and full implementation might take months, if we decide to do it.
There have to be some pleasant steps to execute in this refactoring, and some even more pleasant milestones. That last rm *.cpp has to feel good.
More seriously, I think there is a great opportunity to write refactorings that aren't about software architecture and code. The patterns of Christopher Alexander begat the software patterns world, which caused many of us to write the patterns of other kinds of systems, including music, management, and pedagogy. In many software circles, refactorings are behavior-preserving modifications that target the patterns of the domain. If we write patterns of management or pedagogy, then why not write refactorings that help people prepare their environments for disruptive change? An interesting question comes to mind: what does it mean for a change to a management system to "preserve behavior"? This seems like a very cool avenue for some thought, even if it hits a dead end.
This week I ran across a link to an old essay called Good Writing, by Marc Raibert. By now I shouldn't be so happy to be reminded how much good programming practice is similar to good writing in general. But I usually am. The details of Raibert's essay are less important to me than some of his big themes.
Raibert starts with something that people often forget. To write well, one must ordinarily want to write well and believe that one can. Anyone who teaches introductory computer science knows how critical motivation and confidence are. Many innovations in CS1 instruction over the years have been aimed at helping students to develop confidence in the face of what appear to be daunting obstacles, such as syntax, rigor, and formalism. Much wailing and gnashing of teeth has followed the slowly dawning realization that students these days are much less motivated to write computer programs than they have been over most of the last thirty years. Again, many innovations and proposals in recent years have aimed at motivating students -- more engaging problems, media computation, context in the sciences and social sciences, and so on. These efforts to increase motivation and confidence are corporate efforts, but Raibert reminds us that, ultimately, the individual who would be a writer must hold these beliefs.
After stating these preconditions, Raibert offers several pieces of advice that apply directly to computing. Not surprisingly, my favorite was his first: Good writing is bad writing that was rewritten. This fits nicely in the agile developer's playbook. I think that few developers or CS teachers are willing to say that it's okay to write bad code and then rewrite. Usually, when folks speak in terms of do the simplest thing that will work and refactor mercilessly, they do not usually mean to imply that the initial code was bad, only that it doesn't worry inordinately about the future. But one of the primary triggers for refactoring is the sort of duplication that occurs when we do the simplest thing that will work without regard for the big picture of the program. Most will agree that most such duplication is a bad thing. In these cases, refactoring takes a worse program and creates a better one.
Allowing ourselves to write bad code empowers us, just as it empowers writers of text. We need not worry about writing the perfect program, which frees us to write code that just works. Then, after it does, we can worry about making the program better, both structurally and stylistically. But we can do so with the confidence that comes from knowing that the substance of our program is on track.
Of course, starting out with the freedom to write bad code obligates us to re-write, to refactor, just as it obligates writers of text to re-write. Take the time! That's how we produce good code reliably: write and re-write.
I wish more of my freshmen would heed this advice:
The first implication is that when you start a new [program], there is nothing wrong with using bad writing. Your goal when you start is to get your ideas down on paper in any form you can.
For the novice programmer, I do not recommend writing ungrammatical or "stream of consciousness" code, but I do encourage them to take the ideas they have after having thought about the problem and expressing them in code. The best way to find out if an idea is a good one is to see it run in code.
Raibert's other advice also applies. When I read Spill the beans fast, I think of making my code transparent. Don't hide its essence in subterfuge that makes me seem clever; push its essence out where all can see it and understand the code. Many of the programmers whose code I respect most, such as Ward Cunningham, write code that is clear, concise, and not at all clever. That's part of what makes it beautiful.
Don't get attached to your prose is essential when writing prose, and I think it applies to code as well. Just because you wrote a great little method or class yesterday doesn't mean that it should survive in your program of tomorrow. While programming, you discover more about your problem and solution than you knew yesterday. I love Raibert's idea of a PRIZE_WINNING_STUFF.TXT file. I have a directory labeled playground/ where I place all the little snippets I've built as simple learning experiments, and now I think I need to create a winners/ directory right next to it!
Raibert closes with the advice to get feedback and then to trust your readers. A couple of months back I had a couple of entries on learning from critics, with different perspectives from Jerry Weinberg and Alistair Cockburn. That discussion was about text, not code (at least on the surface). But one thing that we in computer science need to do is to develop a stronger culture of peer review of our code. The lack of one is one of the things that most differentiates us from other engineering disciplines, to which many in computing look for inspiration. I myself look more to the creative disciplines for inspiration than to engineering, but on this the creative and engineering disciplines agree: getting feedback, using it to improve the work, and using it to improve the person who made the work are essential. I think that finding ways to work the evaluation of code into computer science courses, from intro courses to senior project courses, is a path to improving CS education.
This last bit of advice from Raibert is also timely, if bittersweet for me... In just a few days, PLoP 2007 begins. I am quite bummed that I won't be able to attend this year, due to work and teaching obligations. PLoP is still one of my favorite conferences. Patterns and writers' workshops are both close to my heart and my professional mind. If you have never written a software pattern or been to PLoP, you really should try both. You'll grow, if only when you learn how a culture of review and trust can change how you think about writing.
The good news for me is that OOPSLA 2007, which I will be attending, features a Mini-PLoP. This track consists of a pattern writing bootcamp, a writers' workshop for papers in software development, and a follow-up poster. I hope to attend the writers' workshop session on Monday, even if only as a non-author who pledges to read papers and provide feedback to authors. It's no substitute for PLoP, but it's one way to get the feeling.
No, I've not become homicidal. That is the title of a recent book about the Open Court Publishing Company, which according to its subtitle "fought the culture of American education" by trying to change how our schools teach reading and mathematics. Blouke Carus, the creator of Open Court's reading program, sought to achieve an enviable goal -- engagement with and success in the world of great ideas for all students -- in a way that was beholden to neither the traditionalist "back to basics" agenda nor the progressivist "child-centered" agenda. Since then, the reading series has been sold to McGraw-Hill.
Thanks to the creator of the TeachScheme! project, Matthias Felleisen, I can add this book to my list of millions. He calls Let's Kill and Dick and Jane "TeachScheme! writ large". Certainly there are differences between the K-8 education culture and the university computer science culture, but they share enough commonalities to make reform efforts similarly difficult to execute. As I have noted before, universities and their faculty are a remarkably conservative lot. TeachScheme! is a principled, comprehensive redefinition of introductory programming education. In arguing for his formulation, Felleisen goes so far as to explain why Structure and Interpretation of Computer Programs -- touted by many, including me, as the best CS book ever written -- is not suitable for CS 1. (As much as I like SICP, Matthias is right.)
But TeachScheme! has not succeeded in the grand way its implementors might have hoped, for many of the reasons that Open Court's efforts have come up short of its founders' goals. Some of the reasons are cultural, some are historical, and some are probably strategic.
The story of Open Court is of immediate interest to me for our state's interest in changing K-12 math and science education in a fundamental way, a reform effort that my university has a leading role in, and which my department and I have a direct interest in. We believe in the need for more and better computer scientists and software developers, but university CS enrollments remain sluggish. Students who are turned off to science, math, and intellectual ideas in grade school aren't likely to select CS as a major in college... Besides, like Carus, I have a great interest in raising the level of science and math understanding across the whole population.
This book taught me a lot about what I had understood only incompletely as an observer of our education system. And I appreciated that it avoided the typical -- and wrong -- conservative/liberal dichotomy between the traditional and progressive approaches. America's education culture is a beast all its own, essentially anti-intellectual and exhibiting an inertia borne out of expectations, habit, and a lack of will and time to change. Changing the system will take a much more sophisticated and patient approach than most people usually contemplate.
Though I have never developed a complete curriculum for CS 1 as Felleisen has, I have long aspired to teaching intro CS in more holistic way, integrating the learning of essential tools with higher-level design skills, built on the concept of a pattern language. So Open Court's goals, methods, and results all intrigue me. Here are some of the ideas that caught my attention as I read the story of Open Court:
A teacher must dare to be different! She must pull away from monotonous repetition of, 'Today we are going to write a story.' Most children view that announcement with exactly what it deserves, and there are few teachers who are not aware of what the reactions are.
s/story/program/* and s/children/students/* to get a truth for CS instructors such as me.
The quality of the Open Court program was a substantive strength and a marketing weakness. It required teachers to be conversant with a variety of methods. And the program worked best when used as a system... Teachers accustomed to trying a little of this and a little of that were likely to be put off by an approach that did not lend itself to tinkering.
I guess I'm not the only person who has trouble sticking to the textbook. To be fair to us tinkerers, systematic integrated instructional design is so rare as to make tinkering a reasonable default stance.
Thus Open Court's usual problem was not that it contradicted teachers' ideology, but that it violated their routine.
Old habits dies hard, if at all.
... the learned professions ...[in which] adaptation to the expectations of one's peers requires continual growth in knowledge and competence.
In the professions, we focus not only on level of knowledge but also on the process of continuously getting better.
There are circumstances in which it is best to package our revolutionary aspirations in harmless-looking exteriors.... We should swallow our pride and let [teachers] think we are bland and acceptable. We should fool them and play to their complacent pieties, But we should never for a moment fool ourselves.
Be careful what you pretend to be.
Then we obsess about covering all the material, made harder by the inclusion of all this new material.
I've seen this happen to software patterns in CS classrooms. It was sad. I usually think that we elementary patterns folks haven't done a good enough job yet, but Open Court's and TeachScheme!'s experiences do not encourage me to think that it will be easy to do well enough.
In an academic metaphor, [Open Court's] people had been the liberal-arts students looking down on the business school. But now that they needed business-school expertise, they were unable to judge it critically.
Maybe a so-called "liberal education" isn't broad enough if it leaves the recipient unable to think deeply in an essential new context. In today's world, both business and technology are essential components of a broadly applicable education.
Teaching any skill requires repetition, and few great works of literature concentrate on long "e".
My greatest inspiration in this vein is the Suzuki literature developed for teaching violin and later piano and other instruments. I've experienced the piano literature first hand and watched my daughters work deep into the violin literature. At the outset, both use existing works (folk tunes, primarily) whenever appropriate, but they also include carefully designed pieces that echo the great literature we aspire to for our students. As the student develops technical skill, the teaching literature moves wholly into the realm of works with connection to the broader culture. My daughters now play real violin compositions from real composers.
TeachScheme! is a worthy model in this regard. It has worked hard to train teachers in its approach, to provide tangible support, and to build a community of teachers.
In my own work on elementary patterns, my colleague and friend Robert Duvall continually reminds us all of the need for providing practical support to instructors who might adopt our ideas -- if only they had the instructional tools to make a big change in how they teach introductory programming.
In an odd way, this reminds me of Drawing on the Right Side of the Brain, with its precept that we should draw what we see, not what we think we see.
Let's Kill Dick and Jane is a slim volume, a mere 155 pages, and easy to read. It's not perfect, neither in its writing nor in its analysis, but it tells an important story well. I recommend it to anyone with aspirations of changing how we teach computer science to students in the university or high school. I also recommend it to anyone who is at all interested in the quality of our educational system. In a democracy such as the U.S., that should be everyone.
David Altenburg gives a nice example of a pattern you'll find in functional programs, which he calls Enumerate, Map, Filter, Accumulate. This isn't the typical snappy pattern name, but it does show deference to Chapter 2 of Structure and Interpretation of Computer Programs, which discusses in some detail this way of processing a stream of data. I like this blog entry because it illustrates nicely a difference between how functional programmers think and how OO programmers think. He even gives idiomatic Java and Ruby code to demonstrate the difference more clearly. Seeing the Ruby example also makes clear just how powerful first-order blocks can be in an OO language.
SICP is a veritable catalog of the patterns of programs written in a functional style. They aren't written in Alexander's pattern style, but they are patterns nonetheless.
(In a snarkier mood, I might say: I am sure some Lisp aficionado will explain that Enumerate, Map, Filter, Accumulate isn't a pattern because we could define a enumapfilacc macro and make it go away...)
I haven't written much in anticipation of OOPSLA 2007, but not because I haven't been thinking about it. In years when I have had a role in content, such as the 2004 and 2005 Educators' Symposia or even the 2006 tutorials track, I have been excited to be deep in the ideas of a particular part of OOPSLA. This year I have blogged just once, about the December planning meeting. (I did write once from the spring planning meeting, but about a movies.) My work this year for the conference has been in an administrative role, as communications chair, which has focused on sessions and schedules and some web content. Too be honest, I haven't done a very good job so far, but that is a subject for another post. For now, let's just say that I have not been a very good Mediator nor a good Facade.
I am excited about some of the new things we are doing this year to get the word out about the conference. At the top of this list is a podcast. Now, podcasts have been around for a while now, but they are just now becoming a part of the promotional engine for many organizations. We figured that hearing about some of the cool stuff that will happen at OOPSLA this year would complement what you can read on the web. So we arranged to have two outfits, Software Engineering Radio and DimSumThinking, co-produce a series of episodes on some of the hot topics covered at this year's conference.
Our first episode, on a workshop titled No Silver Bullet: A Retrospective on the Essence and Accidents of Software Engineering, organized by Dennis Mancl, Steven Fraser, and Bill Opdyke, is on-line at the OOPSLA 2007 Podcast page. Stop by, give it a listen, and subscribe to the podcast's feed so that you don't miss any of the upcoming episodes. (We are available in iTunes, too.) We plan to role new interviews out every 7-10 for the next few months. Next up is a discussion of a Scala tutorial with Martin Odersky, due out on July 16.
If you would like to read a bit more about the conference, check out conference chair Richard Gabriel's The (Unofficial) How To Get Around OOPSLA Guide, and especially his ooPSLA Impressions. As I've written a few times, there really isn't another conference like OOPSLA. Richard's impressions page does a good job communicating just how, mostly in the words of people who've been to OOPSLA and seen it.
While putting together some of his podcast episodes, Daniel Steinberg of DimSumThinking ran into something different than usual: fun.
I've done three interviews for the oopsla podcast -- every interviewee has used the same word to describe OOPSLA: fun. I just thought that was notable -- I do a lot of this sort of thing and that's not generally a word that comes up to describe conferences.
And that fun comes on top of the ideas and the people you will encounter, that will stretch you. We can't offer a Turing Award winner every year, but you may not notice with all the intellectual foment. (And this year, we can offer John McCarthy as an invited speaker...)
I remember back in my early years teaching (*) I had a student who came in to ask a question about a particular error message she had received from our Pascal compiler. She had some idea of what caused it, and she wanted to know what it meant. It was a pretty advanced error, one we hadn't reached the point of making in class, so I asked her how she had managed to bump into it. Easy, she said; she was intentionally creating errors in her program so that she could figure out what sort of error messages would result.
If you teach programming for very long, you are bound to encounter such a student. She was doing fine in class but was afraid that she was having life too easy and so decided to use her time productively -- creating errors that she could learn to debug and maybe even anticipate.
I've written many times before about practice, including practice for practice's sake. That entry was about the idea of creating "valueless software", which one writes as a learning exercise, not for anyone's consumption. But my forward-thinking student was working more in the vein of fixin' what's broke, in which one practices in an area of known weakness, with the express purpose of making that part of one's game strong. My student didn't know many of the compiler error messages that she was going to face in the coming weeks, so she set out to learn them.
I think that she was actually practicing a simple form of an even more specific learning pattern: consciously seeking out, even creating, challenges to conquer. Make a Mess, Clean it Up!, is a neat story about an example of this pattern in the history of the Macintosh team. There, Donn Denman talks about Burrell Smith's surprising way of getting better at Defender, a video game played by the Mac programmers as a way to relax or pump themselves up:
Instead of avoiding the tough situations, he'd immediately create them, and immediately start learning how to handle the worst situation imaginable. Pretty soon he would routinely handle anything the machine could throw at him.
He'd lose a few games along the way, but soon he was strong in areas of the game that his competitors may not have even encountered before -- because they had spent time avoiding difficult times! Denman saw in this game-playing behavior something he recognized in Smith's life as a programmer: he
... likes challenges so much that he actually seeks them out and consciously creates them. In the long run, this approach makes sense. He seems to aggressively set up challenging situations throughout his life. Then, when life throws him a curve ball, he'll swing hard, and knock it out of the park.
The article uses two metaphors for this pattern: make a mess so that you can clean it up, and choose to face tough situations so that you are ready for the curve balls life throws you. (I guess those tough situations must be akin the nasty breaking stuff of a major-league pitcher.) My title for this entry offers a third metaphor: digging yourself into a hole so that you can how to get out of a hole. As much a baseball fan as I was growing up, the metaphor of digging oneself into a hole was the more common. Whatever it's name, the idea is the same.
I find that I'm more likely to apply this pattern in some parts of my life than others. In programming, I can recover from bad situations by re-compiling, re-booting, or at worst reinstalling. In running, I can lose all the races I want, or come up short in a training session all I want -- so long as I don't put my body at undue risk. The rest of life, the parts that deal with other people, require some care. It's hard to create an environment in which I can screw up my interpersonal relationships just so that I can learn how to get out of the mess. There's a different metaphor for such behavior -- burning bridges -- that connotes its irreversibility. Besides, it's not right to treat people as props in my game. I suppose that this is a place in which role play can help, though artificial situations can go only so far.
Where games, machines, and tools are concerned, though, digging a deep hole just for the challenge of getting out of it can be a powerful way to learn. Pretty soon, you can find yourself as master of the machine.
----
(*) Yikes, how old does that make me sound?
An idea is a feat of association.
-- Robert Frost
Yesterday I went to a talk by Roy Behrens, an earlier talk of whose I enjoyed very much and blogged about. That time he talked about teaching as a "subversive inactivity", and this time he spoke more on the topic of his scholarly interest, in creativity and design, ideas and metaphors, similarities and differences, even camouflage! Given that these are his scholarly interests, I wasn't surprised that this talk touched on some of the same concepts as his teaching talk. There are natural connection between how ideas are formed at the nexus os similarity and difference and how one can best help people to learn. I found this talk energizing and challenging in a different sort of way.
In the preceding paragraph, I first wrote that Roy "spoke directly on the topic of his scholarly interest", but there was little direct about this talk. Instead, Roy gave us parallel streams of written passages and images from a variety of sources. This talk felt much like an issue of his commonplace book/journal Ballast Quarterly Review, which I have blogged about before. The effect was mesmerizing, and it had its intended effect in illustrating his point: that the human mind is a connection-making machine, an almost unwilling creator of ideas that grow out of the stimuli it encounters. We all left the talk with new ideas forming.
I don't have a coherent, focused essay on this talk yet, but I do have a collection of thoughts that are in various stages of forming. I'll share what I have now, as much for my own benefit as for what value that may have to you.
Similarity and difference, the keys to metaphor, matter in the creation of software. James Coplien has written an important book that explicates the roles of commonality analysis and variability analysis in the design of software that can separate domain concerns into appropriate modules and evolve gracefully as domain requirements change. Commonality and variability; similarity and difference. As one of Roy's texts pointed out, the ability to recognize similarity and difference is common to all practical arts -- and to scientists, creators, and inventors.
The idea of metaphor in software isn't entirely metaphorical. See this paper by Noble, Biddle, and Tempero that considers how metaphor and metonymy relate to object-oriented design patterns. These creative fellows have explored the application of several ideas from the creative arts to computing, including deconstruction and postmodernism.
To close, Roy showed us the 1952 short film Blacktop: A Story of the Washing of a School Play Yard. And that's the story it told, "with beautiful slow camera strides, the washing of a blacktop with water and soap as it moves across the asphalt's painted lines". This film is an example of how to make something fabulous out of... nothing. I think the more usual term he used was "making the familiar strange". Earlier in his talk he had read the last sentence of this passage from Maslow (emphasis added):
For instance, one woman, uneducated, poor, a full-time housewife and mother, did none of these conventionally creative things and yet was a marvelous cook, mother, wife, and home-maker. With little money, her home was somehow always beautiful. She was a perfect hostess. Her meals were banquets, her taste in linens, silver, glass crockery and furniture was impeccable. She was in all these areas original, novel, ingenious, unexpected, inventive. I learned from her and others like her that a first-rate soup is more creative than a second-rate painting, and that, generally, (un)cooking or parenthood or making a home could be creative while poetry need not be; it cold be uncreative.
Humble acts and humble materials can give birth to unimagined creativity. This is something of a theme for me in the design patterns world, where I tell people that even novices engage in creative design when they write the simplest of programs and where so-called elementary patterns are just as likely to give rise to creative programs as Factory or Decorator.
Behrens's talk touched on two other themes that run through my daily thoughts about software, design, and teaching. One dealt with tool-making, and the other with craft and limitations.
At one point during the Q-n-A after the talk, he reminisced about Let's Pretend, a radio show from his youth which told stories. The value to him as a young listener lay in forcing -- no, allowing -- him to create the world of the story in his own mind. Most of us these days are conditioned to approach an entertainment venue looking for something that has already been assembled for us, for the express purpose of entertaining ourselves. Creativity is lost when our minds never have the opportunity to create, and when our minds' ability to create atrophies from disuse. One of Roy's goals in teaching graphic design students is to help students see that they have the tools they need to create, to entertain.
This is true for artists, but in a very important sense it is true for computer science students, too. We can create. We can build our own tools--our own compilers, our own IDEs, our own applications, our own languages... anything we need! That is one of the great powers of learning computer science. We are in a new and powerful way masters of our own universe. That's one of the reasons I so enjoy teaching Programming Languages and compilers: because they confront CS students directly with the notion that their tools are programs just like any other. You never have to settle for less.
Finally, may favorite passage from Roy's talk plays right into my weakness for the relationship between writing and programming, and for the indispensable role of limitation in creativity and in learning how to create. From Anthony Burgess:
Art begins with craft, and there is no art until craft has been mastered. You can't create until you're willing to subordinate the creative impulses to the constriction of a form. But the learning of craft takes a long time, and we all think we're entitled to shortcuts.... Art is rare and sacred and hard work, and there ought to be a wall of fire around it.
One of my favorite of my blog posts is from March 2005, when I wrote a piece called Patterns as a Source of Freedom. Only in looking back now do I realize that I quoted Burgess there, too -- but only the sentence about willing subordination! I'm glad that Roy gave the context around that sentence yesterday, because it takes the quote beyond constriction of form to the notion of art growing out of craft. It then closes with that soaring allusion. Anyone who has felt even the slightest sense of creating something knows what Burgess means. We computer scientists may not like to admit that what we do is sometimes art, and that said art is rare and sacred, but that doesn't change reality.
Good talk -- worth much more in associations and ideas than the lunch hour it cost. My university is lucky to have Roy Behrens, and other thinkers like him, on our faculty.
At SIGCSE a couple of weeks ago, I attended an interesting pair of complementary panel sessions. I wrote about one, Ten Things I Wish They Would Have Told Me..., in near-real time. Its complement was a panel called "It Seemed Like a Good Idea at the Time". Here, courageous instructors got up in front of a large room full of their peers to do what for many is unthinkable: tell everyone about an idea they had that failed in practice. When the currency of your profession is creating good ideas, telling everyone about one of your bad ideas is unusual. Telling everyone that you implemented your bad idea and watched it explode, well, that's where the courage comes in.
My favorite story from the panel was from the poor guy who turned his students loose writing Java mail agents -- on his small college's production network. He even showed a short video of one of the college's IT guys describing the effects of the experiment, in a perfect deadpan. Hilarious.
We all like good examples that we can imitate. That's why we are all drawn to panels such as "Ten Things..." -- for material to steal. But other than the macabre humor we see in watching someone else's train wreck, what's the value in a panel full of bad examples?
The most immediate answer is that we may have had the same idea, and we can learn from someone else's bad example. We may decide to pitch the idea entirely, or to tweak our idea based on the bad results of our panelist. This is useful, but the space of ideas -- good and bad -- is large. There are lots of ways to tweak a bad idea, and not all of them result in a good idea. And knowing that an idea is bad leaves us with the real question unanswered: Just what should we do?
(The risk that the cocky among us face is the attitude that says, "Well, I can make that work. Just watch." This is the source of great material for the next "It Seemed Like a Good Idea at the Time" panel!)
All this said, I think that failed attempts are invaluable -- if we examine them in the right way. Someone at SIGCSE pointed out that negative examples help us to create a framework in which to validate hypotheses. This is how science works from failed experiments. This idea isn't news to those of us who like to traffic in patterns. Bad attempts put us on the road to a pattern. We discover the pattern by using the negative example to identify the context our problem lies and the forces that drive a solution. Sometimes a bad idea really was a good idea -- had it only been applied in the proper context, where the forces at play would have resolved themselves differently. We usually only see these patterns after looking at many, many examples, both good and bad, and figuring what makes them tick.
A lot of CS instruction aims to expose students to lots of examples, in class and in programming assignments. Too often, though, we leave the student discover context and forces on their own, or to learn them implicitly. This is one of the motivations of my work on elementary patterns, to help guide students in the process of finding patterns in their and other people's experiences.
A couple of nights I was able to see a performance by the Merce Cunningham Dance Company here on campus. This was my first exposure to Cunningham, who is known for his exploration of patterns in space and sound. My knowledge of the dance world is limited, but I would call this "abstract dance". My wife, who has some background in dance, might call it something else, but not "classical"!
The company performed two pieces for us. The first was called eyeSpace, and it seemed the more avant garde of the two. The second, called Split Sides, exemplifies Cunningham's experimental mindset quite well. From the company's web site:
Split Sides is a work for the full company of fourteen dancers. Each design element was made in two parts, by one or two artists, or, in the case of the music, by two bands. The order in which each element is presented is determined by chance procedure at the time of the performance. Mathematically, there are thirty-two different possible versions of Split Sides.
And a mathematical chance it was. At intermission, the performing arts center's director came out on stage with five people, most local dancers, and a stand on which to roll a die. Each of the five assistants in turn rolled the die, to select the order of the five design elements in question: the pieces, the music, the costumes, the backgrounds, and a fifth element that I've forgotten. This ritual heightened the suspense for the audience, even though most of us probably had never seen Split Sides before, and must have added a little spice for the dancers, who do this piece on tour over and over.
In the end, I preferred the second dance and the second piece of music (by Radiohead), but I don't know to what extent this enjoyment derived from one of the elements or the two together. Overall, I enjoyed the whole show quite a bit.
Not being educated in dance, my take on this sort of performance is often different from the take of someone who is. In practice, I find that I enjoy abstract dance even more than classical. Perhaps this comes down to me being a computer scientist, an abstract thinker who enjoys getting lost in the patterns I see and hear on stage. A lot of fun comes in watching the symmetries being broken as the dance progresses and new patterns emerge.
Folks trained in music may sometimes feel differently, if only because the patterns we see in abstract dance are not the patterns they might expect to see!
Seeing the Merce company perform reminded of a quote about musician Philip Glass, which I ran across in the newspaper while in Carefree for ChiliPLoP:
... repetition makes the music difficult to play."As a musician, you look at a Philip Glass score and it looks like absolutely nothing," says Mark Dix, violist with the Phoenix Symphony, who has played Glass music, including his Third String Quartet.
"It looks like it requires no technique, nothing demanding. However, in rehearsal, we immediately discovered the difficulty of playing something so repetitive over so long a time. There is a lot of room for error, just in counting. It's very easy to get lost, so your concentration level has to be very high to perform his music."
When we work in the common patterns of our discipline -- whether in dance, music, or software -- we free our attention to focus on the rest of the details of our task. When we work outside those patterns, we are forced to attend to details that we have likely forgotten even existed. That may make us uncomfortable, enough so that we return to the structure of the pattern language we know. That's not necessarily a bad thing, for it allows us to be productive in our work.
But there can be good in the discomfort of the broken pattern. One certainly learns to appreciate the patterns when they are gone. The experience can remind us why they are useful, and worth whatever effort they may require. The experience can also help us to see the boundaries of their usefulness, and maybe consider a combination, or see a new pattern.
Another possible benefit working without the usual patterns is hidden in Dix's comments above. Without the patterns, we have to concentrate. This provides a mechanism whereby we attend to details and hone our concentration, our attention to detail. I think it also allows us to focus on a new technique. Programming at the extremes, without an if-statement, say, forces you to exercise the other techniques you know. The result may be that you are a better user of polymorphism even after you return to the familiar patterns that include imperative selection.
And I can still enjoy abstract dance and music as an outsider.
There is another, more direct connection between Cunningham's appearance and software. He has worked with developers to create a new kind of choreography software called DanceForms 1.0. While his troupe was in town, they asked the university to try to arrange visits with computer science classes to discuss their work. We had originally planned for them to visit our User Interface Design course and our CS I course (which has a media computation theme), but schedule changes on our end prevented that. I had looked forward to hearing Cunningham discuss what makes his product special, and to see how they had created "palettes of dance movement" that could be composed into dances. That sounds like a language, even if it doesn't have any curly braces.
Last week I ran across this quote by noted rocker Elvis Costello:
Writing about music is like dancing about architecture -- it's really a stupid thing to want to do.
My immediate reaction was an intense no. I'm not a dancer, so my reaction was almost exclusively to the idea of writing about music or, by extension, other creative activities. Writing is the residue of thinking, an outward manifestation of the mind exploring the world. It is also, we hope, occasionally a sign of the mind growing, and those who read can share in the growth.
I don't imagine that dancing is at all like writing in this respect.
Perhaps Costello meant specifically writing about music and other pure arts. But I did study architecture for a while, and so I know that architecture is not a pure art. It blends the artistic and purely creative with an unrelenting practical element: human livability. People have to be able to use the spaces that architects create. This duality means that there are two levels at which one can comment on architecture, the artistic and the functional. Costello might not think much of people writing about the former, but he may allow for the value in people writing about the latter.
I may be overthinking this short quote, but I think it might have made more sense for Costello to have made this analogy: "Writing about music is like designing a house about dancing ...". But that doesn't have any of the zip of his original!
I can think of one way in which Costello's original makes some sense. Perhaps it is taken out of context, and implicit in the context is the notion of only writing about music. When someone is only a critic of an art form, and not a doer of the art form, there is a real danger of becoming disconnected from what practitioners think, feel, and do. When the critic is disconnected from the reality of the domain, the writing loses some or all of its value. I still think it is possible for an especially able mind to write about without doing, but that is a rare mind indeed.
What does all this have to do with a blog about software and teaching? I find great value in many people's writing about software and about teaching. I've learned a lot about how to build more expressive, more concise, and more powerful software from people who have shared their experiences writing such software. The whole software patterns movement is founded upon the idea that we should share our experiences of what works, when and why. The pedagogical patterns community and the SIGCSE community do the same for teachers. Patterns really do have to be founded in experience, so "only" writing patterns without practicing the craft turns out to be a hollow exercise for both the reader and the writer, but writing about the craft is an essential way for us to share knowledge. I think we can share knowledge both of the practical, functional parts of software and teaching and of the artistic element -- what it is to make software that people want to read and reuse, to make courses that people want to take. In these arts, beauty affects functionality in a way that we often forget.
I don't yet have an appetite for dancing about software, but my mind is open on the subject.
Our working group had its most productive ChiliPLoP in recent memory this year. The work we did isn't ready for public consumption yet, so I can't post a link just yet, but I am hopeful that we will be able to share our results with interested educators soon enough. For now, a summary.
This year, we made substantial progress toward producing a well-documented resource for instructors who want to teach Java and OOP. As our working paper begins:
The following set of exercises builds up a simple application over a number of iterations. The purpose is to demonstrate, in a small program, most of the key features of object-oriented programming in Java within a period of two to three weeks. The course can then delve more deeply into each of the topics introduced, in whatever order the instructor deems appropriate.
An instructor can use this example to lay a thin but complete foundation in object-oriented Java for an intro course within the first few weeks of the semester. By introducing many different ideas in a simple way early, the later elements of the course can be ordered at the instructor's discretion. So many other approaches to teaching CS 1 create strict dependencies between topics and language constructs, which limits the instructor's approach over the course of the whole semester. The result is that most instructors won't adopt a new approach, because they either cannot or do not want to be tied down for the whole semester. We hope that our example enables instructors to do OO early while freeing them to build the rest of their course in a way that fits their style, their strengths and interests, and their institution's curriculum.
Our longer-term goal is that this resource serve as a good example for ourselves and for others who would like to document teaching modules and share them with others. By reducing external dependencies to a minimum, such modules should assist instructors in assembling courses that use good exercises, code, and OO programming practice.
... but where are the patterns? Isn't a PLoP conference about patterns? Yes, indeed, and that is one reason that I'm more excited about the work we did this week than I have been in a while. By starting with a very simple little exercise, growing progressively into an interesting simulation via short, simple steps, we have assembled both a paradigmatic OO CS 1 program and the sequence of changes necessary to grow it. To me, this is an essential step in identifying the pattern language that generates the program. I may be a bit premature, but I feel as if we are very close to having documented a pattern sequence in the Alexandrian sense. Such a pattern sequence is an essential part of a pattern-oriented approach to design, and one that only a few people -- Neil Harrison and Jim Coplien -- have written much about. And, like Alexander's idea of pattern diagnosis, pattern sequences will, I think, play a valuable role in how we teach pattern-directed design. My self-assigned task is to explore this extension of our ChiliPLoP work while the group works on filling in some details and completing our public presentation.
One interesting socio-technical experiment we ran this week was to write collaboratively using a Google doc. I'm still not much a fan of browser-based apps, especially word processors, but this worked out reasonably well for us. It was fast, performed autosaves in small increments, and did a great job handling the few edit conflicts we caused in two-plus days. We'll probably continue to work in this doc for a few more weeks, before we consider migrating the document to a web page that we can edit and style directly.
Two weeks from today, the whole crew of us will be off to SIGCSE 2007, which is an unusual opportunity for us to follow up our ChiliPLoP and hold ourselves accountable for not losing momentum. Of course, two weeks back home like this would certainly wipe my mind clear of any personal momentum I have built up, so I will need to be on guard!
I remember vividly a particular moment of understanding that I experienced in graduate school. As I mentioned last time, I was studying knowledge-based systems, and one of the classic papers we read was William Clancey's Heuristic Classification. This paper described an abstract decomposition for classification programs, the basis of diagnostic systems, that was what we today would call a pattern. It gave us the prototype against which we could pattern our own analysis of problem-solving types.
In this paper, Clancey discussed how configuration and planning are two points of view on the same problem, design. A configuration system produces as output an artifact capable of producing state changes in some context; a planning system takes such an artifact as input. A configuration takes as input a sequence of desired state changes, to be produced by the configured system; a planning system produces a sequence of operations that produces desired state changes in the given artifact. Thus, the same kind of system could produce a thing, an artifact, or a process that creates an artifact. In a certain sense, things and processes were the same kind of entity.
Wow. Design and planning systems could be characterized by similar software patterns. I felt like I'd been shown a new world.
Later I learned that this interplay between thing and process ran much deeper. Consider this Lisp (or Scheme) "thing", a data value known as a list:
(a 1 2)
If I replace the symbol "a" with the symbol "+", I also have a Lisp list of size 3:
(+ 1 2)
But this Lisp list is also the Lisp program for computing the sum of 1 and 2! If I give this program to a Lisp interpreter, I will see the result:
> (+ 1 2)
3
In Lisp, there is no distinction between data and program. Indeed, this is true for C, Java, or any other programming language. But the syntax of Lisp (and especially Scheme) is so simple and uniform that the unity of data and program stands out starkly. It also makes Scheme a natural language to use in a course on the principles of programming languages. The syntax and semantics of Lisp programs are so uniform that one can write a Lisp interpreter in about a page of Lisp code. (If you'd like, take a look at my implementation of John McCarthy's Lisp-in-Lisp, in Scheme, based on Paul Graham's essay The Roots of Lisp. If you haven't read that paper, please do soon.)
There is no distinction between data and program. This is one of the truly beautiful ideas in computer science. It runs through everything that we do, from von Neumann's stored program computer, itself to the implementation of a virtual machine for Java to run inside a web browser.
A related idea is the notion that programs can exist at arbitrary levels of abstraction. For each level at which a program is data to another program, there is yet another program whose behavior is to produce that data. An assembler produces machine language from assembly language.
One of the lessons of computer science is that "machine" is an abstract idea. Everything can be interpreted by someone -- or something -- else.
I don't know enough of the history of mathematics or natural philosophy to say to what extent these ideas are computer science's contributions to our body of knowledge. On the one hand, I'm sure that deep thinkers throughout history at least had reason and resource to make some of the connections between thing and process, between design and planning. On the other, I imagine that before we had digital computers at our disposal, we probably didn't have sufficient vocabulary or the circumstances needed to explore issues of natural language to the level of program versus data, or of languages being processed from abstract to concrete, down to the details of a particular piece of hardware. Church. Turing. Chomsky. McCarthy. These are the men who discovered the fundamental truths of language, data, and program, and who laid the foundations of our discipline.
At first, I wondered why hadn't I learned this small set of ideas as an undergraduate student. In retrospect, I'm not surprised. My alma mater's CS program was aimed at applications programming, taught a standard survey-style programming languages course, and didn't offer a compilers course. Whatever our students here learn about the practical skills of building software, I hope that they also have the chance to learn about some of the beautiful ideas that make computer science an essential discipline in the science of the 21st century.
For most of my research career, I have been studying patterns in software. In the beginning didn't think of it in these terms. I was a graduate student in AI doing work in knowledge-based systems, and our lab worked on so-called generic tasks, little molecules of task-specific design that composed into systems with expert behavior. My first uses of the term "pattern" were home-grown, motivated by an interest to help novice programmers recognize and implement the basic structures that made up their Pascal, Basic, and C programs. In the mid-1990s I came into contact with the work of Christopher Alexander and the software patterns community, and I began to write up patterns of both sorts, including Sponsor-Selector, loops, Structured Matcher, and even elementary patterns of Scheme programming for recursion. My interest turned to the patterns at the interface between different programming styles, such as object-oriented and functional programming. It seemed to me that many object-oriented design patterns implemented constructs that were available more immediately in functional languages, and I wondered whether it were true that patterns in any one style would reflect the linguistic shortcomings of the style, implementing ideas available directly in another style.
My work in this area has always been more phenomenological than mathematical, despite occasional short side excursions into promising mathematics like group and category theory. I recall a 6- to 9-month period five or six years ago when a graduate student and I looked group theory and symmetries as a possible theoretical foundation for characterizing relationships among patterns. I think that this work still holds promise, but I have not had a chance to take it any further.
Only recently did I finally read Matthias Felleisen's 1991 paper On the Expressive Power of Programming Languages. I should have read it sooner! This paper develops a framework for comparing languages on the basis of their expressiveness powers and then applies it to many of the issues relevant to language research of the day. One section in particular speaks to my interest in programming patterns and shows how Felleisen's framework can help us to discern the relative merits of more expressive languages and the patterns that they embody. This section is called "The Conciseness Conjecture". Here is the conjecture itself:
Programs in more expressive programming languages that use the additional features in a sensible manner contain fewer programming patterns than equivalent programs in less expressive languages.
Felleisen gives a couple of examples to illustrate his conjecture, including one in which Scheme with assignment statements realizes the implementation of an stateful object more concisely, more clearly, and with less convention than a purely functional subset of Scheme. This is just the sort of example that led me to wonder whether functional programming's patterns, like OOP's patterns, embodied ideas that were directly expressible in another style's languages -- a Scheme extended with a simple object-oriented facility would make implementation of Felleisen's transaction manager even clearer than the stateful lambda expression that switches on transaction types.
Stated as starkly as it is, I am not certain I believe the conjecture. Well, that's not quite true, because in one sense it is obviously true. A more expressive language allows us to write more concise code, and less code almost always means fewer patterns. This is true, of course, because the patterns reside in the code. I say "almost always" because there is an alternative to fewer patterns in smaller code: the same number of patterns, or more, in denser code!
If we qualify "fewer programming patterns" as "fewer lower-level programming patterns", then I most certainly believe Felleisen's conjecture. I think that this paper makes important contribution to the study of software patterns by giving us a vocabulary and mechanism for talking about languages in terms of the trade-off between expressiveness and patterns. I doubt that Felleisen intended this, because his section on the Conciseness Conjecture confirms his uneasiness with pattern-driven programming. "The most disturbing consequence," he writes, of programming patterns is that they are an obstacle to understanding of programs for both human readers and program-processing programs." For him, an important result of his paper is to formalize "how the use of expressive languages seems to be the ability to abstract from programming patterns with simple statements and to state the purpose of a program in the concisest possible manner."
This brings me back to the notions of "concise" and "dense". I appreciate the goal of using the most abstract language possible to write programs, in order to state as unambiguously and with as little text as possible the purpose and behavior of a program. I love to show my students how, after learning the basics of recursive programming. they can implement a higher-order operation such as fold to eliminate the explicit recursion from their programs entirely. What power! all because they are using a language expressive enough to allow higher-order procedure. Once you understand the abstraction of folding, you can write much more concise code.
Where is the down side? Increasing concision ultimately leads to a trade-off on understandability. Felleisen points to the danger that dispersion poses for code readers: in the worst case, it requires a global understanding of the program to understand how the program embodies a pattern. But at the other end of the spectrum is the danger posed by concision: density. In the worst, the code is so dense as to overwhelm the reader's sense. If density were an unadulterated good, we would all be programming in a descendant of APL! The density of abstraction is often the reason "practical" programmers cite for not embracing functional programming is the density of the abstractions one finds in the code. It is an arrogance for us to imply that those who do not embrace Scheme and Haskell are simply not bright enough to be programmers. Our first responsibility is to develop means for teaching programmers these skills better, a challenge that Felleisen and his Teach Scheme! brigade have accepted with great energy. The second is to consider the trade-off between concision and dispersion in a program's understandability.
Until we reach the purest sense of declarative programming, all programs will have patterns. These patterns are the recurring structures that programmers build within their chosen style and language to implement behaviors not directly supported by the language. The patterns literature describes what to build, in a given set of circumstances, along with some idea of how to build the what in a way that makes the most of the circumstances.
I will be studying "On the Expressive Power of Programming Languages" again in the next few months. I think it has a lot more to teach me.
Our dean is relatively new in his job, and one of the tasks he has been learning about is fundraising. It seems that this is one of the primary roles that deans and other to-level administrators have to fill in these days of falling state funding and rising costs.
This morning he gave his department heads a short excerpt from the book Asking: A 59-Minute Guide to Everything Board Members, Volunteers, and Staff Must Know to Secure the Gift. Despite the massive title, apparently each chapter of the book is but a few chapters, focused on a key lesson. The excerpt we received is on this kernel: Donors give to the magic of an idea. Donors don't give to you because you need money. Everybody needs money. Donors give because there is something you can do.
For some reason, this struck as a lesson I have learned over the last few years in a number of different forms, in a number of different contexts. I might summarize the pattern as "It's not about me." Donors don't give because I need; they give because I can do something, something that matters out there. In the realm of interpersonal communication, the hearer is the final determinant of what is communicated. Listeners don't hear what I say; they hear what they understand me to have said. The blog Creating Passionate Users often talks about selling how my book or software is about empowering my users -- not about me, or any of the technical things that matter to me. The same applies to teachers. While in an important sense my Programming Languages course is about the content we want students to learn, in a very practical sense the course is about my students: what they need and why, how they learn, and what motivates them. Attending only to my interests or to the antiseptic interests of the "curriculum" is a recipe for a course almost guaranteed not to succeed.
Let's try this on. "Students don't learn because you think they need something. They learn because there is something they can do with their new knowledge." They learn because the magic of an idea.
That sounds about right to me. Like any pattern taken too far in a new context, this one fails if I overreach, but it does a pretty good job of capturing a basic truth about teaching and learning. Given the many forms this idea seems to take in so many contexts, I think it is just the sort of thing we mean by a pattern.
Last year, OOPSLA introduced another new track called Essays. This track shared a motivation from another recent introduction, Onward!, in providing an avenue for people to write and present important ideas that cannot find a home in the research-oriented technical program of the usual academic conference. But not all advances are in the form of novelty, of results from narrowly-defined scientific experiments. Some empirical results are the fruit of experience, reflection, and writing. The Essays track offers an avenue for sharing this sort of learning. The author writes an essay in the spirit of Montaigne and Bacon, using the writing to work out an understanding of his experience. He then presents the essay to the OOPSLA audience, followed by a thoughtful response from a knowledge person who has read the essay and thought about the ideas. (Essays crossed my path in a different arena last week, when I blogged a bit on the idea of blog as essay.)
Jim Waldo, a distinguished engineer at Sun, presented the first essay of OOPSLA 2006, titled "On System Design". He reflected on his many years as a software developer and lead, trying to get a handle on what he now believes about the design of software.
What is a "system"? To Waldo, it is not "just a program" in the sense he thinks meant by the postmodern programming crowd, but a collection of programs. It exists at many levels of scale that must be created and related; hence the need for us to define and manage abstractions.
Software design is a craft, in the classical sense. Many of Waldo's engineer friends are appalled at what software engineers think of as engineering (essentially the application of patterns to roll out product in a reliable, replicable way) because what engineers really do involves a lot of intuition and craft.
Software design is about technique, not facts. Learning technique takes time, because it requires trial and error and criticism. It requires patience -- and faith.
Waldo paraphrase Grady Booch as having said that the best benefit of the Rational toolset was that it gives developers "a way to look like they were doing something while they had time to think".
The traditional way to learn system design is via apprenticeship. Waldo usually asks designers he respects who they apprenticed with. At first he feared that at least a few would look at him oddly, not understanding the question. But he was surprised to find that every person answered without batting an eye. They all not only understood the question but had an immediate answer. He was also surprised to hear the same few names over and over. This may reflect Waldo moving in particular circles, or only a small set of master software developers out there!
In recent years, Waldo has despaired of the lack of time, patience, and faith shown in industry for developing developers. Is all lost? No. In reflecting on this topic and discussing with readers of his early drafts, Waldo sees hope in two parts of the software world: open source and extreme programming.
Consider open source. It has a built-in meritocracy, with masters at the top of the pyramid, controlling the growth and design of their systems. New developers learn from example -- the full source of the system being built. Developers face real criticism and have the time and opportunity to learn and improve.
Consider extreme programming. Waldo is not a fan of the agile approaches and doesn't think that the features on which they are sold are where they offer most. It isn't the illusion of short-term cycles or of the incrementalism that grows a big ball of mud which give him hope. In reality, the agile approaches are based in a communal process that builds systems over time, giving people the time to think and share, mentor and learn. Criticism is built into the process. The system is an open, growing example.
Waldo concludes that we can't teach system design in a class. As an adjunct professor, he believes that system design skills aren't a curriculum component but a curricular outcome. Brian Marick, the discussant on Waldo's took a cynical turn: No one should be allowed to teach students system design if they haven't been a committer to a large open-source project. (Presumably, having had experience building "real" big systems in another context would suffice.) More seriously, Marick suggested that it is only for recent historical reasons that we would turn to academia to solve the problem of producing software designers.
I've long been a proponent of apprenticeship as a way of learning to program, but Waldo is right that doing this as a part of the typical university structure is hard, if not impossible. We heard about a short-lived attempt to do this at last year's OOPSLA, but a lot of work remains. Perhaps if more people like Waldo, not just the more provocative folks at OOPSLA, start talking openly about this we might be able to make some progress.
Bonus reading reference: Waldo is trained more broadly as a philosopher, and made perhaps a surprising recommendation for a great document on the act of designing a new sort of large system: The Federalist Papers. This recommendation is a beautiful example of the value in a broad education. The Federalist Papers are often taught in American political science courses, but from a different perspective. A computer scientist or other thinker about the design of systems can open a whole new vista on this sort of document. Here's a neat idea: a system design course team taught by a computer scientist and a political scientist, with The Federalist Papers as a major reading!
Now, how to make system design as a skill an inextricable element of all our courses, so that an outcome of our major is that students know the technique? ("Know how", not "know that".)
The first two sentences of Guy Steele's OOPSLA 2006 keynote this morning were eerily reminiscent of his describes the application of the principles from his justly famous OOPSLA 1998 invited talk Growing a Language. I'm pretty sure that, for that few seconds, he used only one-syllable words!
This talk, A Growable Language, was related to that talk, but in a more practical sense. It applied the spirit and ideas expressed in that talk to a new language. His team at Sun is designing Fortress, a "growable language" with the motto "To Do for Fortran What Java Did for C".
The aim of Fortress is to support high-performance scientific and engineering programming without carrying forward the historical accidents of Fortran. Among the additions to Fortran will be extensive libraries, including for networking, a security model, type safety, dynamic compilation (to enable the optimization of running program), multithreading, and platform independence. The project is being funded by DARPA with the goal of improving programmer productivity for writing scientific and engineering applications -- to reduce the time between when a programmer receives a problem and when the programmer delivers the answer, rather than focus solely on the speed of the compiler or executable. Those are important, too, but we are shortsighted in thinking that they are the only formsof speed that matter. (Other DARPA projects in this vein are the Extend language from IBM[?] and the Chapel language from Cray.)
Given that even desktop computers are moving toward multicore chips, this sort of project offers potential value beyond the scientific programming community.
The key ideas behind the Fortress project are threefold:
Steele reminded his audience of the motivation for growing a language from his first talk: If you plan for a language, and then design it, then build it, you will probably miss the optimal window of opportunity for language. One of the guiding questions of the Fortress project is, Will designing for the growth of a language and its user community change the technical decisions the team makes or, more importantly, the way it makes them?
One of the first technical questions the team faced was what set of primitive data types to build into the language. Integer and float -- but what sizes? Data aggregates? Quaternions, octonions? Physical units such as meter and kilogram?? He "might say 'yes' to all of them, but he must say no to some of them." Which ones -- and why?
The strategy of the team is to, wherever possible, add a desired feature via a library -- and to give library designers substantial control over both the semantics and the syntax of the library. The result is a two-level language design: a set of features to support library designers and a set of features to support application programmers. The former have turned out to be quite obbject-oriented, while the latter is not obbject-oriented at all -- something of a surprise to the team.
At this time, the language defines some very cool types in libraries: lists, vectors, sets, maps (with better, more math-like notion), matrices and multidimensional vectors, and units of measurement. The language also offers as a feature mathematical typography, using a wiki-style mark-up to denote Unicode characters beyond what's available on the ASCII keyboard.
In the old model for designing a language, the designers
At a strategic level, the Fortress team wants to avoid creating a monolithic "standard library", even when taking into account the user-defined libraries created by a single team or by many. Their idea is instead to treat libraries as replaceable components, perhaps with different versions. Steele says that Fortress effectively has make and svn built into its toolset!
I can just hear some of my old-school colleagues decrying this "obvious bloat", which must surely degrade the language's performance. Steele and his colleagues have worked hard to make abstraction efficient in a way that surpasses many of today's languages, via aggressive static and dynamic optimization. We OO programmers have come to accept that our environments can offer decent efficiency while still having features that make us more productive. The challenge facing Fortress is to sell this mindset to C and Fortran programmers with habits of 10, 20, even 40 years thinking that you have to avoid procedure calls and abstract data types in order to ensure optimal performance.
The first category of features in Fortress intend to support library developers. The list is an impressive integration of ideas from many corners of the programming language community, including first-class types, traits and trait descriptors (where, comprise, exclude), multiple inheritance of code but not fields, and type contracts. In this part of the language definition, knowledge that used to be buried in the compiler is brought out explicitly into code where it can be examined by programmers, reasoned over by the type inference system, and used by library designers. But these features are not intended for use by application programmers.
In order to support application developers, Steele and his team watched (scientific) programmers scribble on their white boards and then tried to convert as much of what they say as possible into their language. For example, Fortress takes advantage of subtle whitespace cues, as in phrases such as
Note the four different uses of the vertical bar, disambiguated in part by the whitespace in the expression.
The wired-in syntax of Fortress consists of some standard notation from programming and math:
Any other operator can be defined as infix, prefix, or postfix. For example, ! is defined as a postfix for factorial. Similarly, juxtaposition is a binary operator, one which can be defined by the library designer for her own types. Even nicer for the cientific programmer, the compiler knows that the juxtaposition of functions is itself a function (composition!).
The syntax of Fortress is rich and consistent with how scientific programmers think. But they don't think much about "data types", and Fortress supports that, too. The goal is for library designers to think about types a lot, but application programmers should be able to do their thing with type inference filling in most of the type information.
Finally, scientists, engineers, and mathematicians use particular textual conventions -- fonts, characters, layout -- to communicate. Fortress allows programmers to post-process their code into a beautiful mathematical presentation. Of course, this idea and even its implementation are not new, but the question for the Fortress team was what it would be like if a language were designed with this downstream presentation as the primary mode o presentation?
The last section of Steele's talk looked a bit more like a POPL or ICFP paper, as he explained the theoretical foundations underlying Fortress's biggest challenge: mediating the language's abstractions down to efficient executable code for parallel scientific computation. Steele asserted that parallel programming is not a feature but rather a pragmatic compromise. Programmers do not think naturally in parallel and sop need language support. Fortress is an experiment in making parallelism the default mode of computation.
Steele's example focused on the loop, which in most languages conflates two ideas: "do this statement (or block) multiple times" and "do things in this order". In Fortress, the loop itself means only the former; by default its iterations can be parallelized. In order to force sequencing, the programmer modifies the interval of the loop (the range of values that "counts" the loop) with the seqoperator. So, rather than annotate code to get parallel compilation, we must annotate to get sequential compilation.
Fortress uses the idea of generators and reducers -- functions that produce and manipulate, respectively, data structures like sequences and trees -- as the basis of the program transformations from Fortress source code down to executablecode. There are many implementations for these generators and reducers, some that are sequential and some that are not.
From here Steele made a "deep dive" into how generators and reducers are used to implement parallelism efficiently. That discussion is way behind what I can write here. Besides, I will have to study the transformations more closely before I can explain them well.
As Steele wrapped up, he reiterated The Big Idea that guides the Fortress team: to expose algorithm and design decisions in libraries rather than bury them in the compiler -- but to bury them in the libraries rather than expose them in application code. It's an experiment that many of us are eager to see run.
One question from the crowd zeroed in on the danger of dialect. When library designers are able to create such powerful extensions, with different syntactic notations, isn't there a danger that different libraries will implement similar ideas (or different ideas) incompatibly? Yes, Steele acknolwedge, that is a real danger. He hopes that the Fortress community will grow with library designers thinking of themselves as language designers and so exercise restraint in the the extensions they make, and work together to create community standards.
I also learned about a new idea that I need to read about... the BOOM hierarchy. My memory is vagues, but the discussion involved considering whether a particular operation -- which, I can't remember -- is associative, commutative, and idempotent. There are, of course, eight possible combinations of these features, four of which are meaningful (tree, list, bag/multiset, and set). One corresponds to an idea that Steele termed a "mobile", and the rest are, in his terms, "weird". I gotta read more!
Brenda Laurel is well known in computing, especially the computer-human interaction computing, for her books The Art of Human-Computer Interface Design and the iconic Computers as Theatre. I have felt a personal connection to her for a few years, since an OOPSLA a few years ago when I bought Brenda's Utopian Entrepreneur, which describes her part in starting Purple Moon, a software company to produce empowering computer games for young girls. That sense of connection grew this morning as I prepared this article, when I learned that Brenda's mom is from Middletown, Indiana, less than an hour from my birthplace, and just off the road I drove so many times between my last Hoosier hometown and my university.
Laurel opened this year's OOPSLA as the Onward! keynote speaker, with a talk titled, "designed animism: poetics for a new world". Like many OOPSLA keynotes, this one covered a lot of ground that was new to me, and I can remember only a a bit -- plus what I wrote down in real time.
These days, Laurel's interests lie in pervasive, ambient computing. (She recently gave a talk much like this one at UbiComp 2006.) Unlike most folks in that community, her goal is not ubiquitous computing as primarily utilitarian, with its issues of centralized control, privacy, and trust. Her interest is in pleasure. She self-effacingly attributed this move to the design tactic of "finding the void", the less populated portion of the design space, but she need not apologize; creating artifacts and spaces for human enjoyment is a noble goal -- a necessary part of of our charter -- in its own right. In particular, Brenda is interested in the design of games in which real people are characters at play.
(Aside: One of Brenda's earliest slides showed this painting, "Dutch Windmill Near Amsterdam" by Owen Merton (1919). In finding the image I learned that Merton was the father of Thomas Merton, the Buddhist-inspired Catholic monk whom I have quoted here before. Small world!)
Laurel has long considered how we might extend Aristotle's poetics to understand and create interactive form. In the Poetics, Aristotle "set down ... an understanding of narrative forms, based upon notions of the nature and intricate relations of various elements of structure and causation. Drama relied upon performance to represent action." Interactive systems complicate matters relative to Greek drama, and ubiquitous computing "for pleasure" is yet another matter altogether.
To start, drawing on Aristotle, I think, Brenda listed the four kinds of cause of a created thing (at this point, we were thinking drama):
In an important sense, the material and formal causes work in opposite directions with respect to dramatic design. The effects of the material cause work bottom-up from material to pattern on up to the abstract sense of the thing, while the effects of the formal cause work top-down from the ideal to components on to the materials we use.
Next, Brenda talked about plot structure and the "shape of experience". The typical shape is a triangle, a sequence of complications that build tension followed by a sequence of resolutions that return us to our balance point. But if we look at the plots of most interesting stories at a finer resolution, we see local structures and local subplots, other little triangles of complication and resolution.
(This part of the talk reminded of a talk I saw Kurt Vonnegut give at UNI almost a decade or so ago,in which he talked about some work he had done as a master's student in sociology at the University of Chicago, playfully documenting the small number of patterns that account for almost all of stories we tell. I don't recall Vonnegut speaking of Aristotle, but I do recall the humor in is own story. Laurel's presentation blended bits of humor with two disparate elements: an academic's analysis and attention to detail, and a child's excitement at something that clearly still lights up her days.)
One of the big lessons that Laurel ultimately reaches is this: There is pleasure in the pattern of action. Finding these parts is essential to telling stories that give pleasure. Another was that by using natural materials (the material causality in our creation), we get pleasing patterns for free, because these patterns grow organically in the world.
I learned something from one of her examples, Johannes Kepler's Harmonices Mundi, an attempt to "explain the harmony of the world" by finding rules common to music and planetary motion within the solar system. As Kepler wrote, he hoped "to erect the magnificent edifice of the harmonic system of the musical scale ... as God, the Creator Himself, has expressed it in harmonizing the heavenly motions." In more recent times, composers such as Stravinsky, deBussy, and Ravel have tried to capture patterns from the visual world in their music, seeking more universal patterns of pleasure.
This led to another of Laurel's key lessons, that throughout history artists have often captured patterns in the world on the basis of purely phenomenological evidence, which were later reified by science. Impressionism was one example; the discovery of fractal patterns in Jackson Pollock's drip projectories were another.
The last part of Laurel's talk moved on to current research with sensors in the ubiquitous computing community, the idea of distributed sensor networks that help us to do a new sort of science. As this science exposes new kinds of patterns in the about the world, Laurel hopes for us to capitalize on the flip side of the art examples before: to be able to move from science, to math, and then on to intuition. She would like to use what we learn to inform the creation of new dramatic structures, of interactive drama and computer games that improve the human condition -- and give us pleasure.
The question-and-answer session offered a couple of fun moments. Guy Steele asked Brenda to react to Marvin Minsky's claim that happiness is bad for you, because once you experience it you don't want to work any more. Brenda laughed and said, "Marvin is a performance artist." She said that he was posing with this claim, and told some stories of her own experiences with Marvin and Timothy Leary (!). And she is even declared a verdict in my old discipline of AI: Rod Brooks and his subsumption architecture are right, and Minsky and the rest of symbolic AI are wrong. Given her views and interests in computing, I was not surprised by her verdict.
Another question asked whether she had seen the tape of Christopher Alexander's OOPSLA keynote in San Jose. She hadn't, but she expressed a kinship in his mission and message. She, too, is a utopian and admitted to trying to affect our values with her talk. She said that her research through the 1980s especially had taught her how she could sell cosmetics right into the insecurities of teenage girls -- but instead she chose to create an "emotional rehearsal space" for them to grow and overcome those insecurities. That is what Purple Moon was all about!
As usual, the opening keynote was well worth our time and energy. As a big vision for the future, as a reminder of our moral center, it hit the spot. I'm still left to think how these ideas might affect my daily work as teacher and department leader.
(I'm also left to track down Ted Nelson's Computer Lib/Dream Machines, a visionary, perhaps revolutionary book-pair that Laurel mentioned. I may need the librarian's help for this one.)
What if they through a talk and no one came?
I went to a talk on teaching here today and was the only member of the audience. The speaker came, of course, and the organizer of the talk, too. But then there was just me. The speaker honored me by giving his talk anyway. During the session, a fourth person arrived, and he was half-audience and half-expert.
The talk was on Small Group Instructional Diagnosis (SGID), a technique that helps faculty receive information on how well a course is going. The technique resembles the writers' workshop used in the creative writing world and the software patterns community. In the course of a class period, a moderator -- a person with no connection to the students or course, and preferably not in a power relationship with the instructor -- poses three or four questions to the students and then works with them via group discussion to arrive at a consensus about what is working in the course and what could stand improvement. The moderator requires certain skills at guiding discussion and framing the points of consensus. The author -- the instructor -- is not present to hear the discussions; instead, the moderator meets with the instructor soon after the diagnosis to present the feedback and to discuss the course. Much like a PLoP workshop group, instructors often serve in round-robin as moderators of SGIDs for one another. SGIDs are usually done during the semester, after students have enough time to know the course and instructor but early enough that the professor can use the information to improve the course content, structure, delivery, etc.
Many instructors might think of this as useful only for "bad teachers" who need to get better. But I think that even the best instructors can get better. Getting feedback and using it to inform one's practice seems like a good idea for any instructor. The colleague who gave this presentation, a math professor, is widely recognized as one of the best teachers at my institution, and he has used SGIDs in his own courses. I can imagine having a SGID done in one of my courses, and I can also imagine offering this tool as a possibility to a faculty member who came to me looking for ways to improve their teaching. I can even imagine using the tool to diagnose a particular instance of a course -- not because I think that there is something intrinsically wrong in my approach, but because the particular mix of me, the course, and the student body in the course don't seem to be working.
The similarity between the SGID and a writer's workshop seemed strong. I'm thinking about how one might augment the process I was shown using ideas from PLoP workshops, such as the summary the workshop group does before moving on to "things we like" and "ways we think the author could improve the work".
Also much like the PLoP experience, this process requires that a teacher take the risk to have students discuss their work openly in front of a third party and be willing to listen to feedback and fold it back into the work. Many writers are uncomfortable with this idea, and I know that many, many university professors are uncomfortable with this idea. But getting better usually requires an element of risk, if only by allowing honest discussion to take place.
I'm glad I was the one person who showed up for the talk. I learned from the presentation, of course, but the discussion that took place afterward, in which the half-and-half latecomer described his teaching career and the role an SGID had in helping him earn tenure, was even more illuminating. He was a good storyteller.
By the way, there is still plenty of time to register for PLoP 2006, which is collocated in Portland this year with OOPSLA. I'm looking forward to both conferences, though I'm sad that I won't be able to run at Allerton Park before, during, and after PLoP!
I was in Portland this weekend for the spring meeting of the OOPSLA 2006 conference committee. This is the meeting where we assemble the program for the conference, from technical papers to lightning talks to invited and keynote talks, from Onward! to the Educators' Symposium to DesignFest, from workshops to area of responsibility this year, tutorials. It looks like we will have 57 tutorials this year, covering a range of topics in the OOP community and out in the industrial software development community. It's a tough job to assemble the elements of such a program, which ranges over five days and encompasses affiliated events like GPCE and, for the first time ever this year, PLoP. Trying to schedule events in such a way as to minimize the number of times conference attendees say, "Rats! There are two things I want to see right now. In the session before lunch, there were none!" I suppose that, in some way, we'd be happy if every session created a conflict for attendees, but I'm not sure the attendees would like it so much!
As I've done in the past when chairing the 2004 and 2005 Educators' Symposia, I owe a great debt to my program committee of seven OOPSLA veterans. They did most of the heavy lifting in reading and evaluating all of the submissions we received. I had to make some tough calls at the end, but their input made that doable.
Some highlights from the weekend:
PDX, the Portland International Airport, has free wireless -- with better coverage than promised. Hurray!
Why is Onward! is a must-see? So that you can "cool your pinkies in the mud of the future". Maybe it's a must-see because the chairs of Onward! are the kind of people who say such things. I'm especially looking forward to Onward! films, which I had to step out of last year.
I am not sure that my students are ready for a web page about me that looks like this pictorial biography of past OOPSLA chair Douglas Schmidt. My favorite is this take on the old cartoon standard about the evolution of man:
You may recall me commenting on a particular sign I saw while running in Portland back at the fall meeting. Doesn't it always rain in Portland? Maybe not, it rained again both nights and mornings I was there this time. It was nice enough when I arrived Friday evening, if cool, and the sun had poked through the clouds Monday afternoon -- as we left.
At least it didn't rain on me while I ran. Unfortunately, I was only able to run my first morning in town. It was my first 12-miler in eight weeks or so, and felt pretty good. But, just as I did the second day at SIGCSE and the second day at ChiliPLoP I came down with some sort of respiratory thing that sapped all of my energy. So I took today off, and probably will tomorrow, too, just to get back to normal. I have a feeling that I won't be bragging about my mileage the year like I did at the end of 2005... I'm beginning to wonder about the pattern and what I can do make air travel workable again for me. I won't have a chance to test any hypothesis I develop until October, when I go to PLoP and OOPSLA.
Finally, on a less frivolous note, we spent a few minutes on Monday morning to plan a memorial for John Vlissides, whose passing I memorialized last winter. We want this memorial to be a celebration of all the ways John touched the lives of everyone he met. In an e-mail conversation last week, 2006 Educators' Symposium chair Rick Mercer pointed out a picture of John and me that I didn't know about from John's wiki, courtesy of Dragos Manolescu.
I remember that moment clearly. It has an OOPSLA connection, too, because it was taken at the annual fall meeting of the Hillside Group, which traditionally takes place the evening and morning after OOPSLA. (I've missed the last two, because the night OOPSLA ends is the traditional celebration dinner for the conference committee, and I've been eager to get home to see my family after a week on the round.)
John and I were part of a break-out group at that Hillside meeting on the topic of how to create a larger world in which to publish some of the work coming out of the PLoPs. Most academic conferences are places to publish novel work, and most pattern work is by definition not all that new -- it documents patterns we see in many existing code bases. The pattern as a literary work and teaching tool is itself novel, but that's just not what academic program conference committees are looking for.
Anyway, John and I were brainstorming. I don't remember what we produced in that session, but my clueless expression indicates that at that particular moment John was the one producing. That is not too surprising. yet he made me feel like an equal partner in the work. I guess I didn't hurt his impression of me too much. When he became general chair of OOPSLA 2004, he asked me to get involved with the conference committee for the first time, as his Educators' Symposium chair. Good memories. Thanks for the pointer to the photo, Rick. And thanks, Dragos, for taking the photo and sharing it.
Pascal Van Cauwenberghe writes a bit about agile development, lean production, and other views of software engineering. He recently quoted the Toyota Way Fieldbook as inspiration for how to introduce lean manufacturing as change. I think that educators can learn from Pascal's excerpt, too.
... we're more likely to change what people think by changing what they do, rather than changing what people do by changing what they think.
I can teach students about object-oriented programming, functional programming, or agile software development. I can teach vocabulary, definitions, and even practices and methodologies. But this content does not change learners "deeply held values and assumptions". When they get back into the trenches, under the pressure of new problems and time, old habits of thought take over. No one should be surprised that this is true for people who are not looking to change, and that is most people. But even when programmers want to practice the new skill, their old habits kick in with regularity and unconscious force.
The Toyota Way folks use this truth as motivation to "remake the structure and processes of organizations", with changes in thought becoming a result, not a cause. This can work in a software development firm, and maybe across a CS department's curriculum, but within a single classroom this truth tells us something more: how to orient our instruction. As an old pragmatist, I believe that knowledge is habit of thought, and that the best way to create new knowledge is to create new habits. This means that we need to construct learning environments in which people change what they do in practical, repeatable ways. Once students develop habits of practice, they have at their disposal experiences that enable them to think differently about problems. The ideas are no longer abstract and demanded by an outside agent; they are real, grounded in concrete experiences. People are more open to change when it is driven from within than from without, so this model increases the chance that the learner entertain seriously the new ideas that we would like them to learn.
In my experience, folks who try XP practices -- writing and running tests all the time, refactoring, sharing code, all supported by pair programming and a shared culture of tools and communication -- are more likely to "get" the agile methods than are folks to whom the wonderfulness of agile methods is explained. In the end, I think that this is true for nearly all learning.
I've been having a few Functional Programming Moments lately. In my Translation of Programming Languages course, over half of the students have chosen to write their compiler programs in Scheme. This brought back fond memories of a previous course in which one group chose to build a content management system in Scheme, rather than one of the languages they study and use more in their other courses. I've also been buoyed by reports from professors in courses such as Operating Systems that some students are opting to do their assignments in Scheme. These students seem to have really latched onto the simplicity of a powerful language.
I've also run across a couple of web articles worth noting. Shannon Behrens wrote the provocatively titled Everything Your Professor Failed to Tell You About Functional Programming. I plead guilty on only one of the two charges. This paper starts off talking about the seemingly inscrutable concept of monads, but ultimately turns to the question of why anyone should bother learning such unusual ideas and, by extension, functional programming itself. I'm guilty on the count of not teaching monads well, because I've never taught them at all. But I do attempt to make a reasonable case for the value of learning functional programming.
His discussion of monads is quite nice, using an analogy that folks in his reading audience can appreciate:
Somewhere, somebody is going to hate me for saying this, but if I were to try to explain monads to a Java programmer unfamiliar with functional programming, I would say: "Monad is a design pattern that is useful in purely functional languages such as Haskell.
I'm sure that some folks in the functional programming community will object to this characterization, in ways that Behrens anticipates. To some, "design patterns" are a lame crutch object-oriented programmers who use weak languages; functional programming doesn't need them. I like Behrens's response to such a charge (emphasis added):
I've occasionally heard Lisp programmers such as Paul Graham bash the concept of design patterns. To such readers I'd like to suggest that the concept of designing a domain-specific language to solve a problem and then solving that problem in that domain-specific language is itself a design pattern that makes a lot of sense in languages such as Lisp. Just because design patterns that make sense in Java don't often make sense in Lisp doesn't detract from the utility of giving certain patterns names and documenting them for the benefit of ... less experienced programmers.
His discussion of why anyone should bother to do the sometimes hard work needed to learn functional programming is pretty good, too. My favorite part addressed the common question of why someone should willingly take on the constraints of programming without side effects when the freedom to compute both ways seems preferable. I have written on this topic before, in an entry titled Patterns as a Source of Freedom. Behrens gives some examples of self-imposed cosntraints, such as encapsulation, and how breaking the rules ultimately makes your life harder. You soon realize:
What seemed like freedom is really slavery.
Throw off the shackles of deceptive freedom! Use Scheme.
The second article turns the seductiveness angle upside down. Lisp is Sin, by Sriram Krishnan, tells a tale being drawn to Lisp the siren, only to have his boat dashed on the rocks of complexity and non-standard libraries again and again. But in all he speaks favorably of ideas from functional programming and how they enter his own professional work.
I certainly second his praise of Peter Norvig's classic text Paradigms of AI Programming.
I took advantage of a long weekend to curl up with a book which has been called the best book on programming ever -- Peter Norvig's Paradigms of Artificial Intelligence Programming: Case Studies in Common Lisp. I have read SICP but the 300 or so pages I've read of Norvig's book have left a greater impression on me than SICP. Norvig's book is definitely one of those 'stay awake all night thinking about it' books.
I have never heard anyone call Norvig's book the best of all programming books, but I have heard many folks say that about SICP -- Structure and Interpretation of Computer Programs, by Abelson and Sussman. I myself have praised Norvig's book as "one of my favorite books on programming", and it teaches a whole lot more than just AI programming or just Lisp programming. If you haven't studied, put it at or near the top of your list, and do so soon. You'll be glad you did.
In speaking of his growth as a Lisp programmer, Krishnan repeats an old saw about the progression of a Lisp programmer that captures some of the magic of functional programming:
... the newbie realizes that the difference between code and data is trivial. The expert realizes that all code is data. And the true master realizes that all data is code.
I'm always heartened when a student takes that last step, or show that they've already been there. One example comes to mind immediately: The last time I taught compilers, students built the parsing tables for the compiler by hand. One student looked at the table, thought about the effort involved in translating the table into C, and chose instead to write a program that could interpret the table directly. Very nice.
Krishnan's article closes with some discussion of how Lisp doesn't -- can't? -- appeal to all programmers. I found his take interesting enough, especially the Microsoft-y characterization of programmers as one of "Mort, Elvis, and Einstein". I am still undecided just where I stand on claims of the sort that Lisp and its ilk are too difficult for "average programmers" and thus will never be adoptable by a large population. Clearly, not every person on this planet is bright enough to do everything that everyone else does. I've learned that about myself many, many times over the years! But I am left wondering how much of this is a matter of ability and how much is a matter of needing different and better ways to teach? The monad article I discuss above is a great example. Monads have been busting the chops of programmers for a long time now, but I'm betting that Behrens has explained it in a way that "the average Java programmer" can understand it and maybe even have a chance of mastering Haskell. I've long been told by colleagues that Scheme was too abstract, too different, to become a staple of our students, but some are now choosing to use it in their courses.
Dick Gabriel once said that talent does not determine how good you can get, only how fast you get there. Maybe when it comes to functional programming, most of us just take too long to get there. Then again, maybe we teachers of FP can find ways to help accelerate the students who want to get good.
Finally, Krishnan closes with a cute but "politically incorrect analogy" that plays off his title:
Lisp is like the villainesses present in the Bond movies. It seduces you with its sheer beauty and its allure is irresistible. A fleeting encounter plays on your mind for a long, long time. However, it may not be the best choice if you're looking for a long term commitment. But in the short term, it sure is fun! In that way, Lisp is...sin."
Forego the demon temptations of Scheme! Use Perl.
Not.
Electron Blue recently wrote about some of her experiments in art. As an amateur student of physics, she knows that these experiments are different the experiments that scientists most often perform. She doesn't always start with a "hypothesis", and when she gets done it can be difficult to tell if the experiment was a "success" or not. Her experiments are opportunities to try ideas, to see whether a new technique works out. Sometimes, that's easy to see, as when the paint of a base image dries with a grainy texture that doesn't fit the image or her next stage. Other times, it comes down to her judgment about balance or harmony.
This is quite unlike many science experiments, but I think it has more in common with science than may at first appear. And I think it is very much like what programmers and software developers do all the time.
Many scientific advances have resulted from what amounts to "trying things out", even without a fixed goal in mind. On my office wall, I have a wonderful little news brief called "Don't leave research to chance", taken from some Michigan State publication in the early 1990s. The article is about some work by Robert Root-Bernstein, an MSU science professor who in the 1980s spent time as a MacArthur Prize fellow studying creativity in the sciences. In particular, it lists ten ways to increase one's chances of serendipitously encountering valuable new ideas. Many of these are strict matters of technique, such as removing background "noise" that everyone else accepts or varying experimental conditions or control groups more widely than usual. But others fit the art experiment mold, such as running a reaction backward, amplifying a side reaction, or doing something else "unthinkable" just to see what happens. The world of science isn't always as neat as it appears from the outside.
And certainly we software developers explore and play in a way that an artist would recognize -- at least we do when we have the time and freedom to do so. When I am learning a new technique or language or framework, I frequently invoke the Three Bears Pattern that I first learned from Kent Beck via one of the earliest pedagogical patterns workshops. One of the instantiations of this pattern is to use the new idea everywhere, as often and as much as you can. By ignoring boundaries, conventional wisdom, and pat textbook descriptions of when the technique is useful, the developer really learns the technique's strengths and weaknesses.
I have a directory called software/playground/ where I visit when I just want to try something out. This folder is a living museum of some of the experiments I've tried. Some are as mundane as learning some hidden feature of Java interfaces, while others are more ambitious attempts to see just how far I can take the Model-View-Controller pattern before the resulting pain exceeds the benefits. Just opportunities to try an idea, to see how a new technique works out.
My own experience is filled with many other examples. A grad student and I learned pair programming by giving it a whirl for a while to see how it felt. And just a couple of weeks ago, on the plane to Portland for the OOPSLA 2006 fall planning meeting, I whipped up a native Ook! interpreter in Scheme -- just because. (There is still a bug in it somewhere... )
Finally, I suspect that web designers experiment in much the way that artists do when they have ideas about layout, design, and usability. The best way to evaluate the idea is often to implement it and see what real users think! This even fits Electron Blue's ultimate test of her experiments: How do people react to the work? Do they like it enough to buy it? Software developers know all about this, or should.
One of the things I love most about programming is that I have the power to write the code -- to make my ideas come alive, to watch them in animated bits on the screen, to watch them interacting with other people's data and ideas.
As different as artists and scientists and software developers are, we all have some things in common, and playful experimentation is one.
When I first attended PLoP, I was a rank novice with patterns. But like most everyone else, I had read Design Patterns -- or at least put it on my bookshelf, like everyone else -- and was just a bit in awe of the Gang of Four. Pretty soon I learned that Ralph Johnson and John Vlissides were two of the nicest and most helpful people I around. I also met Erich Gamma a time or two and found him to be a good guy, though I never interacted all that much with him. I've never had the pleasure of meeting Richard Helm.
Within a couple of years, John asked me to chair PLoP 2000. I like to have a decent understanding of something like this before I get started, and John sat with me to patiently answer questions and teach me some software patterns history. He also gave me a lot of encouragement. The conference turned out well.
Then a couple of years later, John approached me with another request: to chair the Educators Symposium at OOPSLA 2004. Again, I had been attending OOPSLA and the Educators Symposium for a few years, even helping on a few symposium committees, but I had never considered taking on the chair, which seemed like much more work and responsibility. Again, John offered me a lot of encouragement and offered to help me in any way he could in his capacity as conference chair -- including giving me his complimentary registration to OOPSLA 2003, so that I could attend the 2004 kick-off planning meeting and begin working with my colleagues to assemble the next year's program. 2003 was a tight money year for my department and me, and John's kindness made it possible for me to attend.
The 2004 Educators Symposium went pretty well, I think we can say. I've certainly talked about it enough here, beginning with this entry. I owed much of its success to John's encouragement and support. When I floated the idea of asking Alan Kay to keynote at the symposium, John said, "Dream big. I'll bet you can do it." Then, when Alan won the Turing Award, John worked to bring the Turing Award lecture to OOPSLA -- but all the while protecting my "coup" at having persuaded Alan to speak at OOPSLA 2004 in the first place. I'd've been happy to have Alan speak at OOPSLA under any circumstances, but I appreciated how John just assumed that I deserved some attention for my efforts and that, under his care, I would receive it.
John was always like that. He was a quiet leader, a person who treated each person with dignity and respect and who, as a result, could make things happen through the team he built.
He was also always a very good writer and scholar. The articles that ended up in his Pattern Hatching went a long way toward making design patterns more accessible to folks who had been a bit swamped by the GoF book. They also taught us a bit about how a good programmer thinks when he writes code.
I am filled with a deep sadness to know that John died at his home on Thanksgiving day, after more than a year and a half battling a brain tumor. He battled silently, with strength and courage derived from his abiding faith in God. My prayers are with his family, especially his wife and children.
As someone said in an announcement of John's death, the essence of John's greatness lay not in his technical accomplishments but in his humanity. He was a friend, a teacher, a colleague, and a mentor to everyone with whom he came into contact. He made everyone around him a better scholar and a better person.
Though I never did anything to deserve it, John was a friend and a mentor to me. I will miss him.
Two enjoyable talks in one week -- a treat!
On Tuesday, I went to the 2005 CHFA Faculty Excellence Award lecture. (CHFA is UNI's College of Humanities and Fine Arts.) The winner of the award was Roy Behrens, whose name long-time readers of this blog may recognize from past entries on a non-software patterns of design and 13 Books. Roy is a graphic arts professor at my university, and his talk reflected both his expertise in design and the style that contributed to his winning an award for faculty excellence. He didn't use PowerPoint in that stultifying bullet-point way that has afflicted the science and technology for the last decade or more... They used high-resolution images of creative works and audio to create a show that amplified his words. They also demonstrated a wonderful sense of "visual wit".
The title of the talk was teaching as a SUBVERSIVE INACTIVITY: a miscellany, in homage to Neil Postman's famous book. When he was asked to give this talk, he wondered what he should talk about -- how to teach for 34 years without burning out? He decided to share how his teaching style has evolved away from being the center of attention in the classroom toward giving students the chance to learn.
The talk opened with pivotal selections from works that contributed to his view on teaching. My favorite from the bunch came from "The Cult of the Fact" by Liam Hudson, a British psychologist: The goal of the teacher is to
... transmit an intellectual tradition of gusto, and instill loyalty to it, ...
Behrens characterized his approach to teaching in terms of Csikszentmihalyi's model of Flow: creativity and productivity happen when the students' skills are within just the right range of the challenges given to them.
(After seeing this talk, I'm almost afraid to use my homely line art in a discussion of it. Roy's images were so much better!)
He called this his "Goldilocks Model", the attempt to create an environment for students that maximizes their chance to get into flow.
What followed was a collage of images and ideas. I enjoyed them all. Here are three key points about teaching and learning from the talk.
Aesthetic and Anesthetic
What Csikszentmihalyi calls flow is roughly comparable to what we have historically called "aesthetic". And in its etymological roots, the antonym of 'aesthetic' is anesthetic. What an interesting juxtaposition in our modern language!
In what ways can the atmosphere of our classrooms be anesthetic?
| extreme similarity | ... | HUMDRUM | ... | monotony | |
| extreme difference | ... | HODGEPODGE | ... | mayhem |
We often think of boredom as a teaching anesthetic, but it's useful to trace this back to the possibility that the boredom results from a lack of challenge. Even more important is to remember that too much challenge, too much activity, what amounts to too much distraction also serves as an anesthetic. People tend to tune out when they are overstimulated, as a coping mechanism. I am guessing that when I bore students the most, it's more likely to be from a mayhem of ideas than a monotony. ("Let's sneak in one more idea...)
Behrens is a scholar of patterns, and he has found it useful to teach students patterns -- linguistic and visual -- suitable to their level of development, and then turn them lose in the world. Knowing the patterns changes our vision; we see the world in a new way, as an interplay of patterns.
Through patterns, students see style and begin to develop their own. 'Style' is often maligned these days as superficial, but the idea of style is essential to understanding designs and thinking about creating. That said, style doesn't determine quality. One can find quality in every genre of music, of painting. There is something deeper than style. Teaching our principles of programming languages course this semester as I am, I hope that my students are coming to understand this. We can appreciate beautiful object-oriented programs, beautiful functional programs, beautiful logic programs, and beautiful procedural programs.
Creativity as Postmodern
Behrens didn't use "postmodern", but that's my shorthand description of his idea, in reference to ideas like the scrapheap challenge.
During the talk, Behrens several times quoted Arthur Koestler's The Act of Creation. Here's one:
The creative process is an "unlikely marriage of cabbages and kings -- of previously unrelated frames of reference or universes of discourse -- whose union will solve the previously insoluble problem." -- Koestler
Koestler's "cabbages and kings" is an allusion to a nonsense poem in Alice in Wonderland. (Remember what Alan Perlis said about "Alice": The best book on programming for the layman ...; but that's because it's the best book on anything for the layman.") Koestler uses the phrase because Carroll's nonsense poem is just the sort of collage of mismatched ideas that can, in his view, give rise to creativity.
Humans don't create anything new. They assemble ideas from different contexts to make something different. Creativity is a bisociation, a "sort crossing", as opposed to analytic intelligence, which is an association, a "sort-matching".
We have to give students the raw material they need to mix and match, to explore new combinations. That is why computer science students should learn lots of different programming languages -- the more different, the better! They should study lots of different ideas, even in courses that are not their primary interest: database, operating systems, compilers, theory, AI, ... That's how we create the rich sea of possibilities from which new ideas are born.
Problems, Not Solutions
If we train them to respond to problems, what happens when the problem giver goes away? Students need to learn to find and create problems!
In his early years, Behrens feared giving students examples of what he wanted, at the risk of "limiting" their creativity to what they had seen. But examples are critical, because they, too, give students the raw material they need to create.
His approach now is to give students interesting and open problems, themes on which to work. Critique their products and ideas, frequently and openly. But don't sit by their sides while they do things. Let them explore. Sometimes we in CS tend hold students' hands too much, and the result is often to turn what is fun and creative into tedious drudgery.
I'm beginning to think that one of the insidious ingredients in students' flagging interest in CS and programming is that we have taken the intellectual challenge out of learning to program and replaced it with lots of explanation, lots of text talking about technical details. Maybe our reasons for doing so seemed on the mark at the time -- I mean, C++ and Java are pretty complex -- but the unintended side effects have been disastrous.
----
I greatly enjoyed this talk. One other good thing came out of the evening: after 13 years working on the same campus, I finally met Roy, and we had a nice chat about some ideas at the intersection of our interests. This won't be the last time we cross paths this year; I hope to present a paper at his conference Camouflage: Art, Science and Popular Culture conference, on the topic of steganography.
I have an interest in writing, both in general as a means for communication and in particular as it relates to the process of programming. So I headed over to the Earth Science department yesterday for a talk on popular science writing called "Words, Maps, Rocks: One Geologist's Path". The speaker was Marcia Bjornerud of Lawrence University, who recently published the popular geology book Reading the Rocks: The Autobiography of the Earth. The Earth Science faculty is using Reading the Rocks as reader in one of their courses, and they asked Dr. Bjornerud to speak on how she came to be a geologist and a popularizer of science.
Bjornerud took a roundabout way into science. As a child, she had no desire to be a scientist. Her first loves were words and maps. She loved the history of words, tracing the etymology of cool words back to their origin in European languages, then Latin or Greek, and ultimately back to the source of their roots. The history of a word was like a map through time, and the word itself was this rich structure of now and then. She also loved real maps and delighted in the political, geographical, and temporal markings that populated them. Bjornerud told an engaging story about a day in grade school when snow created a vacation day. She remembers studying the time zones on the map and learning that at least two places had no official time zone: Antarctica and Svalborg, Norway.
These reminiscences probably strike a chord in many scientists. I know that I have spent many hours poring over maps, just looking at cities and open spaces and geopolitical divisions, populations and latitudes and relative sizes. I remember passing time in an undergraduate marketing class by studying a large wall map of the US and first realizing just how much bigger Iowa (a state I had never visited but would one day call home) was than my home state of Indiana (the smallest state west of the Appalachian Mountains!) I especially love looking at maps of the same place over time, say, a map of the US in 1500, 1650, 1750, 1800, and so on. Cities grow and die; population moves inexorably into the available space, occasionally slowing at natural impediments but eventually triumphing. And words -- well, words were why I was at this talk in the first place.
Bjornerud loved math in high school and took physics at the suggestion of friends who pointed out that the calculus had been invented in large part in order to create modern physics. She loved the math but hated the physics course; it was taught by someone with no training in the area who acknowledged his own inability to teach the course well.
It wasn't until she took an introductory college geology course that science clicked for her. At first she was drawn to the words: esker, alluvium, pahoehoe, ... But soon she felt drawn to what the words name. Those concepts were interesting in their own right, and told their own story of the earth. She was hooked.
We scientists can often relate to this story. It may apply to us; some of us were drawn to scientific ideas young. But we certainly see it in our friends and family members and people we meet. They are interested in nature, in how the world works, but they "don't like science". Why? Where do our schools go wrong? Where do we as scientists go wrong? The schools are a big issue, but I will claim that we as scientists contribute to the problem by not doing a good job at all of communicating to the public why we are in science. We don't share the thrill of doing science.
A few years ago, Bjornerud decided to devote some of her professional energy to systematic public outreach, from teaching Elderhostel classes to working with grade schoolers, from writing short essays for consumption by the lay public to her book, which tells the story of the earth through its geological record.
To write for the public, scientists usually have to choose a plot device to make technical ideas accessible to non-scientists. (We agile software developers might think of this as the much-maligned metaphor from XP.)
Bjornerud used two themes to organize her book. The central theme is "rocks as text", reading rocks like manuscripts to reveal the hidden history of the earth. More specifically, she treats a rock as a palimpsest, a parchment on which a text was written and then scraped off, to be written on again. What a wonderful literary metaphor! It can captivate readers in a day when the intrigue of forensic science permeates popular culture.
Her second theme, polarities, aims more at the micro-structure of her presentation. She had as an ulterior motive, to challenge the modern tendency to see dichotomy everywhere. The world is really a tangled mix of competing concepts in tension. Among the polarities Bjornerud explores are innovation versus conservation (sound familiar?) and strength versus weakness.
Related to this motive is a desire -- a need -- to instill in the media and the public at larger an appetite for subtlety. People need to know that they can and sometimes must hold two competing ideas in their minds simultaneously. Science is a halting journey toward always-tentative conclusions.
These themes transfer well to the world of software. The tension between competing forces is a central theme driving the literature of software patterns. Focusing on a dichotomy usually leads to a sub-optimal program; a pattern that resolves the dichotomy can improve it. And the notion of "program as text" is a recurring idea. I've written occasionally about the value in having students read programs as they learn to write them, and I'm certainly not the first person to suggest this. For example, Owen Astrachan once wrote quite a bit on apprenticeship learning through reading master code (see, for example, this SIGCSE paper). Recently, Grady Booch blogged On Writing, in which he suggested "a technical course in selected readings of software source code".
Bjornerud talked a bit about the process of writing, revising, finding a publisher, and marketing a book. Only one idea stood out for me here... Her publisher proposed a book cover that used a photo of the Grand Canyon. But Bjornerud didn't want Grand Canyon on her cover; the Grand Canyon is a visual cliche, particularly in the world of rocks. And a visual cliche detracts from the wonder of doing geology; readers tune out when they see yet another picture of the Canyon. We are all taught to avoid linguistic cliches like the plague, but how many of us think about cliches in our other media? This seemed like an important insight.
Which programs are the cliches of software education?
"Hello, World", certainly, but it is
In the question-and-answer session that followed the talk, Bjornerud offered some partial explanations for where we go wrong teaching science in school. Many of us start with the premise that science is inherently interesting, so what's the problem?
This is one reason that, all other things being equal, an active scholar in a discipline will make a better teacher than someone else. It's also one of the reasons I favor schools of education that require majors in the content area to be taught (Michigan State) or that at least teach the science education program out of the content discipline's college (math and science education at UNI).
The thought I had as I left the lecture is that too often we don't teach science; we teach about science. At that point, science becomes a list of facts and names, not the ideas that underlie them. (We can probably say the same thing about history and literature in school, too.)
Finally, we talked a bit about learning. Can children learn about science? Certainly! Children learn by repetition, by seeing ideas over and over again at increasing degrees of subtlety as their cognitive maturity and knowledge level grow. Alan Kay has often said the same thing about children and language. He uses this idea as a motivation for a programming language like Smalltalk, which enables the learner to work in the same language as masters and grow in understanding while unfolding more of the language as she goes. His groups work on eToys seeks to extend the analogy to even younger children.
Most college students and professionals learn in this way, too. See the Spiral pedagogical pattern for an example of this idea. Bjornerud tentatively offered that any topic -- even string theory!?, can be learned at almost any level. There may be some limits to what we can teach young children, and even college students, based on their level of cognitive development, their ability to handle abstractions. But for most topics most of the time -- and certainly for the basic ideas of science and math -- we can introduce even children to the topic in a way they can appreciate. We just have to find the right way to pitch the idea.
This reminds me, too, of Owen Astrachan and his work on apprenticeship mentioned above. Owen has since backed off a bit from his claim that students should read master code, but not from the idea of reading code itself. When he tried his apprenticeship through reading master code, he found that students generally didn't "get it". The problem was that they didn't yet have the tools to appreciate the code's structures, its conventions and its exceptions, its patterns. They need to read code that is closer to their own level of programming. Students need to grow into an appreciation of master code.
Talks like this end up touching on many disparate issues. But a common thread runs through Bjornerud's message. Science is exciting, and we scientists have a responsibility to share this with the world. We must do so in how we teach our students, and in how we teach the teachers of our children. We must do so by writing for the public, engaging current issues and helping the citizenry to understand how science and technology are changing the world in which we live, and by helping others who write for the public to appreciate the subtleties of science and to share the same through their writing.
I concur. But it's a tall order for a busy scientist and academic. We have to choose to make time to meet this responsibility, or we won't. For me, one of my primary distractions is my own curiosity -- that which makes us a scientist in the first place drives us to push farther and deeper, to devote our energies to the science and not to the popularizing of it. Perhaps we are doomed to the G. H. Hardy's conclusion in his wonderful yet sad A Mathematician's Apology: Only after a great mind has outlived its ability to contribute to the state of our collective knowledge can -- should? will? -- it turn to explaining. (If you haven't read this book, do so soon! It's a quick read, small and compact, and it really is both wonderful and sad.)
But I do not think we are so doomed. Good scientists can do both. It's a matter of priorities and choice.
And, as in all things, writing matters. Writing well can succeed where other writing fails.
I have now published the last of my entries intended to describe the goings-on at OOPSLA 2005. As you can see from both the number and the length of entries I wrote, the conference provided a lot of worthwhile events and stimulated a fair amount of thinking. Given the number of entries I wrote, and the fact that I wrote about single days over several different entries and perhaps several weeks, I thought that some readers might appreciate a better-organized index into my notes. Here it is.
Of course, many other folks have blogged on the OOPSLA'05 experience, and my own notes are necessarily limited by my ability to be in only one place at a time and my own limited insight. I suggest that you read far and wide to get a more complete picture. First stop is the OOPSLA 2005 wiki. Follow the link to "Blogs following OOPSLA" and the conference broadsheet, the Post-Obvious Double Dispatch. In particular, be sure to check out Brian Foote's excellent color commentary, especially his insightful take on the software devolution in evidence at this year's conference.
Now, for the index:
Day 1
Day 2
Day 3
Day 4
Day 5
This and That
I hope that this helps folks navigate my various meanderings on what was a very satisfying OOPSLA.
Finally, thanks to all of you who have sent me notes to comment on this postings. I appreciate the details you provide and the questions you ask...
Now, get ready for OOPSLA 2006.
The final item on the Educators Symposium program this year was a panel discussion on the future of computer science education. It was called Are We Doomed? Reframing the Discussion, in partial gest following last SIGCSE's panel debate Resolved: "Objects Early" Has Failed. After that session, Owen Astrachan commented, "We're doomed." What did he mean by this? Despite our own declarations that this is The Age of Information and that computer science is a fundamental discipline for helping the world to navigate and use the massive amount of information now being collected, we still teach CS courses in essentially the same way we always have. We still use toy examples in toy domains that don't really matter to anyone, least of all of students. We still teach our introductory courses as 100% old-style programming, with barely a nod to users, let alone to the fact that sophisticated consumers of computing grow increasingly independent of us and our inward focus.
This summer, Owen said it this way:
We have the human genome project, we have Google, we have social networks, we have contributions to many disciplines, and our own discipline, but we argue amongst ourselves about whether emacs is better than vi, Eclipse better than IDEA, C++ better than Java or Scheme, or what objects-first really means.I'm sorry, but if we don't change what we talk about amongst ourselves, we are doomed to a niche market while the biologists, the economists, the political scientists, etc., start teaching there own computational/modeling/programming/informatics courses. Nearly everyone turns to math for calculus, nearly everyone turns to math/stats for statistics. These are nearly universally acknowledged as basic and foundational for *lots* of disciplines. In the age of information nearly no discipline at a large scale requires computer science, certainly not programming as we teach it.
Owen isn't as pessimistic as the provocative "We're doomed" sounds; he simply wants to cause us to think about this sea change and begin to make a change ourselves.
I decided that this would make a great closing for my second Educators Symposium. Last year, my first symposium opened with Alan Kay challenging us all to set a higher bar for ourselves -- in computer science, and in computer science education. This year, my second symposium would close with a challenge to reinvent what we do as a discipline.
As in so many things, the panel did not turn out quite the way I had planned. First of all, Owen wasn't able to be at OOPSLA after all, so we were without our intellectual driving force. Then, when the panel went live, discussion on the panel went in a different direction than I had planned. But it had its good points nonetheless. The panel consisted of Robert Biddle, Alistair Cockburn, Brian Marick, and Alan O'Callaghan. I owe special thanks to Alistair and Alan, who joined us on relatively short notice.
As moderator, I had hoped to pen a wonderfully humorous introduction for for each of the panelists, to loosen things up before we dropped the gloves and got serious about changing the face of computer science. Perhaps I should have commissioned a master to ghostwrite, for in my own merely mortal hands my dream went unfulfilled. I did have a couple of good lines to use. I planned to introduce Robert as the post-modern conscience of the Educators Symposium, maybe with a visual bow to one of his previous Onward! presentations. For Brian, my tag line was to be "the panelist most likely to quote Heidegger -- and make you love him anyway". But I came up short for Alistair and Alan. Alistair's paper on software development as cooperative game playing was one possible source of inspiration. For Alan, all I could think was, "This guy has a higher depth/words ratio than most everyone I know". In the end, I played it straight and we got down to business rather quickly.
I won't try to report the whole panel discussion, as I got sucked into it and didn't take elaborate notes. In general, rather than focusing on how CS is being reinvented and how CS education ought to be reinvented, it took a turn toward metaphors for CS education. I will describe what was for me the highlight of the session and then add a couple of key points I remember.
The highlight for me was Robert's presentation, titled "Deprogramming Programming". It drew heavily on the themes that he and James Noble have been pitching at recent Onward! performances, in particular that much of what we take as accepted wisdom in software development these days is created by us and is, all too often, just wrong.
He started with a quote from Rem Koolhaus and Bruce Mau's "S, M, L, XL":
Sous le pavé, la plage.
(Under the paving stone, the beach.)
There is something beneath what we have built as a discipline. We do not program only our computers... We've programmed ourselves, in many wrong ways, and it's time to undo the program.
The idea that there is a software crisis is a fraud. There isn't one now, and there wasn't one when the term 'software engineering' was coined and became a seemingly unavoidable part of our collective psyche. Robert pointed out that in Greek mythology Narcissus fell in love not with himself but with his reflection. He believes that the field of software engineering has done the same, fallen in love with an image of itself that it has created. We in CS education are often guilty of the same offense.
Robert then boldly asserted that he loves his job as a teacher of computing and software development. If we look under the pavement, we will see that we developed a lot of useful, effective techniques for teaching students to build software: study groups, role play, and especially case studios and studios. I have written before about my own strong belief in the value of case studios and software studios, so at this point I nearly applauded.
Finally:
The ultimate goal of computer science is the program.
This quote is in someways antithetical to the idea Owen and I were basing the panel on (which is one reason I wanted Robert to be on the panel!), but it also captures what many folks believe about computing. I am one of them.
That certainly doesn't do justice to the stark imagery and text that constituted Robert's slides, nor to the distinctive verbal oratory that Robert delivers. But it does capture some of the ideas that stuck with me.
The rest of the panel presentations were good, and the discussion afterward ranged far and wide, with a recurring them of how we might adopt a different model for teaching software development. Here are a few points that stood out:
All in all, the panel did not go where I had intended for it to go. Of course, Big Design Up Front can be that way. Sometimes you have to take into account what your stakeholders want. In my case, the stakeholders were the panelists and the audience, with the audience playing the role of pseudo-customer. Judging from the symposium evaluations, many folks enjoyed the panel, so maybe it worked out all right after all.
Of course, what I had hoped for the panel was to challenge folks in the audience to feel uneasy about the direction of the discipline, to dare to think Big Thoughts about our discipline. I don't think we accomplished that. There will be more opportunities in the future.
As PragDave recently wrote, the Ruby Extensions Project contains a "absolutely wonderful hack". This hack brought back memories and also reminded me of a similar but more ambitious project going on in the Ruby world.
First of all, here's the hack... One of Ruby's nice features is its collections' internal iterators. Instead of writing a for-loop to process every item in a collection, you send the collection a map message with a one-argument block as its argument. PragDave's example is to convert all the strings in an array uppercase, and the standard Ruby code is
names.map { |name| name.upcase }
The map method applies the block -- effectively a nameless method -- to every item in names.
This is a very nice feature, but after you program in Ruby you want more... Isn't writing that block more work than I should have to do? Why can't I just pass upcase, which is a one-argument method, as the argument to map? Because upcase isn't a method or a procedure; it's a symbol that names a method.
As PragDave reports, the Ruby Extensions hack adds a method to the Symbol class that allows Symbols to be coerced to a procedure object at run-time. The result is that we can now write the following:
names.map(&:upcase)
That's more succinct and avoids the need to create a new procedure object on the fly.
Now the memory... I distinctly remember the afternoon I learned the same hack in Smalltalk, back in the summer of 1988. You see, Smalltalk's collections also offer an array of internal iterators that eliminates the need to write most for-loops, and these iterators take blocks as arguments.
I was just learning Smalltalk and loved this idea -- it was my first exposure to object-oriented programming and the power of blocks, which are like functional programming's higher-order procedures. I was working on some code to sort a collection. In Smalltalk, collections also respond to a sort: message, whose argument is a two-argument block for comparing the values. So, to sort a collection of strings in ascending order, I could write:
names sort: [ x y | x < y ]
But soon I wanted more... Why can't I just pass < to sort:? The same reason I can't do it in Ruby: < isn't a block or a method; it is a symbol that names a method.
While figuring this out, I learned how sort: works. It turns around and sends the block a value:value: message with pairs of values from the collection as the two arguments. Hmm, what if a Symbol could respond to value:value: and do the right thing? I added a one-line method to the Symbol class, and they could:
value: anObject value: otherObject
^anObject perform: self with: otherObject
(perform: behaves something like Scheme's eval procedure.)
And now I could write the wonderfully compact
names sort: <
I soon added the one-argument form to Symbol, too, and began to write new code with abandon.
I felt pretty smug at the time, for having created something so beautiful. But I soon learned that I had merely rediscovered a hack that every Smalltalk programmer either reinvents or sees in someone else's code. That didn't diminish the beauty of my idea, but it did extinguish my smugness.
It turns out that this new hack is not only more compact and more convenient to write, but it runs faster than the block alternative, too. The callback on the symbol doesn't require the creation of a block on the fly, which requires memory allocation and the whole bit.
Finally, for the more ambitious project... This cool hack points out that Ruby and Smalltalk method names are symbols, and without some coercion they are not evaluated to their method values in ordinary use. What if messages were first-order objects in these languages? If so, then I can writing message sends that take other messages as arguments, thus creating higher-order messages. If you are interested in this idea, check out Nat Pryce's recent efforts to add higher-order messaging to Ruby, if you haven't already seen it. Nat gives a link to the paper that laid the foundation for this idea and steps you through the value of higher-order messages and their implementation in Ruby. It's another absolutely wonderful hack.
The keynote address for this year's Educators' Symposium was given by Ward Cunningham, one of the software folks I admire most. Of course, he's admired by many folks, including not surprisingly by the folks who organized the Wiki Symposium launched by and collocated with OOPSLA this year. As a result, Ward's keynote to our group had to be moved from its traditional first slot of the day to the slot immediately after lunch. This gave the keynote a different feel, because we all had a morning's worth of activities in which to hear Ward's words. (You can read a summary of Ward's Wiki Symposium keynote, titled "The Crucible of Creativity".)
I introduced Ward by telling the audience how I first encountered his work. At AAAI 1995 in Montreal, I was discussing some of my ideas on teaching elementary patterns with a colleague from Wales. He said, "I have a book for you to review..." You see, he was one of the editors of the journal Expert Systems, and he had received a book for review that he didn't know what to do with. It was about software patterns, and he figured that I'd be an okay reviewer. He was probably encouraged to think this by the fact that none of his other AI friends seemed to be interested.
The book was Pattern Languages of Program Design, and it changed my life. I had never been exposed to the nascent software patterns community, and this book introduced me to a lot of ideas and, ultimately, people who have played an important role in my academic work since.
One of the papers in PLoPD-1 affected me immediately. It was about the CHECKS pattern language, and it was written by Ward Cunningham. These patterns were so simple, so obvious, yet as I read them I learned something about maintaining the integrity of the data in my programs. As I looked for more of Ward's work, I soon learned that what attracted me to CHECKS was a hallmark of Ward's: the ability to recognize simple ideas that offered unexpected depth and to explore that depth, patiently and humbly. So many of Ward's contributions to standard practice have been the result of a similar process: CRC cards, patterns, wiki, extreme programming, test-first design, and FIT among them.
I asked Ward to keynote the Educators Symposium because I admired his work but because I hoped that he could teach us educators -- especially me -- a little bit of his secret gift. Maybe I could nurture the gift in myself, and maybe even pass on something to my students.
Ward opened his talk with a reminiscence, too. As an electrical engineering major in college, he learned about Maxwell's equations from a Professor Simpson. The professor taught the equations with passion, and he expected his students to appreciate their beauty. Much of their beauty lay in their simplicity, in how that brought so many important facets together into such a small number of straightforward equations. Professor Simpson also loved the work of Richard Feynman, who himself appreciated simplicity and wrote with humanity about what he learned.
One of Ward's first slides was The Big Slide, the take-home point of his talk. He characterized his way of working as:
Immerse yourself in a pool of ideas. Come to know them. Make them your own. Then look for some humble idea lying around, something that we all understand or might. Play with this idea to see whether it gives rise to something unexpected, some new ability that changes how we see or work with the pool of familiar ideas you are swimming in.
I have experienced the dangers inherent in looking for a breakthrough idea in the usual ways. When we look for Big Ideas, too often we look for Big Ideas. But they are hard to find. Maybe we can't recognize them from our current vantage point; maybe they are out of scale with the ideas we have right now.
Ward pointed out another danger: Too often, we look for complete ideas when a simple but incomplete idea will be useful enough. (Sounds like You Aren't Gonna Need It!)
Sometimes, we reach a useful destination by ignoring things we aren't supposed to ignore. Don't worry about all the things you are supposed to do, like taking your idea through to its logical conclusion right away, or polishing it up so that everyone can see how smart you are. Keep the ideas simple, and develop just what you need to move forward.
Ward pointed out that one thing we educators do is the antithesis of his approach: the project due date. It forces students to "get done", to polish up the "final version", and to miss opportunities to explore. This is one of the good things behind longer-term projects and undergraduate research -- they allow students more time to explore before packaging everything up in a neat little box.
How can we honor the simple in what we do? How can we develop patience? How can we develop the ability to recognize the simple idea that offers more?
Ward mentioned Kary Mullis's Dancing Naked in the Mind Field as a nice description of the mindset that he tries to cultivate. (You may recall my discussion of Mullis's book last year.) Mullis was passionate, and he had an immediate drive to solve a problem that no one thought mattered much. When he showed his idea to his colleagues, they all said, "Yeah, that'd work, but so what?". So Mullis gave in to the prevailing view and put his idea on the shelf for a few months. But he couldn't shake the thought that his simple little not-much of an idea could lead to big things, and eventually he returned to the idea and tinkered a little more... and won a Nobel Prize.
Extreme Programming grew out of the humble practices of programmers who were trying to learn how to work in the brave new image of Smalltalk. Ward is happy that P creates a work environment that is safe for the kind of exploration he advocates. You explore. When you learn something, you refactor. XP says to do the simplest thing that could possibly work, because you aren't gonna need it.
Many people have misunderstood this advice to mean do something simplistic, something stupid. But it really means that you don't have to wait until you understand everything before you do anything. You can do useful work by taking small steps. These principles encourage programmers to seriously consider just what is the simplest thing that could possibly work. If you don't understand everything about your domain and your task, at least you can do this simplest thing now, to move forward. When you learn more later, you won't have over-invested in ideas you have to undo. But you will have been making progress in the meantime.
(I don't think that Ward actually said all of these words. They are my reconstruction of what he taught me during his talk. If I have misrepresented his ideas in any way, the fault is mine.)
Ward recalled first getting Smalltalk, which he viewed as a "sketchpad for the thinking person to write spike solutions". Have an idea? Try to program it! Everything you need or could want to change is there before you, written in the same language you are using. He and Kent realized that they now had a powerful machine and that they should "program in a powerful way". Whenever in the midst of programming they slowed down, he would ask Kent, "What is the simplest thing that could possibly work?", and they would do that. It got them over the hump, let them regain their power and keep on learning.
This practice specializes his Big Slide from above to the task of programming:
Remember: You can't do it all at once. Ride small steps forward.
This approach to programming did not always follow the most efficient path to a solution, but it always made progress -- and that's more than they could say by trying to stay on the perfect path. The surprise was that the simple thing usually turned out to be all they needed.
Ward then outlined a few more tips for nurturing simple ideas and practices:
From the audience, Joe Bergin pointed out his personal favorite variant of this wisdom (which, I think, ironically turns Ward's advice back on itself): Take a good idea and do it to the hilt. This is, of course, how Kent Beck initially described XP -- "Turn the knobs up to 10."
Simplicity is not universal but personal, because it builds upon a person's own pool of familiar ideas. For example, if you don't know mathematics, then you won't be able to avail yourself of the simplicities it offers. (Or want, or know to want to.)
At this point, Ward ended his formal talk and spent almost an hour demonstrating some of these ideas in the testbed of his current hobby project, the building of simple computers to drive an equally simple little CRT. I can't do justice to all he showed us during this phase of his keynote, but it was remarkable... He created his own assembly language and then built a little simulator for it in Java. He created macros. He played with simple patterns on the screen, and simple patterns in the wiring of his little computer board. He hasn't done anything to completion -- his language and simulator enable him to do only what he has done so far. But that has been good enough to learn some neat ideas about the machines themselves and about the programs he's written.
While I'm not sure anything concrete came out of this portion of his talk, I could see Ward's joy for exploration and his fondness for simple questions and just-good-enough solutions while playing.
We probably should all have paid close attention to what Ward was doing because, if the recent past has taught us anything, it is that in five years we will all be doing what Ward is playing with today.
In my recent post on Gerry Sussman's talk at OOPSLA, I quoted Gerry Sussman quoting concert pianist James Boyk, and then commented:
A work of art is a machine with an aesthetic purpose.
(I am uncomfortable with the impression these quotes give, that artistic expression is mechanistic, though I believe that artistic work depends deeply on craft skills and unromantic practice.)
Thanks to the wonders of the web, James came across my post and responded with to my parenthetical:
You may be amused to learn that fear of such comments is the reason I never said this to anyone except my wife, until I said it to Gerry! Nevertheless, my remark is true. It's just that word "machine" that rings dissonant bells for many people.
I was amused... I mean, I am a computer scientist and an old AI researcher. The idea of a program, a machine, being beautiful or even creating beauty has been one of the key ideas running through my entire professional life. Yet even for me the word "machine" conjured up a sense that devalued art. This was only my initial reaction to Sussman's sentiment, though. I also felt an almost immediate need to mince my discomfort with a disclaimer about the less romantic side of creation, in craft and repetition. I must be conflicted.
James then explained the intention underlying his use of the mechanistic reference in way that struck close to home for me:
I find the "machine" idea useful because it leads the musician to look for, and expect to find, understandable structures and processes in works of music. This is productive in itself, and at the same time, it highlights the existence and importance of those elements of the music that are beyond this kind of understanding.
This is an excellent point, and it sheds light on other domains of creation, including software development. Knowing and applying programming patterns helps programmers both to seek and recognize understandable structures in large programs and to recognize the presence and importance of the code that lies outside of the patterns. This is true even -- especially!? -- for novice programmers, who are just beginning to understand programs and their structure, and the process of reading and writing them. Much of the motivation for work on the use of elementary patterns in instruction, as we try to help learn to comprehend masses of code that at first glance may seem but a jumble but which in fact bear a lot of structure within them. Recognizing code that is and isn't part of recurring structure, and understanding the role both play, is an essential skill for the novice programmer to learn.
Folks like Gerry Sussman and Dick Gabriel do us all a service by helping us to overcome our discomfort when thinking of machines and beauty. We can learn something about science and about art.
Thanks to James for following up on my post with his underlying insight!
Grady Booch refers to himself as an "IBM fellow and free radical". I don't know if 'free radical' part of his job description or only self-appellation, but it certainly fits his roving personality. He is a guy with many deep interests and a passion for exploring new lands.
His latest passion is Handbook of Software Architecture, a project that many folks thinks is among the most important strategic efforts for the history and future of software development.
Booch opened his invited talk at OOPSLA by reminding everyone that "classical science advances via the dance between quantitative observation and theoretical construction." The former is deliberate and intentional; the latter is creative and testable. Computer science is full of empirical observation and the construction of theories, but in the world of software we often spend all of time building artifacts and not enough time doing science. We have our share of theories, about process and tools, but much of that work is based on anecdote and personal experience, not the hard, dispassionate data that reflects good empirical work.
Booch reminisced about a discussion he had with Ralph Johnson at the Computer Museum a few years ago. They did a back-of-envelope calculation that estimated the software industry had produces approximately 1 trillion lines of code in high-level languages since the 1950s -- yet little systematic empirical study had been done of this work. What might we learn from digging through all that code? One thing I feel pretty confident of: we'd find surprises.
In discussing the legacy of OOPSLA, Booch mentioned one element of the software world launched at OOPSLA that has taken seriously the attempt to understand real systems: the software patterns community, of which Booch was a founding father. He hailed patterns as "the most important contribution of the last 10-12 years" in the software world, and I imagine that his fond evaluation rests largely on patterns community's empirical contribution -- a fundamental concern for the structure of real software in the face of real constraints, not the cleaned up structures and constraints of traditional computer science.
We have done relatively little introspection into the architecture of large software systems. We have no common language for describing architectures, no discipline that studies software in a historical sense. Occasionally, people publish papers that advance the area -- one that comes to mind immediately is Butler Lampson's Hints for Computer System Design -- but these are individual efforts, or ad hoc group efforts.
The other thing this brought to my mind was my time in an undergraduate architecture program. After the first-year course, every archie took courses in the History of Housing, in which students learned about existing architecture, both as historical matter and to inform current practice. My friends became immersed in what had been done, and that certainly gave them a context in which to develop their own outlook on design. (As I look at the program's current curriculum, I see that the courses have been renamed History of Architecture, which to me replaces the rich flavor of houses for the more generic 'architecture', even if it more accurately reflects the breadth of the courses.)
Booch spent a next part of his talk comparing software architecture to civil architecture. I can't do justice to this part of his talk; you should read the growing volume of content on his web site. One of his primary distinctions, though, involved the different levels of understanding we have about the materials we use. The transformation from vision to execution in civil systems is not different in principle from that in software, but we understand more about the physical materials that a civil architect uses than we do about a software developer's raw material. Hence the need to study existing software systems more deeply.
Civil architecture has made tremendous progress over the years in its understanding of materials, but the scale of its creations has not grown commensurately other what the ancients built. But the discipline has a legacy of studying the works of the masters.
Finally he listed a number of books that document patterns in physical and civil systems, including The Elements of Style -- not the Strunk and White version -- and the books of Christopher Alexander, the godfather of the software patterns movement.
Booch's goal is for the software community to document software architectures in as great detail, both for history's sake and for the patterns that will help us create more and more beautiful systems. His project is one man's beginning, and an inspirational one at that. In addition to documenting classic systems such as MacPaint, he aims to preserve our classic software as well. That will enable us to study and appreciate it in new ways as our understanding of computing and software grow.
He closed his talk with inspiration but also a note of warning... He told the story of contacting Edsger Dijkstra to tell him about the handbook project and seek his aid in the form of code and papers and other materials from Dijkstra's personal collection. Dijkstra supported the project enthusiastically and pledged materials from his personal library -- only to die before the details had been formalized. Now, Booch must work through the Dijkstra estate in hopes of collecting any of the material pledged.
We are a young discipline, relatively speaking, but time is not on our side.
As always, OOPSLA has been a constant font of ideas. But this year's OOPSLA seems to have triggered even more than its usual share. I think that is a direct result of the leadership of Dick Gabriel and Ralph Johnson, who have been working for eighteen months to create a coherent and focused program. As much as I have already written this week -- and I know that some of my articles have been quite long; sorry for getting carried away... -- I have plenty of raw material to keep me busy for a while, including the rest of the Educators Symposium, Gerald Sussman's invited talk, my favorite neologism of the week, and the event starting as I type this: Grady Booch's conference-closing talk on his ambitious project to build a handbook of software architecture.
For now, I'd like to share just a few ideas from the two panels I attended in the middle part of this fine last day of OOPSLA.
The Echoes panel was aimed at exploring the echoes of the structured design movement of the late 1970s. It wasn't as entertaining or as earth-shaking as it might have been given its line-up of panelists, but I took away two key points:
I plan to re-read both books in the next year.
I am going to think about how to work this idea more concretely into the courses I teach in the next year.
Like Echoes, the Yoshimi Battles the Pink Robots panel -- on the culture war between programmers and users -- didn't knock my socks off, but Brian Foote was in classic form. I don't think that he was cast in the role of Yoshimi, but he defended the role of the programmer qua programmer.
I immediately thought of a couple of plays on the theme of this quote:
I don't teach to have students. I have students to teach.
I don't blog to have readers. I have readers to blog.
I am hacker, and I write the code.
You know the thing that is most annoying about users is that they have no appreciation for the glory, the grandeur, or the majesty of living inside the code. It is my cathedral.
Oh: on his way into the lecture to give his big talk, Grady Booch walked by, glanced at my iBook, and said, "Hey, another Apple guy. Cool."
It's been a good day.
Sadly... The last day of OOPSLA is here. It will be a good day, including Onward! Films (or Echoes -- could I possibly skip a panel with Kent and so many Big Names?) (later note: I didn't), Lightning Talks (or the Programmers versus Users panel) (later note: I am at this panel now), and finally, of course, Grady Booch. But then it's over. And I'll be sad.
On to Martin or, as he would say, Mah-tin. Ralph Johnson quoted Brian Foote's epigrammatic characterization of Martin: an intellectual jackal with good taste in carrion. Soon, Ralph began to read his official introduction of Martin, written by ... Brian. It was a play on the location of conference, in Fashion Valley. In the fashion world, good design is essential, and we know our favorite designers by one name: Versace, Halston, Kent, Ward -- and Mah-tin. Martin lives a life full of beautiful models, and he is "a pretty good writer, for an Englishman".
On came Martin. He roamed the full stage, and then sat down in a cushy chair.
When asked to keynote at a conference like OOPSLA, one is flush with pride. Then you say 'yes', which is your first mistake. What can you say? Keynoters are folks who make great ideas, who invent important stuff. Guy's talks was the best. But I'm not a creator or deep thinker, says... I'm that guy who goes to a fashion show, steals the ideas he sees, knocks off the clothing, and then mass-markets them at the mall. I just want to know where we are, says Martin; predicting the future is beyond me.
To shake things up, he called on George Platts to the stage. Those of you who have attended a PLoP conference know George as a "lateral thinking consultant" and games leader. Earlier, Martin had asked him to create a game for the whole crowd, designed to turn us into intellectual jackals. For this game, George drew his inspiration from the magnificent book Life of Pi. (Eugene says: If you have not read this book, do it. Now.) George read a list of animal sounds from one page in the book and told each of us to choose one. He then told each of us to warm up by saying our own name in that fashion. (I grunted "Eugene"). He then asked everyone whose first name started with A to stand and do it for the crowd. Then I and R; D, M, V; G, P, Y; ... and finally E, N, and W. Finally, the whole room stood and hissed, grunted, growled "OOPSLA".
Back came Martin to the forefront, for the talk itself.
Martin's career is aimed at answering the question, "What is good design?" He seeks an answer that is more than just fuzzy words and fuzzy ideas.
At the beginning of his career, Martin was an EE. In that discipline, designers drawing a diagram that delineate a product and then passes it on to the person who constructs the thing. So when Martin moved on to software engineering, which had adopted this approach. But soon he came to reject this approach. Coding as construction fails. He found that designs -- other people's design and his own -- always turned out to be wrong. Eventually, he met folks he recognized as good designers who design and code at the same time. Martin came to see that the only way to design well is to program at the same time, and the only way to program well is to design at the same time.
That's the philosophy underlying all of Martin's work.
How do we characterize good designs? A set of principles.
One principle central to all good designs is to eliminate duplication. He remembers when Kent told him this, but at the time Martin dismissed it as not very deep. But then he saw that there is much more to this than he first\ thought. It turns out that when you eliminate duplication, your designs end up good, almost irrespective of anything else. He noted that this has been pattern in his life: see an important idea, dismiss it, and eventually come around. (And then write a book about it. :-)
Another principle: orthogonality, the notion that different parts of a system should do different kinds of things.
Another principle: separate the user interface from the guts of the program. One way to approach this is to imagine you have to add a new UI to your system. Any code you would have to duplicate is in the wrong place.
Philosophy. Principles. What is the next P?
Patterns -- the finding of recurring structures. Martin turned to Ralph Johnson, who has likened pattern authors to Victorian biologists, who went off to investigate a single something in great detail -- cataloging and identifying and dissecting and classifying. You learn a lot about the one thing, but you also learn something bigger. Consider Darwin, who ultimately created the theory of natural selection.
The patterns community is about finding that core something which keeps popping in a slightly different way all over the place. Martin does this in his work. He then did a cool little human demonstration of one of the patterns from his Patterns of Enterprise Application Architecture, an event queue. In identifying and naming the pattern, he found so many nice results, including some unexpected ones, like the ability to rewind and reply transactions.
Patterns people "surface" core ideas, chunk them up into the right scale, and identify when and when not to use them.
Why isn't the patterns community bigger? Martin thinks it should be bigger, and in particular should be a standard part of every academic's life! We academics should go out, look at big old systems for a couple of months, and try to make sense of them.
At the end of the session, James Noble pointed out two reasons why academic programmers don't do this: they do not receive academic credit for such activity, and they do not have access to the large commercial systems that they really need to study. On the first point, Martin agreed. This requires a shift in the academic culture, which is hard to do. (This issue of academic culture, publishing, and so on came up again at the Echoes panel later in the morning.) Martin volunteered to bellow in that direction whenever and wherever asked. On the second point, he answered with an emphatic 'yes!' Open source software opens a new avenue for this sort of work...
Philosophy. Principles. Patterns. What is the last P?
Practices. His favorite is, of course, refactoring. He remembers watching Kent Beck editing a piece of code of Martin Fowler code. Kent kept making these small, trivial changes to the code, but after each step Martin found himself saying, "Hmm, that is better." The lightbulb went off again.
He thanked John Brant and Don Roberts, Bill Opdyke and Ralph Johnson, and Ward and Kent. It's easy to write good books when other people have done the deep thinking.
He then pointed to Mary Beth Rosson's project that asks students to fixing code as a way to learn. (Eugene thinks: But that's not refactoring, right?) Refactoring is a good practice for students as they learn. "Here is some code. Smell it. Come back when it's better."
My students had better get ready...
Another practice that Martin lives and loves is test-driven design. Of course,it embodies the philosophy he began this talk with: You design and program at the same time.
And thus endeth the lesson.
In addition to the comment on academics and patterns, James Noble asked another question. (Martin lamented, "First I was Footed, and now I am Nobled." If you know Foote and Noble, you can imagine why this prospect would have a speaker a bit on edge.) James played it straight, except for a bit of camera play with the mic and stage, and pointed out that separating the UI ought causes an increase in the total amount of code -- he claimed 50%. How is that better? Martin: I don't know. Folks have certainly questioned this principle. But then, we often increase duplication in order to make it go away; maybe there is a similarity here?
Or, as Martin closed, maybe he is just wrong. If so, he'll learn that soon enough.
In my entry on Robert Hass's keynote address, I discussed the juxtaposition of 'conservative' and 'creative', the tension between the desire to be safe and the desire to be free, between memory and change. Hass warned us against the danger inherent in seeking safety, in preserving memory, to an extreme: blindness to current reality. But he never addressed the danger inherent in seeking freedom and change to the exclusion of all else. I wrote:
There is a danger in safety, as it can blind us to the value of change, can make us fear change. This was one of the moments in which Hass surrendered to a cheap political point, but I began to think about the dangers inherent in the other side of the equation, freedom. What sort of blindness does freedom lead us to?
During a conversation about the talk with Ryan Dixon, it hit me. The danger inherent in seeking freedom and change to an extreme untethered idealism. Instead of "Ah, the good old days!", we have, "The world would be great if only...". When we don't show proper respect to memory and safety, we become blind in a different way -- to the fact that the world can't be the way it is in our dreams, that reality precludes somehow our vision.
That doesn't sound so bad, but people sometimes forget not to include other people in their ideal view. We sometimes become so convinced by our own idealism that we feel a need to project it onto others, regardless of their own desires. This sort of blindness begins to look in practice an awful lot like the blindness of overemphasizing safety and memory.
Of course, when discussing creative habits, we need to be careful not to censor ourselves prematurely. As we discussed at Extravagaria, most people tend toward one extreme. They need encouragement to overcome their fears of failure and inadequacy. But that doesn't mean that we can divorce ourselves from reality, from human nature, from the limits of the world. Creativity, as Hass himself told us, thrives when it bumps into boundaries.
Being creative means balancing our desire for safety and freedom. Straying too far in either way may work in the short term, but after too long in either land we lose something essential to the creative process.
With Dick Gabriel and Ralph Johnson leading OOPSLA this year, none of us were that the themes of the conference were creativity and discovery. This theme presented itself immediately in the conference's opening keynote speaker, former poet laureate Robert Hass. He gave a marvelous talk on creativity.
Hass began his presentation by reading a poem (whose name I missed) from Dick's new chapbook, Drive On. Bob was one of Dick's early teachers, and he clearly reveled in the lyricism, the rhythm of the poem. Teachers often form close bonds with their students, however long or short the teaching relationship. I know the feeling from both sides of the phenomenon.
He then described his initial panic at thought of introducing the topic of creativity to a thousand people who develop software -- who create, but in a domain so far from his expertise. But a scholar can find ways to understand and transmit ideas of value wherever they live, and Hass is not only a poet but a first-rate scholar.
Charles Dickens burst on scene with publication of The Pickwick Papers. With this novel, Dickens essentially invented the genre of the magazine-serialized novel. When asked how he created a new genre of literature, he said simply, "I thought of Pickwick."
I was immediately reminded of something John Gribble said in his talk at Extravagaria on Sunday: Inspiration comes to those already involved in the work.
Creativity seems to happen almost with cause. Hass consulted with friends who have created interesting results. One solved a math problem thought unsolvable by reading the literature and "seeing" the answer. Another claimed to have resolved the two toughest puzzles in his professional career by going to sleep and waking up with the answer.
So Hass offered his first suggestion for how to be creative: Go to sleep.
Human beings were the first animals to trade instinct for learning. The first major product of our learning was our tools. We made tools that reflected what we learned about solving immediate problems we faced in life. These tools embodied the patterns we observed in our universe.
We then moved on to broader forms of patterns: story, song, and dance. These were,according to Hass, the original forms of information storage and retrieval, the first memory technologies. Eventually, though, we created a new tool, the printing press, that made these fundamentally less essential -- less important!? And now the folks in this room contribute to the ultimate tool, the computer, that in many ways obsoletes human memory technology. As a result, advances in human memory tech have slowed, nearly ceased.
The bulk of Hass's presentation explored the interplay between the conservative in us (to desire to preserve in memory) and the creative in us (the desire to create anew). This juxtaposition of 'conservative' and 'creative' begets a temptation for cheap political shots, to which even Hass himself surrendered at least twice. But the juxtaposition is essential, and Hass's presentation repeatedly showed the value and human imperative for both.
Evolutionary creativity depends on the presence having a constant part and a variable part, for example, the mix of same and different in an animal's body, in the environment. The simultaneous presence of constant and variable is the basis of man's physical life. It is also the basis of our psychic life. We all want security and freedom, in an unending cycle Indeed, I believe that most of us want both all the time, at the same time. Conservative and creative, constant and variable -- we want and need both.
Humans have a fundamental desire for individuation, even while still feeling a oneness with our mothers, our mentors, the sources of our lives. Inspiration, in a way, is how a person comes to be herself -- is in part a process of separation.
"Once upon a time" is linguistic symbol, the first step of the our separation from the immediate action of reading into a created world.
At the same time, we want to be safe and close to, free and faraway. Union and individuation. Remembering and changing.
Most of us think that most everyone else is more creative than we are. This is a form of the fear John Gribble spoke about on Sunday, one of the blocks we must learn to eliminate from our minds -- or at least fool ourselves into ignoring. (I am reminded of John Nash choosing to ignore the people his mind fabricates around him in A Beautiful Mind.)
Hass then told a story about the siren song from The Odyssey. It turns out that most of the stories in Homer's epics are based in "bear stories" much older than Homer. Anyway, Odysseus's encounter with the sirens is part of a story of innovation and return, freedom on the journey followed by a return to restore safety at home. Odysseus exhibits the creativity of an epic hero: he ties himself to the mast so that he can hear the sirens' song without having to take ship so close to the rocks.
According to Hass, in some versions of the siren story, the sirens couldn't sing -- the song was only a sailors' legend. But they desire to hear the beautiful song, if it exists. Odysseus took a path that allowed him both safety and freedom, without giving up his desire.
In preparing for this talk,hass asked himself, "Why should I talk to you about creativity? Why think about it all?" He identified at least four very good reasons, the desire to answer these questions:
So he went off to study what we know about creativity. A scholar does research.
Creativity research in the US began when academic psychologists began trying to measure mental characteristics. Much of this work was done at the request of the military. As time went by, the number of characteristics, perhaps in correlation of research grants awarded by the government. Creativity is, perhaps, correlated with salesmanship. :-) Eventually, we had found several important characteristics, including that there is little or no correlation between IQ and creativity. Creativity is not a province of the intellectually gifted.
Hass cited the research of Howard Gardner and Mihaly Csikszentmihalyi (remember him?), both of whom worked to identify key features of the moment of a creative change, say, when Dickens thought to publish a novel in serial form. The key seems to be immersion in a domain, a fascination with domain and its problem and possibilities. The creative person learns the language of the domain and sees something new. Creative people are not problems solvers but problem finders.
I am not surprised to find language at the center of creativity! I am also not surprised to know that creative people find problems. I think we can save something even stronger, that creative people often create their own problems to solve. This is one of the characteristics that biases me away from creativity: I am a solver more than a finder. But thinking explicitly about this may enable me to seek ways to find and create problems.
That is, as Hass pointed out earlier, one of the reasons for thinking about creativity: ways to make ourselves more creative. But we can use the same ideas to help our children learn the creative habit, and to help create institutions that foster the creative act. He mentioned OOPSLA as a social construct in the domain of software that excels at fostering creative. It's why we all keep coming back. How can we repeat the process?
Hass spoke more about important features of domains. For instance, it seems matter how clear the rules of the domain are at the point that a person enters it. Darwin is a great example. He embarked on his studies at a time when the rules of his domain had just become fuzzy again. Geology had recently expanded European science's understanding of the timeline of the earth; Linnaeus had recently invented his taxonomy of organisms. So, some of the knowledge Darwin needed was in place, but other parts of the domain were wide open.
The technology of memory is a technology of safety. What are the technologies of freedom?
Hass read us a funny poem on story telling. The story teller was relating a myth of his people. When his listener questioned an inconsistency in his story, the story teller says, "You know, when I was a child, I used to wonder that..." Later, the listener asked the same question again, and again, and each time the story teller says, "You know, when I was a child, I used to wonder that..." When he was a child, he questioned the stories, but as he grew older -- and presumably wiser -- he came to accept the stories as they were, to retell them without question.
We continue to tell our stories for their comfort. They make us feel safe.
They is a danger in safety, as it can blind us to the value of change, can make us fear change. This was one of the moments in which Hass surrendered to a cheap political point, but I began to think about the dangers inherent in the other side of the equation, freedom. What sort of blindness does freedom lead us to?
Software people and poets have something in common, in the realm of creativity: We both fall in love with patterns, with the interplay between the constant and the variable, with infinite permutation. In computing, we have the variable and the value, the function and the parameter, the framework and the plug-in. We extend and refactor, exposing the constant and the variable in our problem domains.
Hass repeated an old joke, "Spit straight up and learn something." We laugh, a mockery of people stuck in same old patterns. This hit me right where I live. Yesterday at the closing panel of the Educators' Symposium, Joe Bergin said something that I wrote about a while back: CS educators are an extremely conservative lot. I have something to say about that panel, soon...
First safety, then freedom -- and with it the power to innovate.
Of course, extreme danger, pressure, insecurity can also be the necessity that leads to the creative act. As is often the case, opposites turn out to be true. As Thomas Mann said,
A great truth is a truth whose opposite is also a great truth.
Hass reminds us that there is agony in creativity -- a pain at stuckness, found in engagement with the world. Pain is unlike pleasure, which is homeostatic ("a beer and ballgame"). Agony is dynamic, ceasing to cling to safe position. There is always an element of anxiety, consciousness heightened at the moment of insight, gestalt in face of incomplete pattern.
The audience asked a couple of questions:
I'll close my report with how Hass closed the main part of his talk. He reached "the whole point of his talk" -- a sonnet by Michelangelo -- and he didn't have it in his notes!! So Hass told us the story in paraphrase:
The pain is unbearable, paint dripping in my face, I climb down to look at it, and it's horrible, I hate it, I am no painter...
It was the ceiling of the Sistine Chapel.
~~~~~
UPDATE (10/20/05): Thanks again to Google, I have tracked down the sonnet that Hass wanted to read. I especially love the ending:
Defend my labor's cause,
good Giovanni, from all strictures:
I live in hell and paint its pictures.
-- Michelangelo Buonarroti
I have felt this way about a program before. Many times.
OOPSLA has arrived, or perhaps I have arrived at OOPSLA. I almost blew today off, for rest and a run and work in my room. Some wouldn't have blamed me after yesterday, which began at 4:42 AM with a call from Northwest Airlines that my 7:05 AM flight had been cancelled, included my airline pilot missing the runway on his first pass at the San Diego airport, and ended standing in line for two hours to register at my hotel. But I dragged myself out of my room -- in part out of a sense of obligation to having been invited to participate, and in part out of a schoolboy sense of propriety that I really ought to go to the events at my conferences and make good use of my travels.
My event for the day was an all-day workshop called Extravagaria III: Hunting Creativity. As its title reveals, this workshop was the third in a series of workshops initiated by Richard Gabriel a few years ago. Richard is motivated by the belief that computer science is in the doldrums, that what we are doing now is mostly routine and boring, and that we need a jolt of creativity to take the next Big Step. We need to learn how to write "very large-scale programs", but the way we train computer scientists, especially Ph.D. students and faculty, enforce a remarkable conservatism in problem selection and approach. The Extravagaria workshops aim to explore creativity in the arts and sciences, in an effort to understand better what we mean by creativity and perhaps better "do it" in computer science.
The workshop started with introductions, as so many do, but I liked the twist that Richard tossed in: each of us was to tell what was the first program we ever wrote out of passion. This would reveal something about each of us to one another, and also perhaps recall the same passion within each storyteller.
My first thought was of a program I wrote as a high school junior, in a BASIC programming course that was my first exposure to computers and programs. We wrote all the standard introductory programs of the day, but I was enraptured with the idea of writing a program to compute ratings for chessplayers following the Elo system used for chessplayers. This was much more complex than the toy problems I solved in class, requiring input in the form of player ratings and a crosstable showing results of games among the players and output in the form of updated ratings for each player. It also introduced new sorts of issues, such as using text files to save state between runs and -- even more interesting to me -- the generation of an initial set of ratings through a mechanism of successive approximations, process that may never quite converge unless we specified an epsilon larger than 0. I ultimately wrote a program of several hundred lines, a couple of orders of magnitude larger than anything I had written before. And I cared deeply about my program, the problem it solved, and its usefulness to real people.
I enjoyed everyone else's stories, too. They reminded us all about the varied sources of passion, and how a solving a problem can open our eyes to a new world for us to explore. I was pleased by the diversity of our lot, which included workshop co-organizer John Gribble, a poet friend of Richard's who has never written a program; Rebecca Rikner, the graphic artist who designed the wonderful motif for Richard's book Writers' Workshops and the Work of Making Things, and Guy Steele, one of the best computer scientists around. The rest of us were computer science and software types, including one of my favorite bloggers, Nat Pryce. Richard's first passionate program was perhaps a program to generate "made-up words" from some simple rules, to use in naming his rock-and-roll-band. Guy offered three representative, if not first, programs: a Lisp interpreter written in assembly language, a free verse generator written in APL, and low chart generator written in RPG. This wasn't the last mention of APL today, which is often the sign of a good day.
Our morning was built around an essay written by John Gribble for the occasion, called "Permission, Pressure, and the Creative Process". John read his essay, while occasionally allowing us in the audience to comment on his remarks or previous comments. John offered as axioms two beliefs that I share with him:
What the arts perhaps offer scientists is the history and culture of examining the creative process. We scientists and other analytical folks tend to focus on product, often to the detriment of how well we understand how we create them.
John quoted Stephen King from his book On Writing, that the creator's job is not to find good ideas but to recognize them when they come along. For me, this idea foreshadows Ward Cunningham's keynote address at tomorrow's Educators' Symposium. Ward will speak on "nurturing the feeble simplicity", on recognizing the seeds of great ideas despite their humility and nurturing them into greatness. As Brian Foote pointed out later in the morning, this sort of connection is what makes conferences like OOPSLA so valuable and fun -- plunk yourself down into an idea-rich environment, soak in good ideas from good minds, and your own mind has the raw material it needs to make connections. That's a big part of creativity!
John went on to assert that creativity isn't rare, but rather so common that we are oblivious to it. What is rare is for people to act on their inspirations. Why do we not act? We have so low an opinion of our selves that we figure the inspiration isn't good enough or that we can't do it justice in our execution. Another reason: We fear to fail, or to look bad in front of our friends and colleagues. We are self-conscious, and the self gets in the way of the creative act.
Most people, John believes, need permission to act creatively. Most of us need external permission and approval to act, from friends or colleagues, peers or mentors. This struck an immediate chord with me in three different relationships: student and teacher, child and parent, and spouse and spouse. The discussion in our workshop focused on the need to receive permission, but my immediate thought was of my role as potential giver of permission. My students are creative, but most of them need me to give them permission to create. They are afraid of bad grades and of disappointing me as their instructor; they are self-conscious, as going through adolescence and our school systems tend to make them. My young daughters began life unself-conscious, but so much of their lives are about bumping into boundaries and being told "Don't do that." I suspect that children grow up most creative in an environment where they have permission to create. (Note that this is orthogonal to the issue of discipline or structure; more on that later.) Finally, just as I find myself needing my wife's permission to do and act -- not in the henpecked husband caricature, but in the sense of really caring about what she thinks -- she almost certainly feels the need for *my* permission. I don't know why this sense that I need to be a better giver of permission grew up so strong so quickly today, but it seemed like a revelation. Perhaps I can change my own behavior to help those around me feel like they can create what they want and need to create. I suspect that, in loosing the restrictions I project onto others, I will probably free myself to create, too.
When author Donald Ritchie is asked how to start writing, he says, "First, pick up your pencil..." He's not being facetious. If you wait for inspiration to begin, then you'll never begin. Inspiration comes to those already involved in the work.
Creativity can be shaped by constraints. I wrote about this idea six months or so ago in an entry named Patterns as a Source of Freedom. Rebecca suggested that for her at least constraints are essential to creativity, that this is why she opted to be a graphic designer instead of a "fine artist". The framework we operate in can change, across projects or even within a project, but the framework can free us to create. Brian recalled a song by the '80s punk-pop band Devo called Freedom Of Choice:
freedom of choice is what you got
then if you got it you don't want it
seems to be the rule of thumb
don't be tricked by what you see
you got two ways to go
freedom from choice is what you want
Richard then gave a couple of examples of how some artists don't exercise their choice at the level of creating a product but rather at the level of selecting from lots of products generated less self-consciously. In one, a photographer for National Geographic, put together a pictorial article containing 22 pictures selected from 40,000 photos he snapped. In another, Francis Ford Coppolla shot 250 hours of film in order to create the 2-1/2 hour film Apocalypse Now.
John then told a wonderful little story about an etymological expedition he took along the trail of ideas from the word "chutzpah", which he adores, to "effrontery", "presumptuous", and finally "presumption" -- to act as if something were true. This is a great way to free oneself to create -- to presume that one can, that one will, that one should. Chutzpah.
Author William Stafford had a particular angle he took on this idea, what he termed the "path of stealth". He refused to believe in writer's block. He simply lowered his standards. This freed him to write something and, besides, there's always tomorrow to write something better. But as I noted earlier, inspiration comes to those already involved in the work, so writing anything is better than writing nothing.
As editor John Gould once told Stephen King, "Write with the door closed. Revise with the door open." Write for yourself, with no one looking over your shoulder. Revise for readers, with their understanding in mind.
Just as permission is crucial to creativity, so is time. We have to "make time", to "find time". But sometimes the work is on its own time, and will come when and at the rate it wants. Creativity demands that we allow enough time for that to happen! (That's true even for the perhaps relatively uncreative act of writing programs for a CS course... You need time, for understanding to happen and take form in code.)
Just as permission and time are crucial to creativity, John said, so is pressure. I think we all have experienced times when a deadline hanging over our heads seemed to give us the power to create something we would otherwise have procrastinated away. Maybe we need pressure to provide the energy to drive the creative act. This pressure can be external, in the form of a client, boss, or teacher, or internal.
This is one of the reasons I do not accept late work for a grade in my courses; I believe that most students benefit from that external impetus to act, to stop "thinking about it" and commit to code. Some students wait too long and reach a crossover point: the pressure grows quite high, but time is too short. Life is a series of balancing acts. The play between pressure and time is, I think, fundamental. We need pressure to produce, but we need time to revise. The first draft of a paper, talk, or lecture is rarely as good as it can be. Either I need to give myself to create more and better drafts, or -- which works better for me -- I need to find many opportunities to deliver the work, to create multiple opportunities to create in the small through revision, variation, and natural selection. This is, I think, one of the deep and beautiful truths embedded in extreme programming's cycle "write a test, write code, and refactor".
Ultimately, a professional learns to rely more on internal pressure, pressure applied by the self for the self, to create. I'm not talking about the censoriousness of self-consciousness, discussed earlier, which tells us that what we produce isn't good enough -- that we should not act, at least in the current product. I'm talking about internal demands that we act, in a particular way or time. Accepting the constraints of a form -- say, the line and syllable restrictions of haiku, or the "no side effects" convention of functional programming style -- puts pressure on us to act in a way, whether it's good or bad. John gave us two other kinds of internal pressure, ones he applies to himself: the need to produce work to share at his two weekly writers' workshops, and the self-discipline of submitting work for publication every month. These pressures involve outside agents, but they are self-imposed, and require us do something we might otherwise not.
John closed with a short inspiration. Pay attention to your wishes and dreams. They are your mind's way of telling you to do something.
We spent the rest of the morning chatting as a group on whatever we were thinking after John's talk. Several folks related an experience well-known to any teacher: someone comes to us asking for help with a problem and, in the act of explaining the problem to us they discover the answer for themselves. Students do this with me often. Is the listener essential to this experience, or could we just ask if we were speaking to someone? I suspect that another person is essential for this to work for the learner, both because having a real person to talk to makes us explain things (pressure!) and because the listener can force us to explain the problem more clearly ("I don't understand this yet...")
A recurring theme of the morning was the essential interactivity of creativity, even when the creator works fundamentally alone. Poets need readers. Programmers need other folks to bounce ideas off of. Learners need someone to talk to, if only to figure things out for themselves. People can be sources of ideas. They can also be reflectors, bouncing our own ideas back at us, perhaps in a different form or perhaps the same, but with permission to act on them. Creativity usually comes in the novel combination of old ideas, not truly novel ideas.
This morning session was quite rewarding. My notes on the whole workshop are, fittingly, about half over now, but this article has already gotten quite long. So I think I'll save the afternoon sessions for entries to come. These sessions were quite different from the morning, as we created things together and then examined our processes and experiences. They will make fine stand-alone articles that I can write later -- after I break away for a bite at the IBM Eclipse Technology Exchange reception and for some time to create a bit on my own for what should take over my mind for a few hours: tomorrow's Educators' Symposium, which is only twelve hours and one eight- to ten-mile San Diego run away!
... is right here.
I'm not saying that Doug doesn't have a social life; for all I know, he's a wild and crazy guy. But he has the well-earned reputation of answering e-mail at all hours of the day. I've sent him e-mail at midnight, only to have an answer hit my box within minutes. His grad students all tell me they've had the same experience, only at even more nocturnal hours. They are in awe. I'm a mix of envious and relieved.
I don't know why this was the first thought that popped into my head when I read Becky's post just now. Maybe it has something to do with the fact that I'm sitting in my office at 7:30 PM on a Friday evening. (Shh. Don't tell my students.)
First... A student related this to me today:
But after your lecture on mutual recursion yesterday, [another student] commented to me, "Is it wrong to think code is beautiful? Because that's beautiful."
It certainly isn't wrong to think code is beautiful. Code can be beautiful. Read McCarthy's original Lisp interpreter, written in Lisp itself. Study Knuth's TeX program, or Wirth's Pascal compiler. Live inside a Smalltalk image for a while.
I love to discover beautiful code. It can be professional code or amateur, open source or closed. I've even seen many beautiful programs written by students, including my own. Sometimes a strong student delivers something beautiful as expected. Sometimes, a student surprises me by writing a beautiful program seemingly beyond his or her means.
The best programmers strive to write beautiful code. Don't settle for less.
(What is mutual recursion, you ask? It is a technique used to process mutually-inductive data types. See my paper Roundabout if you'd like to read more.)
The student who told me the quote above followed with:
That says something about the kind of students I'm associating with.
... and about the kind of students I have in class. Working as an academic has its advantages.
Second... While catching up on some blog reading this afternoon, I spent some time at Pragmatic Andy's blog. One of his essays was called What happens when t approaches 0?, where t is the time it takes to write a new application. Andy claims that this is the inevitable trend of our discipline and wonders how it will change the craft of writing software.
I immediately thought of one answer, one of those unforgettable Kent Beck one-liners. On a panel at OOPSLA 1997 in Atlanta, Kent said:
As speed of development approaches infinity, reusability becomes irrelevant.
If you can create a new application in no time flat, you would never worry about reusing yesterday's code!
----
Is there a connection between these two snippets? Because I am teaching a course in programming languages course this semester, and particularly a unit on functional programming right now, these snippets both call to mind the beauty in Scheme.
You may not be able to write networking software or graphical user interfaces using standard Scheme "out of the box", but you can capture some elegant patterns in only a few lines of Scheme code. And, because you can express rather complex computations in only a few lines of code, the speed of development in Scheme or any similarly powerful language approaches infinity much faster than does development in Java or C or Ada.
I do enjoy being able to surround myself with the possibility of beauty and infinity each day.
This being Friday, September 9, I have to come to grips with the fact that I won't be participating in PLoP 2005. This is the 12th PLoP, and it would have been my 10th, all consecutively. PLoP has long been one of my favorite conferences, both for how much it helps me to improve my papers and my writing and for how many neat ideas and people I encounter there. Last year's PLoP led directly to four blog entries, on patterns as autopsy, patterns and change, patterns and myth, and the wiki of the future, not to mention a few others indirectly later. Of course, I also wrote about the wonderful running in and around Allerton Park, the pastoral setting of PLoP. I will dearly miss doing my 20-miler there this weekend...
Sadly, events conspired against me going to PLoP this year. The deadline for submissions fell at about the same time as the deadline for applications for the chair of my department, both of which fell around when I was in San Diego for the spring planning meeting for OOPSLA 2005. Even had I submitted, I would have had a hard time doing justice to paper revisions through the summer, as I learned the ropes of my new job. And now, new job duties make this a rather bad time to hop into the car and drive to Illinois for a few days. (Not that I wasn't tempted early in the week to drive down this morning to join in for a day!)
I am not certain if other academics feel about some of the conferences they attend the way I feel about PLoP, OOPSLA, and ChiliPLoP, but I do know that I don't feel the same way about other conferences that I attend, even ones I enjoy. The PLoPs offer something that no other conference does: a profound concern for the quality of technical writing and communication more generally. PLoP Classic, in particular, has a right-brain feel unlike any conference I've attended. But don't think that this is a result of being overrun by a bunch of non-techies; the conference roster is usually dominated by very good minds from some of the best technical outfits in the world. But these folks are more than just techies.
Unfortunately I'm not the only regular who is missing PLoP this year. The attendee list for 2005 is smaller than in recent years, as was the number of submissions and accepted papers. The Hillside Group is considering the future of PLoP and ChiliPLoP in light of the more mainstream role of patterns in the software world and the loss of cache that comes when one software buzzword is replaced with another. Patterns are no longer the hot buzzword -- they are a couple of generations of buzzwords beyond that -- which changes how conferences in the area need to be run. I think, though, that it is essential for us to maintain a way for new pattern writers to enter the community and be nurtured by pattern experts. It is also essential that we continue to provide a place where we care not only about the quality of technical content but also about the quality of technical writing.
On the XP mailing list this morning, Ron Jeffries mentioned the "patterns movement":
In the patterns movement, there was the notion of "forces". The idea of applying a pattern or pattern language was to "balance" the forces.
I hope Ron's use of past tense was historical, in the sense that the patterns movement first emphasized the notion of forces "back then", rather than a comment that the patterns movement is over. The heyday is over, but I think we software folks still have a lot to learn about design from patterns.
I am missing PLoP 2005. Sigh. I guess there's always ChiliPLoP 2006. Maybe I can even swing EuroPLoP next year.
This spring I was asked to participate on a panel at XP2005, which recently wrapped up in the UK. This panel was on agile practices in education, and as you may guess I would have enjoyed sharing some of my ideas and learning from the other panelists and from the audience. Besides, I've not yet been to any of the agile software development conferences, and this seemed like a great opportunity. Unfortunately, work and family duties kept me home for what is turning out to be a mostly at-home summer.
In lieu of attending XP2005, I've enjoyed reading blog reports of the goings-on. One of the highlights seems to have been Laurent Bossavit's Coding Dojo workshop. I can't say that I'm surprised. I've been reading Laurent's blog, Incipient(thoughts), for a while and exchanging occasional e-mail messages with him about software development, teaching, and learning. He has some neat ideas about learning how to develop software through communal practice and reflection, and he is putting those ideas into practice with his dojo.
The Coding Dojo workshop inspired Uncle Bob to write about the notion of repeated practice of simple exercises. Practice has long been a theme of my blog, going back to one of my earliest posts. In particular, I have written several times about relatively small exercises that Joe Bergin and I call etudes, after the compositions that musicians practice for their own sake, to develop technical skills. The same idea shows up in an even more obviously physical metaphor in Pragmatic Dave's programming katas.
The kata metaphor reminds us of the importance of repetition. As Dave wrote in another essay, students of the martial arts repeat basic sequences of moves for hours on end. After mastering these artificial sequences, the students move on to "kumite", or organized sparring under the supervision of a master. Kumite gives the student an opportunity to assemble sequences of basic moves into sequences that are meaningful in combat.
Repeating programming etudes can offer a similar experience to the student programmer. My re-reading of Dave's article has me thinking about the value of creating programming etudes at two levels, one that exercises "basic moves" and one that gives the student an opportunity to assemble sequences of basic moves in the context of a more open-ended problem.
But the pearl in my post-XP2005 reading hasn't been so much the katas or etudes themselves, but one of the ideas embedded in their practice: the act of emulating a master. The martial arts student imitates a master in the kata sequences; the piano student imitates a master in playing Chopin's etudes. The practice of emulating a master as a means to developing technical proficiency is ubiquitous in the art world. Renaissance painters learned their skills by emulating the masters to whom they were apprenticed. Writers often advise novices to imitate the voice or style of a writer they admire as a way to ingrain how to have a voice or follow a style. Rather than creating a mindless copycat, this practice allows the student to develop her own voice, to find or develop a style that suits their unique talents. Emulating the master constrains the student, which frees her to focus on the elements of the craft without the burden of speaking her own voice or being labeled as "derivative".
Uncle Bob writes of how this idea means just as much in the abstract world of software design:
Michael Feathers has long pondered the concept of "Design Sense". Good designers have a "sense" for design. They can convert a set of requirements into a design with little or not effort. It's as though their minds were wired to translate requirements to design. They can "feel" when a design is good or bad. They somehow intrinsically know which design alternatives to take at which point.Perhaps the best way to acquire "Design Sense" is to find someone who has it, put your fingers on top of theirs, put your eyeballs right behind theirs, and follow along as they design something. Learning a kata may be one way of accomplishing this.
Watching someone solve a kata in a workshop can give you this sense. Participating in a workshop with a master, perhaps as programming partner, perhaps as supervisor, can, too.
The idea isn't limited to software design. Emulating a master is a great way to learn a new programming language. About a month ago, someone on the domain-driven design mailing list asked about learning a new language:
So assuming someone did want to want to learn to think differently what would you go with? Ruby, Python, Smalltalk?
Ralph Johnson's answer echoed the importance of working with a master:
I prefer Smalltalk. But it doesn't matter what I prefer. You should choose a language based on who is around you. Do you know somebody who is a fan of one of these languages? Could you talk regularly with this person? Better yet, could you do a project with this person?By far the best way to learn a language is to work with an expert in it. You should pick a language based on people who you know. One expert is all it takes, but you need one.
The best situation is where you work regularly with the expert on a project using the language, even if it is only every Thursday night. It would be almost as good if you would work on the project on your own but bring code samples to the expert when you have lunch twice a week.
It is possible to learn a language on your own, but it takes a long time to learn the spirit of a language unless you interact with experts.
Smalltalk or Scheme may be the best in some objective (or entirely subjective!) sense, but unless you can work with an expert... it may not the right language for you, at least right now.
As a student programmer -- and aren't we all? -- find a person to whom you can "apprentice" yourself. Work on projects with your "master", and emulate his style. Imitate not only high-level design style but also those little habits that seem idiosyncratic and unimportant: name your files and variables in the same way; start your programming sessions with the same rituals. You don't have to retain all of these habits forever, and you almost certainly won't. But in emulating the master you will learn and internalize patterns of practice, patterns of thinking, and, yes, patterns of design and programming. You'll internalize them through repetition in the context of real problems and real programs, which give the patterns the richness and connectedness that make them valuable.
After lots of practice, you can begin to reflect on what you've learned and to create your own style and habits. In emulating a master first, though, you will have a chance to see deeper into the mind and actions of someone who understands and use what you see to begin to understand better yourself, without the pressure of needing to have a style on your own yet.
If you are a computer scientist rather than a programmer, you can do much the same thing. Grad students have been doing this as long as there have been grad students. But in these days of the open-source software revolution, any programmer with a desire to learn has ample opportunity to go beyond the Powerbook on his desk. Join an open-source project and interact with a community of experts and learners -- and their code.
And we still have open to us an a more traditional avenue, in even greater abundance, literature. Seek out a writer whose books and articles can serve in an expert's stead. Knuth, Floyd, Beck, Fowler... the list goes on and on. All can teach you through their prose and their code.
Knowing and doing go hand in hand. Emulating the masters is an essential part of the path.
A couple of days ago, blog reader Mike McMillan sent me a link to Stanley Fish's New York Times op-ed piece, Devoid of Content. Since then, several of my CS colleagues have recommended this article. Why all the interest in an opinion piece written by an English professor?
The composition courses that most university students take these days emphasize writing about something: current events, everyday life, or literature. But Fish's freshman composition class does something much different. He asks students to create a new language, "complete with a syntax, a lexicon, a text, rules for translating the text and strategies for teaching your language to fellow students". He argues that the best way to learn how to write is to have a deep understanding of "a single proposition: A sentence is a structure of logical relationships." His students achieve this understanding by having to design the mechanisms by which sentences represent relationships, such as tense, number, manner, mood, and agency.
Fish stakes out a position that is out of step with contemporary academia: Learning to write is about form, not content. Content is not only the not the point; it is a dangerous delusion that prevents students from learning what they most need.
Content is a lure and a delusion, and it should be banished from the classroom. Form is the way.
Fish doesn't say that content isn't important, only that it's should not be the focus of learning to write. Students learn content in their science courses, their social science courses, and their humanities courses -- yes, even in their literature courses.
(I, for one, am pleased to see Fish distinguish the goals of the composition courses taught in English departments from the goals of the literature courses taught there. Too many students lose interest in their comp courses when they are forced to write about, oh, a poem by Edna St. Vincent Millay. Just because a student doesn't connect with twentieth-century lyric poetry doesn't mean that he shouldn't or can't learn to write well.)
So, how is Fish's argument relevant to a technical audience? If you have read my blog much, you can probably see my interest in the article. I like to read books about writing, to explore ways of writing better programs. I've also written a little about the role form plays in evaluating technical papers and unleashing creativity. On the other side of the issue, though, I have several times recently about the role of real problems and compelling examples in learning to program. My time at ChiliPLoP 2005 was spent working with friends to explore some compelling examples for CS1.
In the context of this ongoing discussion among CS educators, one of my friends sloganized Fish's position as "It's not the application, stupid; it's the BNF."
So, could I teach my freshman computer programming class after Fish's style? Probably not by mimicking his approach note for note, but perhaps by adopting the spirit of his approach.
We first must recognize that freshman CS students are usually in a different intellectual state from freshman comp students. When students reach the university, they may not have studied tense and mood and number in much detail, but they do have an implicit understanding of language on which the instructor can draw. Students at my university already know English in a couple of ways. First, they speak the language well enough to participate in everyday oral discourse. Second, they know enough at least to string together words in a written form, though perhaps not well enough to please Fish or me.
My first-year programming students usually know little or nothing about a programming language, either as a tool for simple communication or in terms of its underlying syntactic structures. When Fish's students walk into his classroom, he can immediately start a conversation with them, in a rich language they share. He can offer endless example sentences for his students to dissect, to rearrange, to understand in a new way. These sentences may be context-free, but they are sentences.
In a first-year programming course, instructors typically have to spiral our dissection of programs with the learning of new language features and syntax. The more complex the language, the wider and longer the spiral must be.
Using a simple computer language might make an approach like Fish's work in a CS1 course. I think of the How to Design Programs project in these terms. Scheme is simple enough syntactically that the authors can rather quickly focus on the structure of programs, much as Fish focuses on the structure of sentences. The HtDP approach emphasizes form through its use of BNF definitions and "design recipes". However, I don't get the sense that HtDP removes content from the classroom so much as it removes it from the center of attention. Felleisen et al. still try to engage their students with examples that might interest someone.
So, I think that we may well be able to teach introductory programming in the spirit of Fish's approach. But is it a good idea? How much of the motivation to learn how to program springs from the desire to do something particular? I do not know the answer to this question, but it lies at the center of the real problems/compelling examples discussion.
In an unexpected twist of fate, I was thumbing through Mark Guzdial's new book, Introduction to Computing and Programming with Python: A Multimedia Approach, and read the opening sentences of its preface:
Research on computing education clearly demonstrates that one doesn't just "learn to program." One learns to program something [5,20], and the motivation to do that something can make the difference between learning and not learning to program [7].
(The references are to papers on situated learning of the sort Seymour Papert has long advocated.)
I certainly find myself in the compelling problems camp these days and so am heartened by Guzdial's quote, and the idea embodied in his text. But I also feel a strong pull to find ways to emphasize the forms that will help students become solid programmers. That pull is the essence of my interest in documenting elementary programming patterns and using them to gain leverage in the classroom.
Regardless of how directly we might use Fish's approach to teach first-year courses in programming, I am intrigued by what seems to me to be a much cleaner connection between his ideas and the CS curriculum, the traditional Programming Languages course! I'll be teaching our junior/senior level course in languages this fall, and it seems that I could adopt Fish's course outline almost intact. I could walk in on Day 1 and announce that, by the end of the semester, each group of students will have created a new programming language, complete with a syntax, a set of primitive expressions, rules for translating programs, and the whole bit. Their evolving language designs would serve as the impetus for exploring the elements of language at a deeper level, touching all the traditional topics such as bindings, types, scope, control structures, subprograms, and so on. We could even implement our growing understanding in a series of increasingly complex interpreters that extract behavior from syntactic expressions.
Actually, this isn't too far from the approach that I have used in the past, based on the textbook Essentials of Programming Languages. I'll need to teach the students some functional programming in Scheme first, but I could then turn students loose to design and implement their own languages. I could still use the EOPL-based language that I call Babel as my demonstration language in class.
School's barely out for the summer, and I'm already jazzed by a new idea for my fall class. I hope I don't peak too soon. :-)
As you can see, there are lots of reasons that Fish's op-ed piece has attracted the attention of CS folks. It's about language and learning to use it, which is ultimately what much of computer science and software development are about.
Have you heard of Stanley Fish before? I first ran into him and his work when I read a blog entry by Brian Marick on the role the reader plays in how we write code and comments. Brian cited Fish's work on reader-response criticism and hypothesized an application of it to programming. You may have encountered Fish through Brian's article, too, if you've read one of my oldest blog entries. I finally checked the book by Fish that Brian recommended so long ago out of the library today -- along with another Fish book, The Trouble with Principle, which pads my league-leading millions total. (This book is just for kicks.)
[ See what happens when I start talking? I can't shut up. :-) ]
My previous entry brought to mind two related ideas. Think of these as more Agile Moments.
The Delgado Codex
I ran across a neat little example of reflective practice on the major league baseball diamond in The Scholarly Rigor of Carlos Delgado. Carlos is the first baseman for the Florida Marlins in U.S. baseball's National League. He apparently has the agile habit of recording detailed information about every one of his at-bats in a notebook he keeps with him in the dugout. By collecting this data, he is able to derive feedback from his results and use that to improve his future at-bats.
As the article points out, most professional sports teams -- at least in America -- record all of their performances these days and then mine the film for information they can use to do better next time out. Delgado, "like a medieval Benedictine at Monte Cassino", is one of the few major leaguers who still use the ancient technologies of pencil and paper to personally track his own performances. The act of writing is valuable on its own, but I think that as important is the fact that Delgado reflects on his performance immediately after the event, when the physical sensations of the performance are still fresh and accessible to his conscious mind.
How is this related to my previous post? I think that we programmers can benefit from such a habit. If we recorded the smells that underlay our refactorings for a month or even a week, we would all probably have a much better sense of our own tendencies as programmers, which we could then feed back into our next code. And, if we shared our experiences, we might develop an even more comprehensive catalog of smells and refactorings as a community. If it's good enough for Donald Knuth, it ought to work for me, too.
Agility works for Delgado, one of the better offensive players in all of baseball. Knowing about his habit, I'm even happier to have him as a member of my rotisserie baseball team, the Ice Nine. :-)
Intentional Duplication
The Zen Refactoring thread on the XP mailing list eventually came around to the idea deliberately creating code duplication. The idea is this: It is easier first to write code that duplicates other code and then to factor the duplication out later than it is to write clean code first or to refactor first and then add the new code.
I operate in this way most of the time. It allows me to add a new feature to my code immediately, with as little work as possible, without speculating about duplication that might occur in the future. Once I see the actual duplication, I make it go away. Copy-and-paste can be my friend.
This technique is one way that you can refactor your code toward suitable domain abstractions away from primitive data. When you run into a situation where you find yourself handling a tolerance in multiple places, Extract Class does the trick. This isn't a foolproof approach, though, as Chris Wheeler pointed out in his article. What happens when you have references to mass-as-an-int in zillions of places and only then does the client say, "Um, we allow tolerances of 0.1g"? Good design and good refactoring tools are your friend then.
In the same thread, Ron Jeffries commented:
> I have also sometimes created the duplication, and then
> worked to make the duplicated code as similar as possible
> before removing the duplication. Does anyone else do this?I once saw Kent Beck do that in a most amazing way, but I haven't learned the trick of making code look similar prior to removing duplication; would love to see an example.
Now I have fodder for a new blog entry: to write up a simple example of this technique that I use in my freshman-level OOP programming course. It's a wonderful example of how a little refactoring can make a nice design fall out naturally.
How is this related to my previous post? Duplication is one of my pet code smells, though I often create it willingly, with the intention of immediately factoring it out. Like Primitive Obsession, though you have to learn to strike a proper balance between too little and too much. Just right is hard to find sometimes.
Recently, Chris Wheeler posted a thoughtful blog entry called My Favourite Smells, which described only one smell, but one every OOP programmer knows deep in his soul: using a primitive data type instead of a domain-specific type. James Shore calls this smell Primitive Obsession, and Kevin Rutherford calls it Primitive Feature Envy.
Chris has been justifiably lauded for starting a conversation on this topic. I find this smell in my programs and even in many of the programs I read from good OOP programmers. When programmers are first learning to write object-oriented programs, the tendency to write code in terms only of the primitive data types is hard to shake. Who needs that Piece class, when a simple integer flag taking values from 1 to 4 will do just fine? (Heck, we can always use Hungarian Notation to make the semantics clear. :-) When students come to see the value of that Piece class, they begin to see the value of OOP.
That said, we have to be careful to remember that this smell is not an absolute indicator. There is an inherent tension between the desire to create classes to model the domain more closely and the desire to do the simplest thing that could possibly work. If I try to wrap every piece of primitive data in its own class, I can very quickly create a lot of unnecessary code that makes my program worse, not better. My program looks like it has levels of abstraction that simply aren't there.
That's not the sort of thing that Chris, James, and Kevin are advocating, of course. But we need to learn how to strike the proper balance between Primitive Obsession and Class Obsession, to find the abstractions that make up our domain and implement them as such. I think that this is one of the reasons that Eric Evans' book Domain-Driven Design is so important: it goes a long way toward teaching us how to make these choices. Ultimately, though, you can only grok this idea through experience, which usually means doing it wrong many times in both directions so that your mind learns the patterns of good designs. As Chris', James', and Kevin's articles all point out, most of us start with a predilection to err on the side of primitives.
One way to push yourself to learn this balance is to use the Three Bears pattern first described by Kent Beck to create situations in which you confront the consequences of going too far one way or the other. I think that this can be another one of those programming etudes that help you become a better programmer, a lá the Polymorphism Challenge that Joe Bergin and I used at