Why Does This Work Q&A
A followup to yesterday’s article ‘Why does this work?’, with questions and answers and some references to folks from whom I have learned.
Here are questions that readers of the preceding article may have. If you have additional questions or useful comments, please get in touch and I’ll revise as seems fitting.
Questions
Is it always possible to proceed in small steps?
Based on long experience, I believe that it is. One argument to that effect is that our program will always be created bit by bit: we can’t type it all in on a single morning. So the problem comes down to working in such a way that each small step can be tested and shown to work.
What about AI solutions that will someday provide entire programs based on a spec?
Even if “AI” was not consuming precious resources at a prodigious rate and even if “AI” was not going to be used to eliminate jobs for people without dealing with the needs of those people, I would be pessimistic about it.
In my experience I have never seen a specification without errors in it. I have never seen a specification that actually meant what its author thought it meant. So providing a spec is a big problem.
The “AI” systems out there are, as Emily M. Bender puts it, “stochastic parrots”. They feed back answers that are based statistically on answers they have read when being trained. Despite their often very impressive performance, they do not understand the question or the answer. Their answers are often good but sometimes quite subtly wrong. Funny story about that. I’ll use fake names but this happened in my email.
Dave is the husband of my friend Sue Thompson. Dave’s dad passed away at an advanced age and I sent Dave a condolence email care of Sue, because I don’t have Dave’s email. Yesterday I got an email from Sue’s address. The AI summary from Apple looked like this:
Sue Thompson
Dave’s funeral will be held on January 20th
in SomeCity, MN.
You can imagine my shock at hearing that Sue had suddenly lost her husband.
The note was actually from Dave, telling me that his father’s funeral would be on the 20th in SomeCity. The actual email, lightly edited, was
Ron, thank you for your kind words of sympathy. The family will be saying good-bye to dad on Monday, Jan. 20 in SomeCity,MN. A visitation, Catholic mass, burial and a lunch are planned.
Cherish the day, Dave
The “AI” was smart enough to figure out that a funeral was involved. The email does not say “funeral” anywhere. It was also dumb enough to think that Dave was the dead guy.
Now imagine that an “AI” has written some large application. Imagine that we care that it gets right answers. How will we ever know?
I am not optimistic about AI.
How do you see the small steps?
Difficult question: it’s not always easy. I have a few strategies that I use:
-
Focus our code style on small classes and short methods, even if we happen to be working in large steps. As we see small pieces, we’ll begin to be able to devise other small pieces.
-
Try to express what has to be done in words. Whenever we finish a sentence or say “and” or “or”, we may have identified a separate step;
-
Think of a really stupid small thing, implemented in a really stupid way. Then think “well, that won’t work but …” and see what comes to mind;
-
Sit with team members and kick it around a bit. Not for hours, just a bit;
-
Practice. The more I try to think of small steps, the better I get at it.
How do you work with TDD when you set out to write a whole class?
I almost never just set out to write a whole class that someone has decided we need. The very idea is counter to the notion of small steps. Writing a class before deploying it is a big step. I tend to create classes as small things that can quickly be started, and then let them grow as they take up more and more of the load.
I find it useful to use Beck’s “Fake it till you make it” strategy, creating a small class that appears to be producing correct answers to the tests but that is in fact just returning constants. It’s usually sufficient to stop at one such fake answer and then enhance the code, but sometimes you’ll find that there are different kinds of algorithms for different answers. In that case, either fake them all, or simply only build them one at a time.
Finally, sometimes I’ll do an experiment, a “Spike”, building a little version of the class I have in mind, using small steps and TDD where I can, but also sometimes blurting out big chunks of code that I’ve ripped untimely from the womb of Stack Overflow or someplace. I do that when I want to get a basic understanding of what things might be shaped like.
The received wisdom on a Spike is to throw it away. My own practice is to decide whether to keep what I have and begin to weave it into the program, or to treat it as a learning experience and toss it. It’s never wrong to toss it. If we’ve done so much work on it that we fear wasting all that time, we’ve gone too far and spent too much time. It’s probably good discipline to throw out anything if the best argument for it is that it took a long time to do.
What about code branches?
I haven’t worked in a large team for a while, so you should take this with some salt. On the other hand, I hang out with people who are smarter than I am and who do work with large teams, and the general view is that branches are not good. Certainly long-lived branches are right out. The code in a branch inevitably diverges from the main and integration takes a long time.
If all the tests run with my code for the most recent small step, what harm is there in committing it and pushing it right now?
What if we see an improvement but can’t make the improvement now?
What if we don’t see the need until later?
As I discussed in the previous article, I would not recommend stopping productive work to refactor previously committed code that is not in need of functional change. Sure, if you can get some free time to clean something up, it’s OK to do it, but it seems to me that the payoff is in having the code we’re actually working with be easy to work with.
So when we do have work that impacts the area needing refactoring, let’s do some of that refactoring as part of the needed work. I advise cleaning up the area where we are working, rather than going around looking for areas to clean up.
And always … small steps. And never … on a branch.
References and Sources
Here are just some of the sources for what I say here. It is somewhat amazing that with all these contributors, I am still so limited. You’d think I’d be amazing with all this help.
Many More Much Smaller Steps
Small steps have always been part of my style, but it is GeePaw Hill who has really brought the idea home to me, thought conversations and pairing. I’m still not as good at it as I’d like to be. I suspect that there is no step from green to green that is too small.
Test-Driven Development
The original source of TDD, according to Kent Beck, was in an ancient book about programming, but Beck gets the credit for bringing the idea to prominence in its current form.
Refactoring
The definitive source on refactoring is Martin Fowler. Machine refactoring was originated by Bill Opdyke and Ralph Johnson, if I’m not mistaken. It was brought to my attention by Martin and Kent Beck.
Reflection (Kerth, Schwaber)
Norm Kerth wrote the book on Retrospectives, and Schwaber and Sutherland made it part of Scrum. I’m not sure who invented just sitting back and thinking about what one has done. Probably my mother.
So many ideas, so much collaboration
More often than not, I don’t know where my ideas came from. I don’t claim to have invented much of anything, I’ve just picked up a lot of lint along the way. Much of what I think, do, and believe, is certainly the result of my long collaboration with Chet Hendrickson.
Trying to be a better human: Larsen, Dyson
We haven’t spoken much about working with others here, the base article is the story of how I work, which is here sitting at the zebrawood desk in what in any reasonable person’s home would be the front room. But in fact teamwork and general working with others is a key aspect of succeeding in software development or in anything, and I have been particularly helped along by Diana Larsen, Esther Dyson, and Linda Rising. My personality is still mostly odious, but you shoulda known me before.
Other Sources
Various challenging and useful ideas have some from many people, notably James Shore, Brian Marick, Elizabeth Hendrickson, and Michael Bolton (not the singer). I hesitated to start this list because wherever I stop, I’ll have left out so many marvelous people whose interactions with me have been valuable and precious.