PH: Math is collaborative?
SS: Yeah, math is social. ... The fact that math is social would come as a surprise to the people who think of it as antisocial.
PH: It might also come as a surprise to some math teachers!
SS: It's extremely social. Mathematicians constantly spend time talking to each other about places where they're stuck. They get insights from each other, new ways of looking at things. Sometimes it's just to commiserate.
Programming is social, too. Most people think it's not. With assistance from media portrayals of programmers and sloppy stereotypes of our own, they think most of us would prefer to work alone in the dark. Some do, of course, but even then most programmers I know like to talk shop with other programmers all the time. They like to talk about the places where they are stuck, as well as the places they used to be stuck. War stories are the currency of the programmer community.
I think a big chunk of the "programming solo" preference many programmers profess is learned habit. Most programming instruction and university course work encourages or requires students to work alone. What if we started students off with pair programming in their CS 1 course, and other courses nurtured that habit throughout the rest of their studies? Perhaps programmers would learn a different habit.
My agile software development students this semester are doing all of their project work via pair programming. Class time is full of discussion: about the problem they are solving, about the program they are evolving, and about the intricacies of Java. They've been learning something about all three, and a large part of that learning has been social.
They've only been trying out XP for a couple of weeks, so naturally the new style hasn't replaced their old habits. I see them fall out of pairing occasionally. One partner will switch off to another computer to look up the documentation for a Java class, and pretty soon both partners are quietly looking at their own screens. Out of deference to me or the course, though, they return after a couple of minutes and resume their conversation. (I'm trying to be a gentle coach, not a ruthless tyrant, when it comes to the practices.)
I suspect a couple members of the class would prefer to program on their own, even after noticing the benefits of pairing. Others really enjoy pair programming but may well fall back into solo programming after the class ends. Old habits die hard, if at all. That's too bad, because most of us are better programmers when pairing.
But even if they do choose, or fall back into, old habits, I'm sure that programming will remain a social activity for them, at some level. There are too many war stories to tell.
Brent Simmons wrote a blog entry on his time at UserLand. After describing a few of the ideas that founder Dave Winer created and extending, such as RSS and blogging, Simmons said this about Winer:
The tech was his invention too: he built the thing he needed to be able to build other things.
This is among the highest praise one can bestow on an inventor. It's also one of the things I like about computer science. The hallmark of so many interesting advances in computing is the creation of a technology or language that makes the advance possible. Sometimes the enabling technology turns out to be pretty important in its own right. Sometimes, it's a game changer. But even when it is only a scaffold to something bigger, it needed to be created.
Rhett Allain asked his intro physics students to write a short bit of Python code to demonstrate some idea from the course, such as the motion of an object with a constant force, or projectile motion with air resistance. Apparently, at least a few complained: "Wait! I'm not a computer scientist." That caused Allain to wonder...
I can just imagine the first time a physics faculty told a class that they needed to draw a free body diagram of the forces on an object for the physics solutions. I wonder if a student complained that this was supposed to be a physics class and not an art class.
As Allain points out, the barriers that used to prevent students from doing numerical calculations in computer programs have begun to disappear. We have more accessible languages now, such as Python, and powerful computers are everywhere, capable of running VPython and displaying beautiful visualizations.
About all that remains is teaching all physics students, even the non-majors, a little programming. The programs they write are simply another medium through which they can explore physical phenomena and perhaps come to understand them better.
Allain is exactly right. You don't have to be an artist to draw simple diagrams or a mathematician to evaluate an integral. All students accept, if grudgingly, that people might reasonably expect them to present an experiment orally in class.
Students don't have to be "writers", either, in order for teachers or employers to reasonably expect them to write an essay about physics or computer science. Even so, you might be surprised how many physics and computer science students complain if you ask them to write an essay. And if you dare expect them to spell words correctly, or to write prose somewhat more organized than Faulkner stream of consciousness -- stand back.
(Rant aside, I have been quite lucky this May term. I've had my students write something for me every night, whether a review of something they've read or a reflection on the practices they are struggling to learn. There's been nary a complaint, and most of their writings have been organized, clear, and enjoyable to read.)
You don't have to be a physicist to like physics. I hope that most educated adults in the 21st century understand how the physical world works and appreciate the basic mechanisms of the universe. I dare to hope that many of them are curious enough to want to learn more.
You also don't have to be a computer programmer, let alone a computer scientist, to write a little code. Programs are simply another medium through which we can create and express ideas from across the spectrum of human thought. Hurray to Allain for being in the vanguard.
Note. Long-time readers of this blog may recognize the ideas underlying Allain's approach to teaching introductory physics. He uses Matter and Interactions, a textbook and set of supporting materials created by Ruth Chabay and Bruce Sherwood. Six years ago, I wrote about some of Chabay's and Sherwood's ideas in an entry on creating a dialogue between science and CS and mentioned the textbook project in an entry on scientists who program. These entries were part of a report on my experiences attending SECANT, a 2007 NSF workshop on the intersection of science, computation, and education.
I'm glad to see that the Matter and Interactions project continued to fruition and has begun to seep into university physics instruction. It sounds like a neat way to learn physics. It's also a nice way to pick up a little "stealth programming" along the way. I can imagine a few students creating VPython simulations and thinking, "Hey, I'd like to learn more about this programming thing..."
While cleaning up the house recently for a family visit, I came across a stack of newspaper articles I'd saved from last fall. Among them was an article about a September 7, 2013, exhibition at The National Museum of Computing in Bletchley Park, Milton Keynes, England. The exhibition was titled "Celebrating the Heroines of Computing". That alone would have made the article worth clipping, but it had a closer connection to me: it featured a CS professor from the state of Iowa, who was also a Catholic nun.
Sister Mary Kenneth Keller was a professed member of the Sisters of Charity of the Blessed Virgin Mary, an order of nuns based in Dubuque, Iowa. If you have had the privilege of working or studying with nuns, you know that they are often amazing people. Sister Mary Kenneth certainly was. She was also a trailblazer who studied computer science before it was a thing and helped to create a CS department:
As the first person to receive a Ph.D. in computer science from the University of Wisconsin-Madison, she was a strong advocate for women entering the field of computer science. For nearly 20 years she served as chair of the newly-created computer science department at Clarke University and was among the first to recognize the future importance of computers in the sciences, libraries and business. Under her leadership at Clarke, a master's degree program in computer applications in education was included.
Claims that some individual was the "first person to receive a Ph.D. in computer science" have been relatively common over the years. The Department of Computer Science at Wisconsin has a page listing Ph.D.'s conferred, 1965-1970, which list Sister Mary Kenneth first, for a dissertation titled "Inductive Inference on Computer Generated Patterns". But that wasn't her only first; this ACM blog piece by Ralph London asserts that Keller is the first woman to receive a Ph.D. in CS anywhere in the US, and one of the first two US CS Ph.D.s overall.
This bit of history is only a small part of Keller's life in academia and computing. She earned a master's degree in math at DePaul University in the early 1950s. In 1958, she worked at the Dartmouth University Computer Center as part of an NSF workshop, during which time she participated in the development of the BASIC programming language. She wrote four books on computing and served as consultant for a group of business and government organizations that included the city of Dubuque and the state of Illinois.
Sister Mary Kenneth spent her career on the faculty of Clarke University, apparently chairing the Department of Computer Science until her retirement. The university's computer center is named the Keller Computer Center and Information Service in her honor, as is a scholarship for students of computing.
I'd been in Iowa twenty years before I first heard this story of an Iowan's role in the history of computing. Her story also adds to the history of women in computing and, for me, creates a whole new area in the history of computing: women religious. A pretty good find for cleaning up the house.
The passage quoted above come from an article by Jody Iler, "BVM to be Featured as One of the 'Heroines of Computing'", which ran some time last fall in The Witness, the newspaper of the Archdiocese of Dubuque. I found substantially the same text on a news archive page on the web site of the Sisters of Charity, BVM. There is, of course, a Wikipedia page for Sister Mary Kenneth that reports many of the same details of her life.
The photo above, which appears both in Iler's article and on the web site, shows Sister Mary Kenneth with Dr. Paul Laube, a flight surgeon from Dubuque who consulted with her on some computing matter. (Laube's obituary indicates he lived an interesting life as well.) In the article, the photo is credited to Clarke University.
Jim Weirich on dealing with failure in Ruby, via Avdi Grimm's blog:
(An aside, because I use exceptions to indicate failures, I almost always use the "fail" keyword rather than the "raise" keyword in Ruby. Fail and raise are synonyms so there is no difference except that "fail" more clearly communicates that the method has failed. The only time I use "raise" is when I am catching an exception and re-raising it, because here I'm *not* failing, but explicitly and purposefully raising an exception. This is a stylistic issue I follow, but I doubt many other people do).
Words matter: the right words, used at the right times. Weirich always cared about words, and it showed both in his code and in his teaching and writing.
The students in my agile class got to see my obsession with word choice and phrasing in class yesterday, when we worked through the story cards they had written for their project. I asked questions about many of their stories, trying to help them express what they intended as clearly as possible. Occasionally, I asked, "How will you write the test for this?" In their proposed test we found what they really meant and were able to rephrase the story.
Writing stories is hard, even for experienced programmers. My students are doing this for the first time, and they seemed to appreciate the need to spend time thinking about their stories and looking for ways to make them better. Of course, we've already discussed the importance of good names, and they've already experienced that way in which words matter in their own code.
Whenever I hear someone say that oral and verbal communication skills aren't all that important for becoming a good programmer, I try to help them see that they are, and why. Almost always, I find that they are not programmers and are just assuming that we techies spend all our time living inside mathematical computer languages. If they had ever written much software, they'd already know.
After spending a couple of days becoming familiar with pair programming and unit tests, for Day 4 we moved on to the next step: refactoring. I had the students study the "before" code base from Martin Fowler's book, Refactoring, to identify several ways they thought we could improve it. Then they worked in pairs to implement their ideas. The code itself is pretty simple -- a small part of the information system for a movie rental store -- and let the students focus on practice with tools, running tests, and keeping the code base "green".
We all know Fowler's canonical definition of refactoring:
Refactoring is the process of changing a software system in such a way that it does not alter the external behavior of the code yet improves its internal structure.
... but it's easy to forget that refactoring really is about design. Programmers with limited experience in Java or OOP can bring only so much to the conversation about improving an OO program written in Java. We can refactor confidently and well only if we have a target in mind, one we understand and can envision in our code. Further, creating a good software design requires taste, and taste generally comes from experience.
I noticed this lack of experience manifesting itself in the way my students tried to decompose the work of a refactoring into small, safe steps. When we struggle with decomposing a refactoring, we naturally struggle with choosing the next step to work on. Kent Beck calls this the challenge of succession. Ordering the steps of a refactoring is a more subtle challenge than many programmers realize at first.
This session reminded me why I like to teach design and refactoring in parallel: coming to appreciate new code smells and quickly learning how to refactor code into a better state. This way, programming skill grows along side the design skill.
On Day 5, we tried to put the skills from the three previous days all together, using an XP-style test-code-refactor-repeat cycle to implement a bit of code. Students worked on either the Checkout kata from Dave Thomas or a tic-tac-toe game based on a write-up by Gojko Adzic. No, these are not the most exciting programs to build, but as I told the class, this makes it possible for them to focus on the XP practices and habits of mind -- small steps, unit tests, and refactoring -- without having to work too hard to grok the domain.
My initial impression as the students worked was that the exercise wasn't going as well as I had hoped it would. The step size was too big, and the tests were too intrusive, and the refactoring was almost non-existent. Afterwards, though, I realized that programmers learning such foreign new habits must go through this phase. The best I can do is inject an occasional suggestion or question, hoping that it helps speed them along the curve.
This morning, I decided to have each student pair up with someone who had worked on the other task last time, flip a coin, and work on the one of the same two tasks. This way, each pair had someone working on the same problem again and someone working on a new problem. I instructed them to start from scratch -- new code, new thoughts -- and have the person new to the task write the first test.
The goal wass to create an asymmetry within each pair. Working on the same piece again would be valuable for the partner doing so, in the way playing finger exercises or etudes is valuable for a musician. At the same time, the other partner would see a new problem, bringing fresh eyes and thoughts to the exercise. This approach seems like a good one, as it varies the experience for both members of the pair. I know how important varying the environment can be for student learning, but I sometimes forget to do that often enough in class.
The results seemed so much better today. Students commented that they made better progress this time around, not because one of them had worked on the same problem last time, but because they were feeling more comfortable with the XP practices. One students something to the effect,
Last time, we were trying to work on the simplest or smallest piece of code we could write. This time, we were trying to work on the smallest piece of functionality we could add to the program.
That's a solid insight from an undergrad, even one with a couple of years programming experience.
I also liked the conversation I was hearing among the pairs. They asked each other, "Should we do this feature next, or this other?" and said, "I'm not sure how we can test this." -- and then talked it over before proceeding. One pair had a wider disparity in OO experience, so the more experienced programmer was thinking out loud as he drove, taking into account comments from his partner as he coded.
This is a good sign. I'm under no illusion that they have all suddenly mastered ordering features, writing unit tests, or refactoring. We'll hit bumps over the next three weeks. But they all seem to be pretty comfortable with working together and collaborating on code. That's an essential skill on an agile team.
Next up: the Planning Game for a project that we'll work on for the rest of the class. They chose their own system to build, a cool little Android game app. That will change the dynamic a bit for customer collaboration and story writing, but I think that the increased desire to see a finished product will increase their motivation to master the skills and practice. My job as part-time customer, part-time coach will require extra vigilance to keep them on track.
Days 2 and 3 of my Agile Software Development May term course are now in the books. This year, I decided to move as quickly as we could in the lab. Yesterday, the students did their first pair-programming session, working for a little over an hour on one of the industry standard exercises, Conway's Game of Life. Today, they did their first pair programming with unit tests, using Bill Wake's Test-First Challenge to implement the beginnings of a simple data model for spreadsheets.
I always enjoy watching students write code and interacting with them while they do it. The thing that jumped out to me yesterday was just how much code some students write before they ever think about compiling it, let alone testing it. Another was how some students manage to get through a year of programming-heavy CS courses without mastering their basic tools: text editor, compiler, and language. It's hard to work confidently when your tools feel uncomfortable in your hands.
There's not much I can do to help students develop greater facility with their tools than give them lots of practice, and we will do that. However, writing too much code before testing even its syntactic correctness is a matter of mindset and habit. So I opened today's session with a brief discussion, and then showed them what I meant in the form of a short bit of code I wrote yesterday while watching them. Then I turned them loose with Wake's spreadsheet tests and encouragement to help each other write simple code, compile frequently even with short snippets, and run the tests as often as their code compiles.
Today, we had an odd number of students in class, something that's likely to be our standard condition this term, so paired with one of the students on a spreadsheet. He wanted to work in Haskell, and I was game. I refreshed my Haskell memories a bit and even contributed some helpful bits of code, in addition to meta-contributions on XP style.
The student is relatively new to the language, so he's still developing the Haskell in his in his mind. There were times we struggled because we were thinking of the problem in a stateful way. As you surely know, that's not the best way to work in Haskell. Our solutions were not always elegant, but we did our best to get in the rhythm of writing tests, writing code, and running.
As the period was coming to an end, our code had just passed a test that had been challenging us. Almost simultaneously, a student in another thrust his arms in the air as his pair's code passed a challenging test, too, much deeper in the suite. We all decided to declare victory and move on. We'll all get better with practice.
Next up: refactoring, and tools to support it and automated testing.
May term started today, so my agile course is off the ground. We will meet for 130 minutes every morning through June 6, excepting only Memorial Day. That's a lot of time spent together in a short period of time.
As I told the students today, each class is almost a week's worth of class in a regular semester. This means committing a fair amount of time out of class every day, on the order of 5-7 hours. There isn't a lot of time for our brains to percolate on the course content. We'll be moving steadily for four weeks.
This makes May term unsuitable, in my mind at least, for a number of courses. I would never teach CS 1 in May term. Students are brand new to the discipline, to programming, and usually to their first programming language. They need time for the brains to percolate. I don't think I'd want to teach upper-division CS courses in May term if they have a lot of content, either. Our brains don't always absorb a lot of information quickly in a short amount of time, so letting it sink in more slowly, helped by practice and repetition, seems best.
My agile course is, on the other hand, almost custom made for a compressed semester. There isn't a lot of essential "content". The idea is straightforward. I don't expect students to memorize lists of practices, or the rules of tools. I expect them to do the practices. Doing them daily, in extended chunks of time, with immediate feedback, is much better than taking a day off between practice sessions.
Our goal is, in part, to learn new habits and then reflect on how well they fit, on where they might help us most and where they might get in the way. We'll have better success learning new habits in the compressed term than we would with breaks. And, as much as I want students to work daily during a fifteen-week semester to build habits, it usually just doesn't happen. Even when the students buy in and intend to work that way, life's other demands get in the way. Failing with good intentions is still failing, and sometimes feels worse than failing without them.
So we begin. Tomorrow we start working on our first practice, a new way of working with skills to be learned through repetition every day the rest of the semester. Wish us luck.
Spring semester ends today. May term begins Monday. I haven't taught during the summer since 2010, when I offered a course on agile software development. I'm reprising that course this month, with nine hardy souls signed on for the mission. That means no break for now, just a new start. I like those.
I'm sure I could blog for hours on the thoughts running through my head for the course. They go beyond the readings we did last time and the project we built, though all that is in the mix, too.
For now, though, three passages that made the highlights of my recent reading. All fit nicely with the theme of college days and transition.
First, this reminder from John Graham, a "self-made merchant" circa 1900, in a letter to his son at college.
Adam invented all the different ways in which a young man can make a fool of himself, and the college yell at the end of them is just a frill that doesn't change essentials.
College is a place all its own, but it's just a place. In many ways, it's just the place where young people spend a few years while they are young.
Next, a writer tells a story of studying with Annie Dillard in college. During their last session together, she told the class:
If I've done my job, you won't be happy with anything you write for the next 10 years. It's not because you won't be writing well, but because I've raised your standards for yourself.
Whatever we "content" teach our students, raising their standards and goals is sometimes the most important thing we do. "Don't compare yourselves to each other", she says. Compare yourselves to the best writers. "Shoot there." This advice works just as well for our students, whether they are becoming software developers or computer scientists. (Most of our students end up being a little bit of both.)
It's better to aim at the standard set by Ward Cunningham or Alan Kay than at the best we can imagine ourselves doing right now.
Now that I think about it, this last one has nothing to do with college or transitions. But it made me laugh, and after a long academic year, with no break imminent, a good laugh is worth something.
What do you call a rigorous demonstration that a statement is true?
- If "proof", then you're a mathematician.
- If "experiment", then you're a physicist.
- If you have no word for this concept, then you're an economist.
This is the first of several items in The Mathematical Dialect Quiz at Math with Bad Drawings. It adds a couple of new twists to the tongue-in-cheek differences among mathematicians, computer scientists, and engineers. With bad drawings.
Back to work.
Several people have recommended Pat Brisbin's Thinking in Types for programmers with experience in dynamically-typed languages who are looking to grok Haskell-style typing. He wrote it after helping one of his colleagues of mine was get unstuck with a program that "seemed conceptually simple but resulted in a type error" in Haskell when implemented in a way similar to a solution in a language such as Python or Ruby.
This topic is of current interest to me at a somewhat higher level. Few of our undergrads have a chance to program in Haskell as a part of their coursework, though a good number of them learn Scala while working at a local financial tech company. However, about two-thirds of undergrads now start with a one or two semesters of Python, and types are something of a mystery to them. This affects their learning of Java and colors how they think about types if they take my course on programming languages.
So I read this paper. I have two comments.
First, let me say that I agree with my friends and colleagues who are recommending this paper. It is a clear, concise, and well-written description of how to use Haskell's types to think about a problem. It uses examples that are concrete enough that even our undergrads could implement with a little help. I may use this as a reading in my languages course next spring.
Second, I think think this paper does more than simply teach people about types in a Haskell-like language. It also gives a great example of how thinking about types can help programmers create better designs for their programs, even if they are working in an object-oriented language! Further, it hits right at the heart of the problem we face these days, with students who are used to working in scripting languages that provide high-level but very generic data structures.
The problem that Brisbin addresses happens after he helps his buddy create type classes and two instance classes, and they reach this code:
renderAll [ball, playerOne, playerTwo]
renderAll takes a list of values that are Render-able. Unfortunately, in this case, the arguments come from two different classes... and Haskell does not allow heterogeneous lists. We could try to work around this feature of Haskell and "make it fit", but as Brisbin points out, doing so would cause you to lose the advantages of using Haskell in the first place. The compiler wouldn't be able to find errors in the code.
The Haskell way to solve the problem is to replace the generic list of stuff we pass to renderAll with a new type. With a new Game type that composes a ball with two players, we are able to achieve several advantages at once:
It's this last win that jumped off the page for me. Creating a Game class would give us a better object-oriented design in his colleague's native language, too!
Students who become accustomed to programming in languages like Python and Ruby often become accustomed to using untyped lists, arrays, hashes, and tuples as their go-to collections. They are oh, so, handy, often the quickest route to a program that works on the small examples at hand. But those very handy data structures promote sloppy design, or at least enable it; they make it easy not to see very basic objects living in the code.
Who needs a Game class when a Python list or Ruby array works out of the box? I'll tell you: you do, as soon as you try to almost anything else in your program. Otherwise, you begin working around the generality of the list or array, writing code to handle special cases really aren't special cases at all. They are simply unbundled objects running wild in the program.
Good design is good design. Most of the features of a good design transcend any particular programming style or language.
So: This paper is a great read! You can use it to learn better how to think like a Haskell programmer. And you can use it to learn even if thinking like a Haskell programmer is not your goal. I'm going to use it, or something like it, to help my students become better OO programmers.
Recently, a gentleman named Seth Roberts passed away. I didn't know Roberts and was not familiar with his work. However, several people I respect commented on his life and career, so I took a look at one colleague's reminiscence. Roberts was an interesting fellow who didn't do things the usual way for a research academic. This passage stood out:
Seth's academic career was unusual. He shot through college and graduate school to a tenure-track job at a top university, then continued to do publication-quality research for several years until receiving tenure. At that point he was not a superstar but I think he was still considered a respected member of the mainstream academic community. But during the years that followed, Seth lost interest in that thread of research (you can see this by looking at the dates of most of his highly-cited papers). He told me once that his shift was motivated by teaching introductory undergraduate psychology: the students, he said, were interested in things that would affect their lives, and, compared to that, the kind of research that leads to a productive academic career did not seem so appealing.
That last sentence explains, I think, why so many computer science faculty at schools that are not research-intensive end up falling away from traditional research and publishing. When you come into contact with a lot of undergrads, you may well find yourself caring more deeply about things that will affect their lives in a more direct way. Pushing deeper down a narrow theoretical path, or developing a novel framework for file system management that most people will never use, may not seem like the best way to use your time.
My interests have certainly shifted over the years. I found myself interested in software development, in particular tools and practices that students can use to make software more reliably and teaching practices that would students learn more effectively. Fortunately, I've always loved programming qua programming, and this has allowed me to teach different programming styles with an eye on how learning them will help my students become better programmers. Heck, I was even able to stick with it long enough that functional programming became popular in industry! I've also been lucky that my interest in languages and compilers has been of interest to students and employers over the last few years.
In any event, I can certainly understand how Roberts diverged from the ordained path and turned his interest to other things. One challenge for leaving the ordained path is to retain the mindset of a scientist, seeking out opportunities to evaluate ideas and to disseminate the ones that appear to hold up. You don't need to publish in the best journals to disseminate good ideas widely. That may not even be the best route.
Another challenge is to find a community of like-minded people in which to work. An open, inquisitive community is a place to find new ideas, a place to try ideas out before investing too much in a doomed one, and a place to find the colleagues most of us need to stay sane while exploring what interests. The software and CS worlds have helped create the technology that makes it possible to grow such communities in new ways, and our own technology now supports some amazing communities of software and CS people. It is a good time to be an academic or developer.
I've enjoyed reading about Roberts' career and learning about what seems to have been one of the academia's unique individuals. And I certainly understand how teaching introductory undergrads might motivate a different worldview for an academic. It's good to be reminded that it's okay to care about the things that will affect the lives of our students now rather than later.