This post originated from an RSS feed registered with Ruby Buzz
by Anders Bengtsson.
Original Post: What do we want the software to do?
Feed Title: A View From Above: Ruby
Feed URL: http://www.ghostganz.com/blog/xml/rss20/category/Ruby/feed.xml
Feed Description: Anders Bengtsson on programming and other things
About intentions, two stages in the history of programming and the corresponding stages in the individual programmer’s skills.
Stage A – How do I get it to do what I want?
In the beginning of a programmer’s learning there is a struggle to simply get the machine to do something, anything. Much like when you try to communicate in a spoken language you’ve just started learning, you can’t express some concepts, invent awkward statements instead of words you don’t know, and get things plain wrong.
You have a pretty clear idea what you want to say, but you struggle to communicate it.
“I need a lift in your el truck-o to the next town-o!”—Brad Pitt, The Mexican
In the early programming languages, there wasn’t much more to it than this. The language was very limited and even though it could theoretically express everything, you couldn’t communicate it. The higher level concepts and ideas was not expressed in the language, but in the documentation or, more likely, remained in the programmer’s head. Even though you learn the language to perfection, there’s little difference in what you can express.
Stage B – What do I want?
“I want a helmet. A cheese helmet. A helmet full of cheese. You just pop it on your head and eat all day.”—Denis Leary
Once you master a language, the focus shifts away from the language itself. If you know what you want to say, you can often express it directly, less limited by the language. Ever higher levels of abstraction and expressiveness in languages makes this increasingly simple. (Learning the language in the first place isn’t necessarily any simpler). Constructs like classes allow you to express very abstract concepts and ideas in just a few statements.
The original purpose of a language, communication, can now be achieved. The problem is now to find out what you want, your intention, so that you can express it.
Understanding and Documentation
While most of what programmers do these days is firmly in “B”, there are a lot of ideas with roots in “A” that still linger in our minds. Our ideas about how and when to document our code often have their origins in a time where the languages couldn’t serve the purpose of communication. There was no option but to annotate everything with natural language if you wanted to communicate. When we left machine code for procedural languages this need was reduced a lot (to merely procedure-level comments), and object-oriented languages reduced even further (maybe to just class-level comments). This is all under the assumption that the language’s abilities are actually used.
The intensive documentation required in “A” also sometimes created the belief that the documentation should be extensive enough for someone, with no prior knowledge of the system, to understand it directly.
But just like in any natural language, the individual statements don’t make sense unless you know their context. In a program the context can be very big, ranging from knowledge about the problem domain to the technical solutions preferred in the programming team and can not be expected to be learned from low-level documentation within the code.
The purpose of the code is communication with the other programmers working on the system (and with the compiler). Like any natural language, you use people’s shared context to make the communication more efficient, at the expense of the outsider’s understanding of it.
Getting to B
“I CAN WRITE COBOL IN ANY LANGUAGE”—Unknown
While a beginner may naturally be in “A”, there is no guarantee that experienced programmers will be in “B”. While it is a requirement to know the language well to do “B”-style programming, it isn’t enough. Just using a modern language doesn’t make our code more communicative. We can still write long methods with three-letter variable names in Java, as we did in C. We can still organize and name our Ruby classes entirely without connection to our problem domain.
We have to strive to keep accidental complexity and technicalities to creep into how we write and organize our code. Using good naming on everything from variables up to modules, we have to keep the code close to the intentions that originate it. When the intentions change, we have to use Refactoring to make the code reflect the new conditions. If we don’t use these new opportunities, we’re also stuck with the needs for heavy documentation and other practices of “A”. Even if we don’t write code for the “outsider” audience, we still need to communicate as clearly as possible.
“Getting the words right”
The big challenge is to know what your intentions really are. Unless they are truly clear in our minds, they can’t be clear in the code. This is where design tools like Test-Driven Development (TDD) is a big help. By forcing us to reason and express what we really want our code to do, it makes it easier to write code that also communicates this intention.
The more recent Behavior-Driven Development (BDD) concept emphasizes the TDD idea that the tests themselves should be used for communication. BDD tools typically encourage you to state your intentions in natural language, together with code that verifies each intention (paradoxically similar to the early documentation practices). Unlike other forms of documentation, it is harder for this one to become out-of-date and misleading.
The TDD/BDD ideas seems like a parallel, but orthogonal, development to that of the modern languages. They are adding more ways of communication, but at the same time as helping us use the existing ways better.
Thus
There are a lot of opportunities in “B”, as long as you actually take advantage of them. For novices, there is the need to master their programming language, to gain the ability to express themselves in it. For experienced programmers, it’s important to really use the abilities to communicate that modern languages provide, supported by the available tools.