About

This is the archive page for Head of the Kyu. Click to go to the frontpage of this site.

Last Comments

Ben (Breakthroughs and…): Here is a strange observa…
Carl Manaster (A handy heuristic…): Note on the comment syste…
Carl Manaster (A handy heuristic…): Let’s try that again… www…
Carl Manaster (A handy heuristic…): I once wrote a little vis…
Nico (A handy heuristic…): C# can have multiple clas…
Nat (A handy heuristic…): “an XP project is suppose…
Jim Bullock (A handy heuristic…): Are the class (or whateve…
Ä¢irts Kalniņš (Head of the Kyu): good to see you back.

Calendar

« May 2008
S M T W T F S
        1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31

Archives

Next Archive Previous Archive

01 Jan - 31 Jan 2007
01 Oct - 31 Oct 2006
01 Feb - 28 Feb 2006
01 Jan - 31 Jan 2006
01 Nov - 30 Nov 2005
01 Sep - 30 Sep 2005
01 Aug - 31 Aug 2005
01 Jul - 31 Jul 2005
01 Jun - 30 Jun 2005
01 May - 31 May 2005
01 Mar - 31 Mar 2005
01 Feb - 28 Feb 2005
01 Jan - 31 Jan 2005
01 Dec - 31 Dec 2004
01 Nov - 30 Nov 2004
01 Oct - 31 Oct 2004
01 Sep - 30 Sep 2004
01 Aug - 31 Aug 2004
01 Jul - 31 Jul 2004
01 Jun - 30 Jun 2004
01 May - 31 May 2004
01 Apr - 30 Apr 2004
01 Mar - 31 Mar 2004
01 Feb - 28 Feb 2004
01 Jan - 31 Jan 2004
01 Dec - 31 Dec 2003
01 Nov - 30 Nov 2003
01 Oct - 31 Oct 2003
01 Sep - 30 Sep 2003
01 Aug - 31 Aug 2003
01 Jul - 31 Jul 2003
01 Jun - 30 Jun 2003
01 May - 31 May 2003
01 Apr - 30 Apr 2003
01 Mar - 31 Mar 2003
01 Feb - 28 Feb 2003
01 Jan - 31 Jan 2003

Miscellany

Powered by Pivot - 1.40.0: 'Dreadwind' 
XML: RSS Feed 
XML: Atom Feed 

31 July 03 - 16:29The genius of (programming) languages

I've been thinking about the linguistic and expressive aspects of software development.

There is a persistent and dangerous aberration in the software industry, which consists of arguing that programming languages should resemble natural languages. Nobody ever demonstrated that this was feasible or could yield a measurable benefit - and since COBOL, the attempts have been going on for over half a century.

This does not mean that we can draw no useful parallels between programming languages and the ones we use in conversation. Idiomatic language is one common aspect.

The term "idiom" has its subtleties. An idiom, in natural language, is a ready-made expression with a specific meaning that must be learned, and can't necessarily be deduced from the terms of the expression. This meaning transposes easily to programming languages and to software in general.

If you are an old hand at Java, you're probably familiar with a number of Java idioms, such as implementing an interface to gain access to its constants, or nesting an exception to strip it of its "checked" taint. One of Ruby's idioms is the exclamation mark to distinguish a method with side-effects. (The question mark used in Ruby for boolean queries is, perhaps, less idiomatic since its meaning derives from the English grammar it imitates.)

Alan Cooper convincingly argues that the way we interact with software is idiomatic, rather than metaphoric as commonly described. Click-and-drag is an idiom of graphical user interfaces. To quote Cooper, "the key observation about idioms is that although they must be learned, good ones only need to be learned once."

Let's move back to natural languages. The term "idiom" also has a second meaning, which is the large-scale aggregate of the more specific meaning; the idiomatic use of a language is characterized by the proficient use of the language's idoms. Thus, "idiom" also refers to the skillful and appropriate use of a language. There is only one English language, but there can be many skillful and appropriate ways to use the English language; thus, we can also speak of a given author's idiom.

A wonderful phrase (also idiomatic) for this second sense is "the genius of (a) language".

With respect to software and programming languages, is there anything akin to this sense of "idiom" ? I believe there is - in more than one way. Cooper argues - and once more I agree - that the original success of the Macintosh wasn't due to the "desktop metaphor"; but he goes on to attribute this success to its being "the first computer that defined a tightly restricted vocabulary for communicating with users based on a very small set of mouse actions". This isn't very convincing. Rather, I suspect that the Mac wowed users because of its "genius of language" - because it spoke its own idiom, beautifully.

Yes, and early versions of Windows were the opposite of idiomatic - they looked as gauche a foreigner might sound who relies too heavily on your language's idioms in an attempt to pass for a native. Eventually, Microsoft got the hang of its own idioms, and started contributing innovations such as tooltips or toolbar "butcons" (speed buttons).

Of course, it is important to remember that not all idioms are equally agreeable. There is a thin line between idiom and cliché. Much as I like Cooper's ideas on interaction design, I find it ironic that he had a hand in the creation and popularization of Visual Basic, which did much to spread some of the worst known idioms in developing user interfaces: pervasive wizards, visual layout editors which spew huge window initialization methods, etc.

I have saved for last one more example of "idiom" in the second sense, which helped me feel a lot better about this excerpt from a recent article by Bob Martin:

But now, as we all gradually adopt Test Driven Development, are we going to find [type] safety redundant ?


This initially disturbed me, because it smacked of "TDD as silver bullet". But over the last couple days, I've started to think of TDD as a programming idiom. Or if you will, "just" a programming idiom; but most certainly a damn good one, knowledge of which is likely to be as critical to a software developer's professional credibility as, say, her mastery of the object-oriented idiom.

One exciting thing about recent idioms like TDD (or, given any sense of perspective, object-oriented programming itself, for all that it is 20-30 years old) is that there is still ample room to create Great Works using them. (But do check your sense of perspective.) One notion I'm all fired up about, at least this week, is blending TDD and Cooper's ideas on interaction design, to undo some of the damage done by the unsavory UI idioms we have, unfortunately, become inured to.

One inspiring quote to close this ramble on "the genius of languages", including software langages:

Men of genius are far more abundant than is supposed. In fact, to appreciate thoroughly the work of what we call genius, is to possess all the genius by which the work was produced. -- Edgar Allan Poe

- Software Development - three comments / No trackbacks - §

29 July 03 - 22:37Google hiring Agile ?

Hmm, interesting. At the time of this writing, searching Google with the keywords "pair programming" will bring up one of these "Sponsored Link" boxes, right of the results list, which says:

Work at Google
Google is hiring expert computer
scientists and software developers!

www.google.com/jobs
Interest:


I haven't tried all other 11 practices (or however many are left once you take out pair programming, and this isn't necessarily linear), but it doesn't look as if anything other than "pair programming" brings up this ad. Just "programming" isn't enough. Hear that: if you want to work at Google, you gotta pair. ;)

- Extreme Programming - one comment / No trackbacks - §

29 July 03 - 17:54Time and Choice

"We never have time to do it right, but we always have time to do it over."

I have to wonder whether we are not simply led up the garden path by phrases like "having the time" or "taking the time". Consider the next hour, starting right now. At this instant you have it. In one hour it will have been taken from you. Ditto days, weeks, months, years.

Possibly, all issues of time are in fact issues of choice. I choose to spend the next hour on X or Y. I may choose based on several factors : whether I expect X or Y to best contribute to my current goals, how I feel about X or Y, etc.

It is tempting to consider that "I have no time for X" always means "I prefer to do Y rather than X in the relevant time period", suggesting that the person in question does not in fact expect that X is more worthwhile than Y, or for some reasons feels bad about doing X. Even when they say they would do X if they had the time.

- The Universe And Everything - three comments / No trackbacks - §

28 July 03 - 18:06How to write a perfect program

You want to know how to paint a perfect painting ? It's easy. Make yourself perfect and then just paint naturally. -- Robert Pirsig, in Zen and...


What is it that finds bugs in our programs ? Here are a few hints. Not unit tests - not even when we write them before the code. Not test plans - not even when these are carefully crafted and executed. Not tools such as Boundschecker or Purify - even when they are handled skillfully. Not code coverage. Not pair programming. Not knowledge of bug patterns.

We find bugs in programs, and we find bugs best when we are concerned about the quality of the programs we test. Ultimately, what finds bugs in our programs is our concern with where the programs could be improved, how they could be made more valuable to those who use them.

What is it that contributes to quality software in the first place ? Here are a few hints. Not design patterns - even when we have experience with them and we're not a little boy with a hammer. Not formal methods - even when we're writing programs that seem perfectly suited to mathematical formalisms, which can't be very often (what's the formal proof-of-correctness of a user interface ?). Not Extreme Programming - even when we use all of it rather than just that bit about not writing any documentation. Not daily builds. Not version control.

We write quality software, and only when we set out to do just that, even if more often than not we fail in the attempt. The particular techniques tend to sort themselves out, at least for people who share a deep, abiding concern for putting out software that is of value to the people who commission and use it.

I cringe whenever I hear one of my colleagues say something like, "Nobody writes bug-free programs anyway." It's a self-fulfilling prophecy.

- Software Development - two comments / No trackbacks - §

24 July 03 - 13:46Project & Product Portfolio

I occasionally come across the phrase "project portfolio management", or sometimes just "project portfolio", but so far it has failed to convey much concrete meaning to me. Perhaps because it is often found in the company of ethereal buzzwords like "enterprise architecture", or perhaps because it is difficult enough to survive single projects, the agile crowd seems to be likewise unconcerned with the topic.

I realized today, though, that I know of at least one perennial issue faced by software developers which is typically a portfolio management issue: the dreaded question of "redesign our product or rewrite it from scratch".

One product company I'm consulting with has recently been faced with that choice, and after an agonizing decision process has finally split its R&D team into two entities. One is tasked with delivering a brand-new product line. The other will, in essence, try to keep the current product line on artificial life support - doing their level best to avoid its complete collapse under a massive infection of bugs and technical debt - for as long as it takes to have the new products out the door and generating revenue. Massive redesign and refactoring would have been needed to bring the product back into a decent state of maintainability, hence the decision.

The "refactor vs rewrite" question is a symptom of poor or nonexistent portfolio management. Every developer - and I suppose every development manager - is, after all, familiar with the typical lifecycle of a software product: an initial release provides the basic functionality, in the best cases supported by a solid design and with few defects. Successive releases add features (and some defects), often not directly related to the product's core objectives but serving to broaden its market appeal. As the design deteriorates under the conflicting tensions imposed by unrelated feature areas, the product becomes harder and harder to modify without generating large numbers of defects. Eventually, this "software entropy" reaches a critical mass, where each defect fixed engenders one new defect or more as a side-effect.

This lifecycle can be made longer, using agile practices such as pervasive testing and refactoring, frequent builds; a design that, over time, emphasizes modular decomposition and reuse; and collective ownership and responsibility for quality. But it seems likely that any single product will eventually reach that terminal stage.

If so, it is extremely unwise to wait that long before planning a replacement effort. By then, the cumulated costs of "life support" for the old product and the intense creative demands of the new effort will make the rewrite decision quite expensive.

I can think of at least two strategies that would probably reduce overall cost and increase overall revenue over longer periods. In the first, as soon as the initial product generates sufficient revenue to do so, set aside a small portion of the effort spent on new features to work on a new product instead, targeting the emerging technologies or feature areas most in demand from customers of the main product line. By the time the main product runs out of wind, a new offering will be ready to take up the slack. A second strategy is piecemeal replacement - break up the product into portions which can evolve independently of each other. When the main focus is on improving, e.g., the client product, start a smaller project to replace the server product using new technology, compatible with the current client code. When the client products start to get old, unveil the new server and start work on the next generation client, and so on.

- Software Development - No comments / No trackbacks - §

23 July 03 - 14:09Debugging doesn't scale

Occasionally, I make mistakes while coding. I intend my code to do one thing, but what I write says something different.

There are only two ways that I, on my own, can become aware of that. One way is by executing part of the program's features - the parts which my mistake affects. The other way is by examining the code - rereading it - and spotting my mistakes. The first is by far the more likely to yield results, if I'm working on my own: a writer (of code or of prose) is usually oblivious to his own mistakes.

Previously, my development method was to write a bunch of code, at the same time running my program from time to time to check on the feature that I was writing. As a result, I was usually able to quickly discover those of my mistakes which created problems in the feature I was developing.

This worked fairly well as long I worked only on very small, very simple programs that did only one thing. The first "serious" programming I did was on early Macintosh models - Mac Plus and Mac II's - and I started by writing "INITs", system extensions which modified operating system services in small but useful ways. My first effort implemented an "auto-save" feature for application programs: it automatically sent an Command-S keystroke to the running program every few minutes.

It broke down as soon as I started tackling larger programs.

Whenever my mistakes resulted in problems affecting other parts of the program - different features, special cases not part of the task immediately at hand - it would take longer for me to become aware of the mistakes. In the meantime, I would have written lots of code related to many different features.

As a result, when a mistake was brought to light - by me, by a teammate, by a tester, or worse, by a user - I had to look for it in the entire program. I had to use a powerful tool to locate most of my mistakes: a debugger.

The debugger allowed me to track down my mistakes, by interacting with the program as it was running. The debugger let me see how the program really behaved (as opposed to what I'd thought I'd specified in the source code). As long as I could reproduce the problem, all I had to do what set a breakpoint close to where the problem occurred. Sometimes this directly told me which parts of my code contained a mistake. Other times I had to work back if necessary to where the problem had been introduced, and then figure out which parts of that code were in error.

Eventually, this broke down, too. As the programs I wrote grew larger, so did the amount of work to reproduce situations under which problems occured; so did the required amount of "backtracking" to original causes; so did, massively, the amount of ancillary work required to use the debugger effectively. Not to mention all the problems that couldn't be reliably reproduced, but only occurred randomly - or worse, only occurred when running outside of the debugger. For a while there, I was a debugging wizard - and I still couldn't produce bug-free programs.

I work differently nowadays.

Whenever I write code for a feature, at a fine grained level, I also write a test. I don't mean a documented test plan, which would entail firing up the program to check on this or that feature; but a fully automated test, written in Java, or in C#, or in whatever language I'm using on the project. My programs are self-testing, so to speak. Since the testing is automated, I can afford to retest all of the program's features several times a day.

When I make a mistake, it's overwhelmingly likely that one of my tests will fail. As a consequence, I'm informed of my mistakes almost immediately. As a further consequence, I nearly always know where I made a mistake: most of the time, it's in the code I wrote a hour or two ago, or ten minutes. In the rarer cases where I only spot a mistake later, I reflect on the kind of test I could have written to spot the mistake sooner, and I write the test after the fact. This trains me to write the right kind of test.

Just say no to debugging - it doesn't scale.

- Testing - No comments / No trackbacks - §

22 July 03 - 12:31The Logic of Expression

Peter Lindberg: "Humans seem to have a tendency to invent constrained universes of expression."

The logic of expression is a topic I've been thinking about, in a back-of-my-mind, inarticulate sort of way, for what must be years now.

The phrase "constrained universe of expression" is new to me, and apt, but immediately meaningful. A cousin would be Douglas Hofstadter's "linguistic medium" : a language restricted by a set of constraints that are not so tight as to preclude the expression of arbitrary meanings.

Similarly, but at a lower spot on the same scale, we can speak of an "expressive medium" : a set of constraints applicable to some activity, not necessary linguistic, that are loose enough to permit an arbitrarily large range of nuances in meaning. It's not necessary that meaning can be expressed, just nuances. Peter mentions Yo-yos; a good test of Yo-yos as an expressive medium, for instance, is whether you could laugh out loud at a particularly skilled performer's rendition of a "yo-yo joke".

It's not just that we invent expressive mediums. We have a knack for turning anything we do into an expressive medium. As a beginning driver, I was surprised to find that it was possible to blink a turn light contemptuously, or aggressively.

Code occupies a middle ground. You can't "express arbitrary meanings" in code, at least not in correct, working code. Pseudo-code makes for a somewhat amusing linguistic medium (here is a somewhat loose example), but you can't use actual, working source code to articulate your feelings about the Gulf war or compose a love letter.

Source code does allow one an infinite range of nuances in a restricted domain of expression : the description of problems we expect a computer to solve for us.

- Private Life Of The Brain - No comments / No trackbacks - §

21 July 03 - 21:54Blueprints

Commenting on the Alan Cooper quote, Pascal pointed me to this entry by Chris Sells.

Cooper is on record as insisting on a "phasist" approach to software development, seemingly in violent opposition to XP. Cooper's ideas are nicely modular, though. I can certainly imagine, with Kent Beck, adapting some of the novel stuff in Interaction Design (personas, goal-directed, rich modeless visual feedback, no error messages), and leaving phases aside.

Something in Chris' entry caught my attention:

Of course, what Alan's talking about is the standard waterfall method of software design, which is what I learned in software engineering school. So why don't we do it? Because we don't like drawing up blueprints. We like to make the lights go blinky, blinky on the monitor. Building a shed in your backyard is quicker and easier without an architect or an engineer involved, but is that how you want your house built?


I'm puzzled with this "don't like drawing blueprints" idea. As far as I'm concerned, it's true: I don't like drawing blueprints. On the other hand, the fact of the matter is that I am, with some regularity, asked to write code for software products. So it seems that there are people the world over who get asked to write code for software products. And, as a rule and broadly speaking, they don't like drawing blueprints.

I suppose someone has had the idea of trying to get software from people who do like drawing blueprints. I wonder how that went.

- Software Development - three comments / No trackbacks - §

21 July 03 - 21:39Orwell on Language

Thanks to Jim Bullock for reminding me to reread Orwell's Politics and the English Language.

What is above all needed is to let the meaning choose the word, and not the other way around. In prose, the worst thing one can do with words is surrender to them. When yo think of a concrete object, you think wordlessly, and then, if you want to describe the thing you have been visualizing you probably hunt about until you find the exact words that seem to fit it. When you think of something abstract you are more inclined to use words from the start, and unless you make a conscious effort to prevent it, the existing dialect will come rushing in and do the job for you, at the expense of blurring or even changing your meaning. Probably it is better to put off using words as long as possible and get one's meaning as clear as one can through pictures and sensations. Afterward one can choose - not simply accept - the phrases that will best cover the meaning, and then switch round and decide what impressions one's words are likely to make on another person.

- The Universe And Everything - No comments / No trackbacks - §

20 July 03 - 21:56Blame the user

During my vacation, I've read and (mostly) enjoyed About Face 2.0, by Alan Cooper and Robert Reimann. It's a long, long book, not unlike Meyer's Object-Oriented Software Construction (2nd ed.) in this regard.

It's well worth slogging through, however. I've particularly appreciated the description of the "personas" scheme to drive requirements elicitation.

I was captivated by the entire rant on error messages, and how they should (and very often could) be eliminated. Mark well the following gem:

No crisis inside a computer is worth humiliating a human.


Error messages often make people feel stupid, or incompetent, or somehow unworthy. Modal error messages are particularly offensive in that they stand right there in the user's path to productive work. I've blogged once already about a particularly obnoxious instance, and I suppose we all have our favorite stories about the error box from Hell.




On a related note...

A recent entry by Andy Tinkham, primarily on the use of context-free questions, brings up an example with an interesting "ethical" conondrum. The example is about testing an application's rules for validating input values in the GUI, and making sure the program puts up an error message for "incorrect" values. Well, it's a conondrum when seen from Cooper's point of view, and keeping in mind Brian Marick's advice that a tester should consider usability problems to be valid "bugs". How should a tester approach testing "features" which detract from the product's value rather than add to it ?

- Software Development - one comment / No trackbacks - §

11 July 03 - 16:46Vacation alert

Take vacations, says Johanna.

So I'm off on one, for the next week. No Internet access (it's a rather rural seaside place in Normandy). No laptop (I don't have one anyway). I'm only taking my cell phone with me. Don't expect any postings until around 22/07.

- Blogversations - No comments / No trackbacks - §

09 July 03 - 23:05Conflict

Conflict is a bugbear with me. I can't stand conflictual situations; at work or in life.

By "conflict" I do not mean opposition, such as when ideas are being debated. I don't mind healthy opposition. Nor do I mean contention, for instance a situation where a scarce resource must be apportioned. I'm quite able to accept the possibility that someone else will be getting something I wanted.

No, the kind of conflict I have in mind is the "who comes on top" thing. Displays of aggression, symbolic or actual. As an example of just how far things can go in the first category, I played a few "serious" games of chess recently, at a tournament where my son was playing. I was shaking with adrenalin by the middle of the first game. It was almost the same as an actual, physical fight. I wanted to run for my life.

At work the same states can be triggered by someone being loudly angry, or even taking an excessive blaming posture toward me or someone else. Some small thing can trigger a surge of adrenalin. I suspect that what I hate most about such situations is how little control I feel I have over my reactions to them.

I'm wondering if this is a problem I have, or merely a consequence of investing so much thought and energy in cooperation. I have too little left to think up or practise tactics for dealing with conflict.

- Private Life Of The Brain - two comments / No trackbacks - §

07 July 03 - 22:19Risk Management

Somebody over on comp.software.extreme-programming was asking how risk management plays with XP. I'm (still) an XPer; I also like to think of myself as at least minimally risk-savvy and apply risk management techniques consciously, if quite informally, on projects I'm involved with. I took the occasion to do a brain dump of what I know about the topic, and I'll post it here, as always in the hope of learning something new.

I started with a quick Google brush-up on "risk management". It hasn't changed too much since I last got an interest in the topic.

The memes I've got installed at the moment, whether they are useful or not, run more or less as follows.

Risk is basically the problem of not having facts about the future. At best we have facts about the past. Risks are undesirable things that might happen in the future, and we have no way to tell which of these things will or will not happen.

A project consists essentially of the statement that a given desirable future will come about. Thus a project is risky through and through : there are many more undesirable things that can happen than desirable ones. There is less risk in maintaining a desirable status quo than in bringing about a new state of affairs.

Any structured, deliberate approach to doing something already constitutes risk management. Driving with both hands on the wheels is managing the risk of being involved in a car collision; so are putting on a seat belt or buying a car with air bags. Extreme Programming contains provisions for certain risks, which might or might not be the risks which affect your project.

You cannot address unspecified risks, or "all risks". You might be hit by a meteorite tomorrow, or you might lose your job. If your circumstances are anything like mine, protecting your job takes priority. Risks are prioritized by, roughly, likelihood of occurrence times damage done if risk materializes. Let's say that your greatest risk is "We might not meet milestone M with feature set F as scheduled." There is a broad palette of risk tactics for each specific risk.

Risk avoidance: I don't think XP "avoids" risk at all. Risk is avoided by obviating the possibility that the undesirable event will happen. You refuse to commit to meeting milestone M by feature F - don't sign the contract until the software is done. This avoids the risk. As long as you enter into the contract to deliver specific scope by a specific date, the risk that it won't come about exists.

Risk reduction: this consists of minimizing the likelihood of the undesirable event. XP reduces the likelihood that you will lack some features at each milestone by reducing the amount of "extra" work to be done, such as paperwork or documentation, and improving overall quality so as to make development faster.

Risk mitigation: this consists of minimizing the impact of the undesirable event. XP has active mitigation for the "schedule risk", by insisting that the most valuable features be done first; this reduces the likelihood that important features will be left out of milestone M.

Risk acceptance: just grit your teeth and take your beating. So we're missing feature F by milestone M - we'll ship with what we have by that date. After reduction and mitigation, XP manages any residual risk this way.

Risk transfer: this consists of getting someone else to take the risk in your place. Insurance is a risk transfer tactic. You pay a definite, known-with-certainty amount of money; the insurer will reimburse you if the risk of not completing feature F by milestone M materializes. No provision in XP. Has anyone ever insured a software project against schedule/budget overrun ?

Contingency planning: substituting one risk for another, so that if the undesirable event occurs you have a "Plan B" which can compensate for the ill consequences. If we miss critical milestone M1 with feature set F1, we'll shelve the project and reassign all resources to our back-burner project which is currently being worked on by interns.

Key point from all the above: risk management starts with identifying specific risks. Also, I think you can perform conscious risk management using any process, method, technique or approach. It's important to recognize that any process, etc. simply changes the risk landscape; your project will always have one single biggest risk, then a second biggest risk, and so on.

Also: risks, like requirements, don't have the courtesy to stay put over the life of a project. They will change - old ones will bow out as risk tactics take effect, new ones will take their place.

Risk management is like feedback. If you're not going to pay attention to it, you're wasting your time. More than once I've tried to adopt a risk-oriented approach to projects, only to have management react something like, "Oh, you think that's a risk. Well, thank you for telling us. We're happy to have had that risk reduced. Now proceed as before."

One risk I often raise in projects is skills risk. Developers are supposed to crank out Java code who have only ever written Visual Basic, that sort of thing. Not once have I seen a response of risk avoidance (substituting other, trained team members for the unskilled ones), reduction (training the worker in Java), or mitigation (making provision for closer review of the person's code). It's always been acceptance - "We know it's less than ideal to have this guy working on that project, but he's what we've got at the moment. Can't hire anyone on short order, no time for training, no time for more reviews."

If you only ever have one tactic for dealing with risk, your risk "management" is a no-brainer.

- Extreme Programming - four comments / No trackbacks - §

04 July 03 - 19:29Exaptation

I dithered a good ten minutes before settling on a title for this entry, which is somewhat unusual. Today's topic is "scope creep", the uncontrolled change in requirements which keeps bringing projects over into the dark land of Late And Over Budget, or so it is said.

Although it has deprived me of the most natural title, I wanted to refer to Dale's wonderful piece on The Scope Creep, where he points out who the true culprit is on most of those occasions when we complain about "customers changing requirements behind our backs" - ourselves, when we fail to manage our agreements with the customer.

I also wanted to use the term "spandrels", in reference to the controversial article by Stephen Jay Gould and Richard Lewontin, which uses an architectural metaphor to contrast the evolutionary mechanisms of exaptation and adaptation.

Also, for some reason I was certain that "exaptation" wasn't in the dictionary. It turns out that it is, which solves the easy problem of coming up with a title, and leaves the more difficult one of explaining what exaptations have to do with scope creep.

In the context of software, an exaptation consists of people finding a valuable use for the software by exploiting some implementation-level behaviour which is entirely accidental and was never anticipated as a requirement. Exaptations are interesting because I think they have to do with more than managing agreements - they're part of the process of discovering requirements as the product is being built. They're also both a boon and a trap.

I saw a real live example of exaptation today on a project where I'm helping with the XP Customer role, which is why it's on my mind. The software is a business process modeling tool, and it can be used to generate code for Web applications that implement some automation for these business processes. Users create page templates for their platform of choice (JSP, ASP) or use one of the samples provided, then with a click on 'Generate', voila - the application is created.

For performance reasons, the pages are generated in two passes: in the first pass an intermediate form is produced, which is then processed once more to yield the final pages. This makes for faster turnaround time when users modify only the BPM and not the template, and re-generate. Then someone in the Professional Services department found that you could open the intermediate pages with a tool such as Dreamweaver, and move certain things around in a way not provided by the modeling tool. There had been a "product suggestion" in the knowledge base - not an official requirement, mind you - that it should be possible to move these things around, and it became known that this was a way to do it. Eventually this "trick" found its way into end user documentation.

Exaptations can be wonderful because they suggest "low hanging fruit" for delivering features that surprise and delight the end users and hopefully the customers of the software. (I say hopefully, because the end users of a system's features are not always its customers. For instance, a category of exaptation is "security exploits" - flaws in the implementation which allow persons with malicious intent to retrieve information they're not supposed to see.)

They can also be traps, and I think particularly in Agile contexts, where no detailed documentation is kept of requirements as "problem-space", separate and distinct from implementation-level, or "solution-space". The Agile process with the most detailed requirements documentation is XP, which keeps detailed acceptance tests for each distinct feature of the software; but acceptance tests mix together requirements and implementation.

The XP remedy to this problem, of course, is the doctrine that "the requirements are never wrong, only incomplete" : all it takes to change a feature, or steer it away from an undesirable implementation, is writing one more test. On the other hand, such a decision may mean removing some "feature" that end users have come to rely upon, which may take some courage. At the very least, for product companies, it will open up a difficult question - how well do we know our users, what they do with our software and what they've come to expect of it ?




A footnote:

Jerry Weinberg's otherwise excellent Exploring Requirements lists no less than 14 categories of "requirements leakage", a.k.a. scope creep, but none that corresponds to exaptation: altered hardware base, customer complaints, compatibility with manuals, private bug fixes, sales force complaints, changed standards, one-time special features, operating system changes, special favors, annual updates, demonstrations, internal bug fixes, marketing features... and "programmers fooling around".

- Software Development - three comments / No trackbacks - §

02 July 03 - 22:51All or nothing

Me: "Rather than spend a lot of time removing bugs from your code, what I suggest is finding ways to write code that has no bugs in the first place."

They: "You are an extremist ! It is well known that no code ever written is without bugs. Why do you always have to insist that quality is an all or nothing proposition ?"

When I hear that bit about "an all or nothing proposition", I feel I'm being set up for a verbal trap.

I am not advocating software quality as an "all or nothing proposition". I am advocating software quality as an "all" proposition. The "or nothing" term does not enter in my reasoning; most of the time, and in spite of our best efforts, "nothing" is precisely what happens. I don't worry about "nothing".

I do worry about the intermediate, shades-of-gray positions which lie on the scale that includes "all" and "nothing". In particular, I am concerned that with diligent effort at software management, we might be able to achieve "worse than nothing" : a net decrease in the quality of the code produced. I am also concerned that our best efforts might yield no more than "not enough to prevent the business from going under".

These are the relevant terms of the quality proposition.

When I say I advocate quality as an "all" proposition, what I mean is that we should adopt a goal : no new bugs in what we ship from now on. We may miss this goal, of course. We are not infallible. But we will not be satisfied with anything less than the goal.

- Software Development - No comments / No trackbacks - §

01 July 03 - 16:02The heart of refactoring

There's a piece of advice often given to writers, which goes as follows. You're writing an article, or a book, or whatever, and somebody who's reviewing your work feels prompted to ask : "I don't understand what you mean here". Novice writers will attempt to explain what they meant to the reviewer. Experienced readers will make their meaning clear in the original piece, and ask for a review again. Sometimes you have to explain, of course - not once but many times, until you know what you really meant to write. But ultimately, it must end up in the writing. Spare your reviewer the explanations; put them instead in the article.

That advice is the heart of refactoring. When you come across something and catch yourself explaining, or even thinking, "we wrote it this way which isn't ideal - that way would have worked better", change it right now so it reads that way. If you've learned a better way, put the better way into the code. Or more succinctly: teach the code everything you learn.

- Extreme Programming - No comments / No trackbacks - §

Linkdump