OK, that headline is a bit inflammatory and an insult to a perfectly good tech journalist but Alex Kidman here is the latest in a long line of commentators to take a swipe at Apple for the quality of its software. Unfortunately he grabs the wrong end of the clue stick.
I am not going to argue that there aren’t some things that Apple could do to improve software quality, indeed I will point out some of them before I conclude. What I would like to do is look at some of the reasons there are problems. I will also point out some of the things that won’t fix the problems and why. As I do I’ll show why Alex is partly wrong though partly correct at the core of his arguments.
First, software is hard. I started out my professional life as a programmer, mostly writing code for accounting software, most of the time in C. It is impossible for anyone who has not spent several years writing software to understand the complexity of what you do and the difficulties you find in proving it’s correct.
A Tale of Complexity
Let me tell a short tale of one particular application I worked on. I was porting a payroll system from an old operating system — CP/M — to DOS and writing in a version of BASIC.
The first problem was that CP/M had an extended memory model and the BASIC under DOS didn’t. This meant that all the code for the current task had to fit into 64K of RAM and all the data had to fit into 64K of RAM — otherwise I had to look after manually loading and unloading 64K blocks of data and code.
Then came the complexity of the task. A payroll system — simple you might think. Well this was for a dredging company who ran a number of dredging boats. That meant staff who could be members of 4 different unions and over twenty different pay scales. Due to the difference in pay between different jobs at different times it was possible for a worker on the one shift to be paid one rate while he was on the wharf, a different rate while on the boat tied up, a third rate while the boat was moving to the dredge site and a fourth while the boat was actually dredging.
Now think of all the different possible scenarios that have to be tested to make sure this software is correct? It took me around ten working days to complete the first software port. It took me twenty working days of testing and debugging to get the software to the point where the customer signed off on it. After that I was back to the company on a regular basis for over twelve months to fix bugs we hadn’t found in our supposedly “complete” testing. (I was also back every year for five years because the ATO changed the formatting of the group certificates every year for five years. Bloody tax office.)
This was one fairly simple application. Apple deals with complexity orders of magnitude worse.
Are Errors Common?
How common are software errors? Let’s have a look at spreadsheets? A study in 2008 by Professor Raymond Panko concluded that over 80% of spreadsheets used in business contained errors. Please read the report as Professor Panko has done a great deal of work on errors and discusses them in depth in the paper. He also says that “Code inspection usually finds errors in about 5% of all program statements after the developer has finished building and checking the module”.
Then we also get to the question of how good is code inspection? To again quote Panko “Experience has shown that code inspection is very difficult. In experiments, it has been found that individual inspectors catch only half or fewer of all errors in seeded program modules. Even real-world team inspection usually only catches 80% or fewer of all errors in a program module.”
So writing error free software is hard.
So we can conclude that writing software without errors is really hard. Testing it can be an even worse nightmare. Have a look at the two “problems” that Alex Kidman raised.
The first is that if you set newer iOS devices to a date close to the 1st of January 1970 you will totally brick the phone. In case you’re wondering why that date then you should know that “Unix time” started on that day.
Imagine you’re the programmer responsible for that code. Why would people want to set their phone to a date in 1970? Why would you test that? You might test parts of your code to see what happens when you have a zero date but testing the entire code base with it might not be done and would never come up in user testing.
The other software problem Kidman raises is the “Error 53” problem. Apparently if you get your iPhone repaired by a third party and they replace the TouchID sensor then “at some point you may be locked out of your iOS device with the not-terribly-helpful “Error 53” message coming up. Error 53 is fatal to your device, and the data on it. Gone, lost, eradicated, and so on and not so forth. Not forth at all.” according to Kidman.
Once again let’s look at this from the point of the programmer. You’re writing and testing code to talk to the TouchID sensor. So you test the heck out of that code, you test it with a working sensor and you probably even test it with a broken sensor. You might even test it with attempts to hack the sensor. Do you test it with every possible third party sensor replacement?
Software testing is hard.
What is a Problem?
Kidman goes on to say “At the same time, bricking a phone because you didn’t play with Apple’s repair tools seems a little harsh. I do wonder if Apple hasn’t stuck itself between a rock and a hard place here, because it could well be that the underlying security code can’t be simple altered to allow unverified parts to drop TouchID and allow at least basic access without destroying the core security in the first place. Again, that comes down to the quality of the underlying code.”
Hey Alex, you try writing it and then come back and complain. He’s asking that Apple make a change to the iOS security model so that when there is a problem with a third party TouchID sensor you can do some things on your phone and not others. Oh, and Apple you better debug all that new code perfectly as well. (Then we start the arguments about exactly what “basic access” is and what you can do and see.)
Finally, Kidman’s “that comes down to the quality of the underlying code”. No Alex, that actually comes down to system architecture and code design, not quality.
More on testing and software quality later.
Why The Problem?
Now we come to the root question. Why is software hard and why does it have bugs?
Frederick P. Brooks in chapter 1 of “The Mythical Man Month” when talking about the woes of systems programming:
First, one must perform perfectly. The computer resembles the magic of legend in this respect, too. If one character, one pause, of the incantation is not strictly in proper form, the magic doesn’t work. Human beings are not accustomed to being perfect, and few areas of human activity demand it. Adjusting to the requirement for perfection is, I think, the most difficult part of learning to program.
Next, other people set one’s objectives, provide one’s resources, and furnish one’s information. One rarely controls the circumstances of his work, or even its goal. In management terms, one’s authority is not sufficient for his responsibility. It seems that in all fields, however, the jobs where things get done never have formal authority commensurate with responsibility. In practice, actual (as opposed to formal) authority is acquired from the very momentum of accomplishment.
The dependence upon others has a particular case that is especially painful for the system programmer. He depends upon other people’s programs. These are often maldesigned, poorly implemented, incompletely delivered (no source code or test cases), and poorly documented. So he must spend hours studying and fixing things that in an ideal world would be complete, available, and usable.
The next woe is that designing grand concepts is fun; finding nitty little bugs is just work. With any creative activity come dreary hours of tedious, painstaking labor, and programming is no exception.
Next, one finds that debugging has a linear convergence, or worse, where one somehow expects a quadratic sort of approach to the end. So testing drags on and on, the last difficult bugs taking more time to find than the first.
The last woe, and sometimes the last straw, is that the product over which one has labored so long appears to be obsolete upon (or before) completion. Already colleagues and competitors are in hot pursuit of new and better ideas. Already the displacement of one’s thought-child is not only conceived, but scheduled.
That was a pretty long quote but it saves me a good hour (or perhaps two) of writing. Brooks sums up most of the problem the iOS programming team faces better than I could.
Brooks has left out one critical problem faced by Apple’s software teams, a fixed completion date. When Apple is planning the release of a new phone or a new version of iOS then the software must be completed by a certain date. With a new phone then it is months before the the phone is released since the phones must start manufacture with the software ready. This adds difficulties in such areas as user testing. You can be sure that for several months before a phone is released there are a few Cupertino staff using the phone but for obvious reasons it can only be a few.
All of this has been a discussion of the problems about writing system software the first time. Changing software to add features or adapt it for new hardware adds a whole new set of problems such as technical debt and conceptual integrity over time.
When it comes to adding features to systems software there are two different parts to be addressed — the first is the platform and the second is the interface. When we talk about the platform we are referring to the underlying parts of the system that are used by developers and administrators. When we talk about the interface we are talking about what the user sees and interacts with. That might be new features or even whole new apps.
Let’s Fix The Bug
After you write it and software testing finds a bug then the programming team has to fix it. So how hard is software tresting and debugging?
To go back to Brooks (get used it to it, I will be quoting him a lot):
For some years I have been successfully using the following rule of thumb for scheduling a software task:
- 1/3 planning
- 1/6 coding
- ¼ component test and early system test
- ¼ system test, all components in hand.
Failure to allow enough time for system test, in particular, is peculiarly disastrous. Since the delay comes at the end of the schedule, no one is aware of schedule trouble until almost the delivery date. Bad news, late and without warning, is unsettling to customers and to managers.
Furthermore, delay at this point has unusually severe financial, as well as psychological, repercussions. The project is fully staffed, and cost-per-day is maximum. More seriously, the soft- ware is to support other business effort (shipping of computers, operation of new facilities, etc.) and the secondary costs of delay- ing these are very high, for it is almost time for software shipment.
That’s just the start of the problem. As well as not enough time and a lot of pressure from managers to get it finished, dammit! debugging is for most programmers a finicky, boring, difficult task. Remember Brooks describing it as a “woe”?
How hard can it be to find what’s causing a bug and fix it?
I once spent two days chasing one bug that involved adding data into a text field, if the field was empty when you submitted the form on one particular form then the software crashed. I could reproduce it easily. Unfortunately when I loaded the code into
db, the Unix debugger we used, the software worked every time. After two days I discovered that the programmer of the screen form system was asking for a chunk of memory for the field every time but not clearing it properly before using it and then to make matters worse wasn’t adding a null to denote the end of the text string. Of course when the software was run out of the debugger and inside the debugger the “random” contents of that memory block were different. Indeed since the program was constantly allocating and de-allocating memory mostly for text strings the chances of getting a long run of memory without a null text delimiter was small — and when combined with a form where you might add a blank text field there was only the one spot where the problem hit. So I spent the first day and a half checking in infinite detail the code defining that one particular screen before I suspected the software used to draw every screen form.
Ask programmers who have debugged a large system. They all have tales just like mine.
Fixing bugs is hard.
Why Is It Hard to Fix The QA Problem?
Why can’t Apple fix the problem? They have oodles of cash and make tons of profit — surely it only needs to devote more effort to the task to get better software design and quality?
If only life was so simple.
First, let’s be certain of what we’re talking about. I can (and often do) hack out a pretty useful, fully debugged, working flawlessly computer program in a day. The first spreadsheet program, VisiCalc was written by two blokes in two months. But that’s not what we’re talking about, we’re talking about an operating system – a much more complex beast.
Brooks says that we can turn a program into something better in two ways. One, by turning it into a product, which requires writing it in a “generalized fashion” so that it can be used by anybody over a wide set of data. This includes such niceties as documentation. The second is to turn it into a system. Brooks – “This is a collection of interacting programs, coordinated in function and disciplined in format, so that the assemblage constitutes an entire facility for large tasks. To become a programming system component, a program must be written so that every input and output conforms in syntax and semantics with precisely defined interfaces.”
Then we get the case where we do both. Then we get a systems product, which is exactly what we have when we talk about an operating system. Make no mistake, there is no computer task more complex than writing an entire operating system and a set of apps for it.
Could we fix it by hiring more programmers?
Brooks (again) sums it up perfectly when he states Brook’s Law – “Adding manpower to a late software project makes it later”.
The reasons for this are fairly simple. First a lot of systems programming is not partionable — you can’t break it down into smaller tasks. That means that when you assign two programmers to the task they have to spend some time communicating with each other rather than programming. Brooks says “Men and months are interchangeable commodities only when a task can be partitioned among many workers with no communication among them. This is true of reaping wheat or picking cotton; it is not even approximately true of systems programming.”
Brooks points out that this gets worse fast when you add even more people to the team “if each part of the task must be separately coordinated with each other part, the effort increases as nn-l/2. Three workers require three times as much pairwise intercommunication as two; four require six times as much as two. If, moreover, there need to be conferences among three, four, etc., workers to resolve things jointly, matters get worse yet.”
How about we hire better programmers? Studies have shown that the best programmers are easily five times and up to ten times more productive than the worst. Steve Wozniak wrote every single line of code required for the operating system (and BASIC interpreter) for the Apple II himself — indeed he wrote some of it on an airplane on the way to a computer show on paper (it was either the tape interface or disk interface, I can’t remember which.)
The problems here are many. First, programmers as brilliant as Steve Wozniak are rare. Even top quality programmers are rare. I know, I’m not one (I’m a good journeyman programmer, but not top quality) and during ten years as a programmer I met a limited number, maybe a dozen.
Second, no one has ever come up with a way of finding one out of a pool of candidates except by trusted recommendation. All those Google interview questions about the number of service stations in the US or writing a piece of code on a blackboard weed out the poor programmers but don’t sift the great from the merely good. Worse, they might miss a great programmer who needs an hour every morning noodling about to hit his stride, I’ve known a few of those.
Third, even when you’ve hired them it’s equally hard to know who the best programmer’s are. There can be any number of reasons why a great programmer is not obviously performing great work and equally a poor programmer can be covered by a great team. It requires extremely good managers to notice, reward and keep great programmers.
Finally, Apple need hundreds of programmers. It wouldn’t surprise me if Cupertino needs to hire a dozen (or more) programmers a week just to replace people leaving.
So if we can’t easily hire more programmers or better programmers then hiring is hard.
How About Agile Programming?
Why doesn’t Apple adopt Agile programming? How about team programming, or scrum?
First, once again we are talking about something other than normal programming. Here we are talking about systems programming. Most of those methods don’t apply.
You can be sure that the manager at Apple are using the best methods they can find to optimise the output and quality of the programmers and teams. You can also be sure that whatever the latest so called “solution” or “tool” that is sweeping the trendy programmers at the moment like whooping cough through the Northern Beaches will in the fullness of time be shown to be just that, a fad. Just ask all the advocates who told us that object-oriented programming would cure everything including cancer — now obvious by the egg on their faces — about predicting a solution to the problems of developing systems software.
Do Apple Know They Have A Problem?
A good question. Of course getting Apple to talk about anything is a monumental task, they are incredibly close-lipped. We can get some idea from a small number of public comments. When Phil Schiller appeared as a guest on John Gruber’s live podcast from WWDC last year Gruber raised the question. Here’s Schiller’s response:
Phil: So there is no doubt, with every release there’s bugs and there’s things we hit on and there’s things the team’s passionate about getting out there and fixing but we’re also very careful about tracking crash logs and Apple Care calls and Genius Bar visits and we even have a tool that is able to follow a lot of user forms to ascertain what the complaints are and try to really gather a good metric, set of metrics on all the issues. And in this case, I do think the storyline isn’t really accurate with the reality.
Not to say there aren’t bugs, there aren’t things that are driving some people crazy, there are. Of course there are. But it isn’t a change. In fact, if there’s any change I think the biggest change in Yosemite, truthfully, over the last year, was that we had a faster adoption rate of OS 10 than of any Mac OS in history. And so you saw a larger number of users faster in the release cycle, in more diverse networks and environments and different uses and that surfaced even more things that would have kind of have happened over a slower ramp. And so there were things to chase out and go to work on, no doubt about it. But I wouldn’t say it’s systemic to some issue or some wider thing going on, not in any way.
Gruber: The feedback I got, it seemed like you guys were taken a little by surprise by that because a lot of the things that you measure were all saying this is better than before. We’re seeing fewer crash logs per user. We’re seeing fewer of certain problems and I kind of feel like maybe what got lost in the shuffle there is that a lot of the problems people were having were things that don’t even generate crash logs and it’s sort of like some of this discoveryd stuff is just like all of a sudden my printer just isn’t connected anymore.
Phil: There’s an example where I think everyone should be proud that if we’re going to try something, it’s great to try things. Sometime’s it’s OK to take a risk. You don’t want everything to stay and never change. But if things aren’t perfect and people telling us they’re not happy with how something’s working here we are, we haven’t shipped El Capitan yet, already dealing with that within this one year cycle inside of that to make a big change to make things better and I think that’s a sign of how much the team is willing to self analyze what the situation is and do whatever is right.
Gruber: So just for the record, before we move on to the next topic, you guys do read the radars that they
<gestures at audience>file?
(Apple’s bug reporting system for developers is called “Radar” so a radar is a bug report.)
So Apple certainly know they have a perception problem even if they don’t publicly acknowledge a real problem. There is even an element of denial in Schiller’s response, “But I wouldn’t say it’s systemic to some issue or some wider thing going on, not in any way.”
The one thing that really worries me is that Schiller mentions what I believe is part of the real problem as an excuse, “And so you saw a larger number of users faster in the release cycle, in more diverse networks and environments and different uses and that surfaced even more things that would have kind of have happened over a slower ramp.” Yes, Phil but that’s a problem.
Just ask Mac administrators, as much as we warn, beg and plead our users not to install the new version the moment it comes out increasingly we find ourselves with a host of support calls the day after Apple rolls out a new version of OS X. It used to be that you had to go and buy a CD to install the new OS, then it was a many hour paid download. Now it’s free and you can probably download it in 20 minutes or half an hour while you continue to browse Facebook and answer your emails. That fast uptake has impacts on organisations across the world when the inevitable bugs hit.
What Can Apple Do?
Let me admit that it appears software QA and testing at Apple has slipped. A major look at how Apple does it and how many resources are devoted to it is probably overdue. Even if it hasn’t actually slipped Apple has a perception problem — people think that software design and quality has slipped and they are talking about it. Alex Kidman might have chosen two bad examples but you can easily find better ones.
To see what better-informed and -educated people say I dropped a thought bomb into a Slack channel full of nothing but people who administer fleets of Apple devices — from a couple of dozen up to literally thousands. They have a perception that Apple software quality is slipping and came up with a number of “show-stopper” bugs in recent releases such as the “discoveryd disaster”, the “great login/lockout problem” and Active Directory integration that had a bug in 10.7, fixed in 10.8, back in 10.9 and not fixed till 10.11.
There is also general agreement with Walt Mossberg who commenting on a story that someone has switched from MacOS to Linux said “I suspect the biggest force keeping stories like this from being more common is that Windows is still worse overall and desktop Linux is still too much of a pain in the ass for most people. But it should be troubling if a lot of people are staying on your OS because everything else is worse, not necessarily because they love it.”
Mossberg also said:
Apple has always been a marketing-driven company, but there’s a balance to be struck. Marketing plays a vital role, but marketing priorities cannot come at significant expense to quality.
I suspect the rapid decline of Apple’s software is a sign that marketing is too high a priority at Apple today: having major new releases every year is clearly impossible for the engineering teams to keep up with while maintaining quality. Maybe it’s an engineering problem, but I suspect not — I doubt that any cohesive engineering team could keep up with these demands and maintain significantly higher quality.
The problem seems to be quite simple: they’re doing too much, with unrealistic deadlines.
So Apple do have a problem.
There is really only one way Apple can fully resolve this problem. If we read “The Mythical Man Month” from cover to cover and take heed of Brooks and his experience the answer is obvious. There is only one thing that Apple can add and that’s time.
Unfortunately it is also the one thing Apple can’t add. We want new versions of OS X, iOS and now for our Apple TV and Apple Watch. We want new Macintosh computers, iPhones and iPads. Apple is also dealing with an entire ecosystem — it must often ship a new version of Mac OS to match new features introduced in iOS.
All of these dictate that software is written on short time scales.
So we come to the core of the question. Why do Apple’s software problems persist? Because the problem is intractable given the constraints. In our consumerist society Apple has to keep on shipping new products at a constant pace — customers and shareholders demand it. At the same time the complexity of the software that ships with them increases with more features and more included apps. We have discussed why none of the obvious solutions won’t work.
There are some things that Apple can do to nibble around the edges of the problem. The biggest would be a large expansion of the testing team so that the software teams get better, earlier and more frequent bug reports from testing. As Schiller admitted, bugs surface faster and affect more people sooner now that the uptake of a new OS is faster across a larger user base.
Apple might also consider giving more weight (and therefore resources) to supporting “enterprise” Mac users and their problems. The Mac system administrators who bear the brunt of these problems are major thought leaders and Mac evangelists and if these people are expressing an opinion that Apple’s software quality is slipping then Apple has a real problem.
In IT support for large organisations we have a way of grading problems, we have an incident scale starting with a major problem, a “Level 1”, down to perhaps “Level 4” which is a minor problem affecting one or two users. Here you can see an example in the table on page two. As you can imagine a “Level 1” was serious stuff — senior management would be informed and it was all hands to the pumps to get it fixed now.
I certainly hope that Apple has something similar to rate the bugs and problems that come into their quality control system from crash reports, “Radar” reports and public comments. I feel they need to rethink both their grading system and their response. The “discoveryd problem”, for example, was bad. Thousands of users across the world suddenly had problems connecting to their printer because
discoveryd was a broken replacement for
mDNS in OS X 10.10, which worked perfectly. When this problem surfaced it should have been a level 1 incident (and this despite it not registering a single crash report) and Apple should have moved heaven and earth ot get either a working
discoveryd or a roll back to
mDNS within a matter of a day or two. Senior engineers should have been chained to desks.
Then we can talk about the problems with integrating Macs with Active Directory. Sure, this affects very few “consumer” customers, it’s only in the enterprise that the problem surfaces and since it’s a problem with the initial bind between the Mac and the enterprise’s Active Directory infrastructure then it’s mainly the Mac system admins who see the problem. But it affected a huge number of Macs across thousands of organisations, and remember those admins are thought leaders and evangelists. Apple don’t want to piss us off but enterprise problems often seem to be ignored at Apple. They need to be higher up the “incident” ladder.
Finally, as someone who has filed a number of Radar reports, Apple could improve the feedback you get. Often it’s just a rote email from the system. Often (even though you’ve searched to see if anyone else has filed the same bug and you can just add a “me too” onto it) it’s a curt email telling you it has been marked as “Duplicate”. Rarely do you get real engineering feedback unless you have access to someone inside Apple who can hurry it along.
Either Radar needs improvement or there needs to be a level above for real admins and developers.
<rant>Dammit, my employers have spent a fortune in time and money to get me top Apple technical certification and paid Developer access but my bug reports go into the same system and get treated the same as a badly written bug report from some lame script kiddie with a free developer account who thinks he’s found a bug when he just can’t write code.
Is There Anything We Can Do?
As consumers there is one thing we can do. We can chill out.
We shouldn’t complain if we do something totally out of the ordinary and the software borks. We shouldn’t complain if we mod the hardware and the software borks. So Alex Kidman is wrong even if there is a real problem.
Imagine some complaints to Holden. “I was driving up my road at 90kmh in reverse and when I hit the brakes the ABS system didn’t work” or “I replaced the gear box in my Commodore with one I bought from Canada over eBay and then a week later when I changed gears the car stopped working”. How far do you think that would fly? This is essentially what Kidman is complaining about.
If we want real progress in Apple’s software quality then we should make real complaints not turn a minor, extreme edge case problems into causes célèbres.
I use a Macintosh computer and an iPhone for hours every day. My Macintosh gets pretty stressed software wise — for example I currently have nine different third party applications running in the background that want to put an icon in my menu bar and another that hides most of those icons until required. It’s now been 25 days, 18 hours and 21 minutes since my computer was last rebooted. It’s probable the reboot was to install a system update rather than a hang. That’s a reliable system.
The truth is that the people responsible for giving us the software on our Apple products do an amazing job. It’s feature rich, mostly well designed and incredibly reliable. They even ship bug fixes at a constant rate. They oversee increasingly feature rich and complex software systems inter-related on multiple platforms under a punishing schedule. It’s not suprising that a problem was found with TouchID — it’s the newest piece of hardware to be integrated into the underlying OS. Personally, I applaud their work.
The second thing we can do is report bugs and report them well. Bug reporting is an art, but an easily learnt one. I’m a really good bug reporter so let me give you a few tips:
- Make sure you are running the latest version of the software.
- Give your bug report a useful heading. Not “It’s broken” but instead “Adding a fourth dongle to the seventh dingle causes software crash”.
- Give all the information. Include all operating system and software versions.
- Make it reproducible. Get the bug down to the simplest form and then document every step to reproduce it.
- Write clearly. Go to the trouble of spell checking and double checking your grammar. It does count.
- Finally, be polite. Sure the bug has lost you a couple of hours work and ruined the rest of your day but right now there is nothing that can be done to fix that and the program team didn’t want that to happen so cursing or insulting people won’t help.
If you want more then Simon Tatham has a fairly well written and expanded version of the above. Read it.
At Last, The Conclusion
To conclude, Apple do have a real problem, albeit one made worse by a perception problem.
For the reasons I have argued it is incredibly difficult for them to improve the quality of the software they write.
There are, however, some things they can do to improve testing, the quality of the software they ship and their response to problems.
We can also help by gaining a sense of perspective on the problems. Complaining about a problem that occurs when we do something rare and totally out of the ordinary might be asking too much. We can also realise how much our software systems do and how reliable they mostly do it. Finally, when we do complain about an error we should do it thorugh proper channels and properly, not just whinge in public.
So we get to the end of my rambling rant. Thank you for reading this far, I thought it important to give an understanding of software complexity and the inherent difficulties as well as talk about just Apple.
Before I leave, if you would like to know more about the complexities and problems of designing and building software and computer hardware let me point you at Brooks book and another.
- The Mythical Man Month: Essays on Software Engineering, Frederick P. Brooks.
The seminal work on software engineering.
- The Soul of A New Machine, Tracy Kidder.
A well written (it won the Pulitzer prize) tale of Data General building their first 32-bit mini-computer in the late 70’s.
Here’s two more general books of interest:-
- Hackers: Heroes of the Computer Revolution, Steven Levy.
Has some great stories that demonstrate what genius programmers and designers can do, including some stuff about Woz and the Apple II.
- Revolution in The Valley: The Insanely Great Story of How the Mac Was Made, Andy Hertzfeld.
By one of my personal gods (my copy is autographed), the story of making the Mac told from the memories of those who did it. You can also read the above (and a bit more) at the website he built, folklore.org.