TITLE: The Trade-off Between Process and Tools AUTHOR: Eugene Wallingford DATE: August 26, 2009 1:19 PM DESC: ----- BODY: Mark Guzdial blogged this morning about a bug slipped through into the latest release of JES, the Jython IDE that his group has created to support courses and workshops in media computation. The bug was the result of a simple variable renaming in which n-1 of the uses was changed. (That nth always comes back to haunt us.) Mark uses this bug as an opportunity to discuss some bigger issues involving process, language, and the nature of CS1. He is taking some heat from a couple of pro-Python commenters, but I'm glad he wrote the article. People too rarely share mistakes when they are made, and besides Mark offers some interesting ideas both in his post and in his responses to comments. Should we use a different kind of language when we program for others than when we program for ourselves? A compiler would have found this simple error at the time JES was built and saved everyone the grief of a new release. But so would running the test suite that the JES team has built. The difference is that developers have a choice of running the test suite or not, whether they use a compiled language or an interpreted one, but they have to compile their program when they use a compiled language. People make mistakes. I am certainly not in a position to look down on the poor developer who opted not to run the unit tests after making what seemed like a trivial change. I have made similar mistakes before, and I'm sure I'll make another like it soon. And at least one thing is true about teaching university courses: students will find my mistakes! I like it when a compiler catches errors like this for me, but... Still, I'm uneasy to give up the freedom that a language like Smalltalk, Scheme, or Ruby gives me when I am writing code. Even when the value of Mark's f() rises. What is someone like me to do? The compiler is a tool that helps me find a certain kind of error. But there are other tools that help me find this and other kinds of error. The unit tests are one. A refactoring browser is another. If the JES developer had had at his or her disposal a refactoring browser for Python, it would have at least been able to point out possible effects of renaming the variable behind this bug. Dynamic languages pose a particular challenge for building really useful static analysis tools, but we can still build tools to help. But the developer might not use the refactoring browser. The change is so simple, a quick romp in emacs or vi is all we need, right? The compiler is a build tool; the programmer has to run it to create the executable. One approach that developers using dynamic languages can take is to use a build system that always runs the test suite. Another is to tool the version control system to run the tests before accepting the code at check-in. These tools more closely fulfill the role played by the compiler. In response to another comment on his entry, Mark mentions a trade-off between process and language, a lá the familiar space-time trade-off among algorithms and data structures. This, I think, is the most interesting implication of his post. But the language in which we write code is just one tool that we use in building software. The compiler is another. So are editors, browsers, version control systems, build systems, and testing frameworks. The trade-off is between processes and tools. This trade-off is one that seems to fly under most people's radar. The authors of the Agile Manifesto wrestle with the trade-off between caring for "individuals and interactions" and caring for "processes and tools". They come down on the side of individuals and interactions. But as I wrote a few weeks ago, valuing people over tools makes having the right tools even more important. I should probably have said "the right tools and process", because the process by which one works is just as important a part of the infrastructure that any programmer or creator needs. The question then becomes: In supporting individuals and interactions, how do we find the right balance between tools and process? People characterize the different kinds of process available to programmers in a number of ways: Some people assume that the righthand side of these choices require more discipline than the left, because the lefthand-style processes provide more rules to follow. That's not right. Discipline is, at best, orthogonal to this distinction. I think that the agile, lightweight, and low-ceremony approaches usually require more discipline, not less. In XP, you have to code in pairs, even if you think you don't need to. You have to run the tests. You have to refactor frequently and, on occasion, vigorously. You have to integrate code frequently. You have to take what you learn from all the practices and feed that back into the code. Easy? Not at all. Undisciplined? Not if you are practicing what you preach. This sort of disciplined approach only works when the practices are at the level of granularity where they can become habit, part of one's muscle memory. It also works well only when supported by tools that make the process comfortable, almost disappear from conscious thought. Good tools shift as much of the burden of details and administrivia off of the programmer's mind and onto the tools that we use to write, build, test, share, and deliver our code. I understand why many people want to use a compiler to support their process. But I still prefer to use languages that give me other kinds of freedom -- along with other tools that support my creative process. -----