Last updated: Sun, 3 May 2015 12:57:45 -0400
This page explains some course philosophy.
The first thing you need to know: this course is not about programming in Racket (or Java, or any other specific programming language).
This course is about program design.
As David Parnas cautioned:
"Unless we teach people how to design, the languages matter very little."
as quoted in The Mythical Man-Month [MythicalManMonth]
cannot handle anything beyond a few narrow test cases;
are difficult for others to read and understand;
are poorly designed and thus difficult to extend and maintain;
have behavior that is not well-understood and cannot easily be explained, even by their authors.
Anyone who has ever been frustrated while working with someone else’s code understands this dilemma well.
Unfortunately, this dilemma is extremely costly in practice, for startups and established companies alike, because it leads to the accumulation of technical debt.
Thus, despite the hype you might hear about interviews focusing on cute, algorithmic questions, what quality software companies are ultimately looking for are programmers who can write clear, readable, and maintainable programs.
To address this dilemma, we teach "program design" in this course. In other words, we teach you to how to think and organize your program before you start writing any code.
create programs that are well-tested and correct;
write clear and readable code;
write well-structured programs that are changeable and maintainable;
can effectively communicate their ideas and their code to others.
are never stalled in front of an empty editor because they always know where to start with their program design;
always have a next step and thus spend less time being stuck when debugging;
automatically have a means of explaining their programs to others.
This course begins with a basic program design recipe. Then, throughout the semester, we extend and refine the recipe to accomodate various contexts and styles, and hone your program design skills through deliberate practice.
Given that we don’t know which future programming languages will be popular, or what future problems you’ll be solving, this course strives to teach program design in a language-agnostic manner. We try to avoid being constrained by language-specific ideas and constructs as much as possible, in hopes that the programming skills you learn are applicable regardless of whatever future programming language you happen to be using.
Another danger of focusing on a specific language is that it’s easy to overlook what the language cannot do. For example, regarding the well-known C++/Java/OO Design Patterns Peter Norvig famously observed that 16 out of 23 patterns are not even needed in other languages like Lisp or Dylan.
Of course, to learn program design, we must write actual programs. Thus, we must choose concrete tools to program with.
We use Racket in this course for several reasons:
This enables writing realistic, interactive programs from scratch in a short amount of time, yet still forces students to focus on and understand the design of their program.
Contrast this with frameworks that require many lines of boilerplate code just to accomplish simple tasks; or the all-too-common practice of programming via "plugging in magic incantations" ([CodersAtWork], Chapter 15), where programmers often don’t fully understand what their program does.
It is a "multi-paradigm" language, so we are not restricted to a specific programming style.
Alternatively, with other languages like Java, where "everything is an object", all programs must be squeezed into a particular paradigm. For example, these days it’s recommended to program in a "value-oriented" (i.e., functional) style, even in OO-based languages like Java ([EffectiveJava], Ch 4, Item 13). However, rather than study the hyperspecialized functional-programming-in-Java, we can learn much more about program design by studying concepts, e.g., programming via functions, in isolation.
A multi-paradigm language also enables smooth transitions between different programming styles, e.g., from a teaching subset to the full language; or from a functional, to a functional-object-oriented, to an imperative-object-oriented style.
It is untyped. At a high level, The Program Design Recipe is about designing datatypes and following their shape when writing code. Thus some formal checking of data definitions would undoubtedly be a useful. However, such checking often comes with additional, language-specific complexities such as burdensome annotations or confusing error messages. Having to possibly wrangle a separate system to "make it accept" your program is distracting and orthogonal to the course concepts.
In addition, arbitrarily restricting our programs to a typeful environment neglects the fact that a majority of industrial programming occurs with scripting languages that don’t have types.
Racket does enable programmers to migrate their programs to leverage static or dynamic checks, but to remain consistent with our language-agnostic goal, we currently do not use these features in our course.
Finally, Racket is equally unknown to all of you, which puts everyone on a fair and equal starting point, regardless of prior experiences.