Joel on Software
Joel Spolsky
Apress,
2004
Yet Another Book
Review
By
J. L. Sloan
2005-04-22
Joel Spolsky is a hardened veteran of several campaigns in the
software wars. He was on the Excel team at Microsoft. He worked for an internet
startup. Now he runs his own successful software company.
Since about 2000
Joel has written an influential, and occasionally controversial, weblog, Joel on Software (http://www.joelonsoftware.com). The
contents of his blog range from thoughtful treatises
on software marketing strategies, to techniques for writing better code, to
rants and raves where he names more names than I personally would feel
comfortable doing in today’s litigious climate. That’s probably why Joel is
writing a very popular weblog and I am not. The one
common theme that runs through all of Joel’s essays is that they are frequently
hysterically funny, typically at the expense of other hapless individuals or
companies. Joel is not afraid to cite specific bad examples of what not to do.
We should all be glad he has not turned his attention to the telecommunications
industry (although he did write an essay on the joys of getting network and
telephone service to his offices in
I discovered Joel’s blog while researching Robert Austin’s book, Measuring
and Managing Performance in Organizations (Dorset House, 1996).
Some of Joel’s
better blog entries have been consolidated into a
book by the same name, Joel on Software (Apress/Springer-Verlag,
2004). The forty-five essays in the book have been edited to offer a more
coherent flow, and too allow forward and backward references to related
material. The book is divided into four sections. The first is on practical
aspects of being a better software developer. The second is on managing
software developers and the development process. The third is a more general
collection but is largely about software marketing strategy. The last, and
least useful to me, was a series of essays on Microsoft’s .NET product,
something which apparently figures prominently into the commercial web tools
that Joel’s company, Fog Creek Software, produces.
Like
“Shrinkwrap”
is software that is sold in boxes at CompUSA or downloaded off the internet. It
has millions of users and must run on as a generic a platform as possible to
insure a broad user base. Shrinkwrap software is more
or less in eternal development. Existing features must be refined and new
features added to battle off competitors and to insure future revenue by
enticing users to upgrade.
“Internal” is
software that is developed for a specific internal application. Since there is
really only one user of the software, there is no market pressure to improve it.
Development tends to grind to a halt when the software is “good enough”.
“Embedded” software
must be developed to a much higher quality standard. Even though it may be
capable of being upgraded, it frequently is not. I’m reminded of the hassles
I’ve had trying to upgrade various consumer devices such as MP3 players. Also,
the limited interface to the device means workarounds to bugs may not be
possible in the field.
“Game” software is
unique for two reasons. Only “hit” games are really profitable, so a game
developer must release a portfolio of games so that the very few hits make up
for the more numerous bombs. The other issue with games is that they really are
never upgraded.
Finally, “throwaway”
software is that which is written to solve some immediate problem. It has no
life cycle. For example, code written to convert files from one format to
another may be used just once, until all the files have been converted. (I once
developed tools to convert hundreds of thousands of files from the various IBM
VM formats to something more palatable to UNIX languages. These were files
accumulated in a petabyte-scale mass storage system
over the span of a decade. Most of them were the output of supercomputer models
and could not be recreated. Since the VM system was going away, there would be
no second chance. The VM formats were not documented, so I had to reverse
engineer the VM source code written in IBM assembler. I also learned a lot
about UNIX file formats. As important this all was, I bet the source code for
those tools does not even exist anymore.)
I found a lot to
think about in this fairly simple software classification. Joel lives in the “shrinkwrap” world. The successful processes and techniques
in his world might not work in my world. The other thing I thought about is
that CM doesn’t quite fit in any of these worlds, although “embedded” is
probably the closest. So maybe Joel’s taxonomy is a little coarse.
In “The Joel Test:
12 Steps to Better Code” he outlines the basic processes and tools every
software developer should use and have at their disposal.
1.
Do you
use source control?
2.
Can you
make a build in one step?
3.
Do you
make daily builds?
4.
Do you
have a bug database?
5.
Do you
fix bugs before writing new code?
6.
Do you
have an up-to-date schedule?
7.
Do you
have a specification?
8.
Do
programmers have quiet working conditions?
9.
Do you use
the best tools money can buy?
10.
Do you
have testers?
11.
Do new
candidates write code during their interview?
12.
Do you
do hallway usability testing?
You the reader will
probably not be able to avoid comparing this list to our own CM processes. It
would be interesting to compare notes on this topic. Some of this, like
“hallway usability testing”, is really only applicable if you are writing
user-facing software, and in the CM process would have to be done by systems
engineers. (As I’ve said before, translating ATM CES trunks would fail this
test.)
In “Hard-Assed Big Fixin’”, Joel makes three points. “Make sure you find out
about the bugs.” He recommends shrinkwrap-centric
techniques for this, like automatic bug reporting when good software goes bad.
But our own MR database is a form of this. “Make sure you get economic
feedback.” He recommends charging the cost of a technical support call to the
business unit that produced the code. This is an interesting idea in our own
world. Maybe we already do this. But if we don’t, doing so would certainly
alter the basic economics of software development. “Figure out what it’s worth
to you to fix them all.” Joel admits that some bugs are not worth fixing. The
cost of fixing the bug will be greater than the revenue gained or retained by
having it fixed. But he argues that unless you know the economic cost of having
a bug, it is hard to know the return on investment of fixing it. Much of the
ROI lies in less tangible ideas like the perception of quality among your
customers.
“Biculturalism”
discusses the difference in cultures between the Windows world and the UNIX
world. He cites from Eric S. Raymond’s book The Art of UNIX Programming
(Addison-Wesley, 2003) (I have this), comparing Raymond’s UNIX-centric design
culture with the Windows design culture. Joel remarks that UNIX applications
tend to be written for other UNIX developers, while Windows applications are
written for “Aunt Marge”, a naïve at best computer user.
They really are two
completely different cultures. UNIX applications tend to remain silent until
they have completed. Windows applications display a progress bar. UNIX
applications have interfaces usable by other applications, including scripting
languages; a GUI interface might be tacked on top. Windows applications are
primarily GUI based; an API might be tacked on the side. (I’ve remarked that
UNIX interfaces look like they were designed by a lot of graduate students that
never talked to one another. Mostly because that’s exactly how they were
developed. Windows applications, and Mac ones to boot, tend to have similar
look and feels thanks to a common GUI toolkit on each platform.)
Joel remarks that
neither approach is wrong. It is just a result of the cultures of each system.
It will no doubt occur to you the reader that this may have more than a little
to do with Linux’s incursion into the server arena
while it has mostly failed on the desktop. (I use a Windows XP laptop as my
desktop here in the palatial Digital Aggregates corporate headquarters. I also
run Linux on a second laptop… which I use as a server. Using it directly is
still just too painful.)
In the essays
“Incentive Pay Considered Harmful” and “Measurement” (the review of
“…at
least two dozen studies over the last three decades have conclusively shown
that people who expect to receive a reward for completing a task or for doing
that task successfully simply do not perform as well as those who expect no
reward at all.”
Those forced to
listen to my talks on measurement dysfunction will recognizes this as the
difference between extrinsic and intrinsic motivation.
He also cites
material from another book I can recommend, Tom DeMarco
and Timothy Lister, Peopleware: Productive
Projects and Teams (Dorset House, 1999) (I have this too). DeMarco and Lister argue that regular performance reviews
do more to drive wedges between team members than to improve productivity.
However, while I
agree with the points here that Spolsky, DeMarco and Lister are making, I have to admit that none of
them are very good at explaining just exactly what you should do instead. This
is probably one of the reasons I have gotten out of management on three
different occasions. Leadership I grok. Management
remains a mystery to me, and, apparently, if my own experience is any indication,
to most other managers.
I won’t describe the
essay “Top Five (Wrong) Reasons You Don’t Have Testers” in any detail because,
well, we have testers. Pretty darn good ones to boot, in my own experience. But
it is worth mentioning that Joel says do not try to use programmers as testers.
The skill sets are completely different. “I’ve seen a lot of this. Programmers
do not make good testers, and you’ll lose a good programmer, who is a lot
harder to replace.” Given our current perceived devaluation of good programming
skills (while at the same time bemoaning the quality problem in the CM code
base), maybe the “lot harder to replace” isn’t really felt to be an issue. Joel
does promote offering interested testers a career path into development, which
I agree with.
“Human task switches
considered harmful” argues, with mathematical support, that it is probably more
efficient to perform development tasks serially than in parallel. Anyone who
has spent more time just keeping track of what is on their plate instead of
actually accomplishing work will find no surprises here.
In “Things you
should never do, part one”, Joel claims the single worst strategic mistake any
software company can make is to rewrite code from scratch. Somewhat to my
surprise, I found myself agreeing with this. Joel isn’t saying that “refactoring” is a bad idea. But he does use case studies of
real companies who decided to rewrite their cash cow software product from
scratch, and didn’t ship a product for years. One thing he says which got an
“Amen, Brother!” from me was “It’s harder to read code than to write it”. This
is absolutely true, even if you wrote it yourself. I remember years ago I had a
young developer I had never met before show up at my office door asking about
some code I had written mumble mumble years ago. It
was in IBM 370 assembler. I didn’t remember the code. Heck, I didn’t even
remember the project. Yes, I could see that the code was written in my style,
and it had my name in the comments. Honestly, I remembered that there was a
time in my life in which I had written tens of thousands of lines of IBM 370
assembler code. But I had no idea what this stuff he had in his hand was even
for. But thanks to years of experience reverse engineering other people’s code,
some of it in languages I had never seen before, we figured it out together.
Thank the Fates for good comments. My opinion, not necessarily Joel’s: doing
maintenance on large software bases was a good way for me to learn what is good code and what is bad code.
“The Iceberg Secret,
Revealed”: “Customers don’t know what they want. Stop expecting customers to
know what they want. It’s just never going to happen. Get over it.” There are
exceptions to this rule, but it’s more true in my experience than not. As
someone once pointed out, if companies only developed what customers wanted,
the cellular phone would never have been invented. There was no perceived
market for what later turned out to be a multibillion industry. This is why
(again, my opinion) you must do a certain amount of forward looking work unless
your goal is to produce the same commodity as your competitors and acquire
market share incrementally. And you must expect the majority of your FLW to not
yield useful results.
In “The Law of Leaky
Abstractions” Joel generalizes what every OO developer already knows: that when
an otherwise good abstraction starts to leak, that is, the abstraction starts
to fail and exceptions in the interface start to creep in, problems occur. For
example, NFS makes remote files look and act like local files. Until the
network goes down that is, and the remote files don’t look or act anything like
local files. The NFS abstraction develops a leak. However, “All nontrivial
abstractions, to some degree, are leaky”. I would claim too that if an
abstraction has no leaks at all, it probably isn’t really an abstraction. It
probably accurately describes something quite concrete. However, an abstraction
with no leaks may be either too trivial or too detailed to be useful. So leaks
are inevitable.
The essay “In
defense of not-invented-here syndrome” Joel attacks code reuse. Yes, this hurt
a little bit, even though I believe I have come to agree with his argument. He
points out the reuse is frequently proposed by “architecture astronauts” that
don’t have to deliver working code (ouch). And that dependencies
in code, whether caused by reuse or not, lead to breakage. An example of this,
albeit not from Joel, is the so called “brittle base class” problem, where a
change in a base class breaks all the derived classes, often in subtle ways. He
proposes reusing code where it makes sense, but if the code implements a core
function, do it yourself. He recognizes (although not
necessarily in this particular essay) that this is also the rule for when to
outsource business functions and when not to. If you are a software development
company and your revenue stream depends on developing software, do not
outsource software development. Payroll, yes. Accounts receivable, yes. But not core business functions.
In a series of five
essays on software business strategy, he compares the Ben & Jerry’s
business model (lots of competitors, commodity product, no customer lock-in,
slow and sustainable growth to acquire market share, corporate culture is
important, if all fails you won’t lose too much money) with the Amazon model
(no competitors yet, must rush to acquire market share at all costs before they
show up, things are moving so quickly that corporate culture is impossible, you
have a tiny chance to becoming a billionaire, a much larger chance of
squandering hundreds of millions). He discusses the myth of bloatware:
yes, Microsoft applications have grown a lot in successive releases, but given
the reduction in the cost of processing power and memory, they’ve actually
gotten smaller in terms of their “dollar footprint” (my term). He talks about
the application of the microeconomic concepts of substitutes and complements
to software development, and in so doing gave me some nomenclature for what I
was trying to accomplish in the late lamented DETRE effort on the IPEI project:
a substitute is a product you might by if the product you really wanted was too
expensive; a complement is a product that you buy in conjunction with another
product. “Smart companies try to commoditize their products’ complements.” I
was trying to commoditize the embedded operating system, to lower the cost of
application firmware. Too bad I was too ignorant at the time to see this. Joel
points out that this is why companies support open source development: they are
supporting the development of a complement to whatever product (typically
hardware) they sell to generate revenue. (Joel isn’t too complimentary of Sun
Microsystems, whose marketing strategy neither he nor apparently anyone else
can quite figure out.)
I have described
only a fraction of the material in the book. I can recommend Joel on
Software, both the book and the weblog, as long
as the reader keeps in mind that Joel is writing about his own specific world.
His essays are both insightful and entertaining, even
though they sometimes come across as more of a rant and rave (this is true of
even the better ones).
(For a bibliography
of references like this book and others that I have found useful, visit
http://www.diag.com/ftp/Bibliography.doc.)
