I must have first come by this little parable in the 80s and I usually refer to it at least twice a year. Basically it explains the different between Engineers and Computer Scientists. Engineers try to reduce a problem to it most simple form while Computer Scientists will try to solve the a the universal case guaranteeing it solution for all the sub problems. A great way to write a compiler, operating system, or tools, but a terrible way to design embedded systems. Unfortunately I believe that since many Software Engineers take the majority of their classes from the computer science department, that they are tend to think like Computer Scientists.
Anyway so here it is. It is used with permission by Do While Jones. Comments encouraged!
The Breakfast Food Cooker
by Do-While Jones
Once upon a time, in a kingdom not far from here, a king summoned two of his advisors to test them. He showed them both a shiny metal box, with two slots in the top, a control knob, and a lever. He asked his advisors, "What do you think this is?"
One advisor, who happened to be an engineer, answered first. "It is a toaster," he said. The king asked, "How would you design an embedded computer for it?"
The engineer replied, I would use a 4-bit microcontroller to do the job. I would write a simple program that reads the darkness knob and quantizes its position to one of sixteen shades of darkness from snow white to coal black. The program would use that darkness level as the index to a sixteen-element table of initial timer values. Then it would turn on the heating elements and start the timer with the initial value selected from the table. At the end of the time delay, it would turn off the heat and pop the toast. Come back next week and I'll show you a working prototype.
The second advisor, a computer scientist, immediately recognized the danger of such short-sighted thinking. He said, Toasters don't just turn bread into toast, they are also used to warm frozen waffles and pop-tarts. What you see before you is really a Breakfast Food Cooker. As the subjects of your kingdom become more sophisticated, they will demand more capability. They will need a Breakfast Food Cooker that can also cook sausage, fry bacon, and make scrambled eggs. A toaster that only makes toast will soon be obsolete. If we don't look to the future, we will have to completely redesign it in just a few years. With this in mind, we can formulate a more intelligent solution to the problem. First, create a class of Breakfast Foods. Specialize this class into subclasses called Grain Breakfast Foods, Pork Breakfast Foods, and Poultry Breakfast Foods. Each of these classes should inherit properties from the Breakfast Foods class. The specialization process should be repeated with Grain Breakfast Foods divided into Toast, Muffins, Pancakes, and Waffles; Pork Breakfast Foods divided into Sausage, Links, and Bacon; Poultry Breakfast Foods divided into Scrambled Eggs, Hard-Boiled Eggs, Poached Eggs, Fried Eggs, and various Omelet classes. The Ham and Cheese Omelet class is worth special attention because it must inherit characteristics from Pork Breakfast Foods and Dairy Foods, as well as Poultry Breakfast Foods. Thus we see that the problem cannot be properly solved without multiple inheritance. At run time the program must create objects of the proper type and send a message to the object that says, 'Cook yourself.' The semantics of this message depends, of course, on the kind of object, so it has a different meaning to a piece of toast than it does to scrambled eggs. Reviewing the process so far, we see that the Analysis Phase has revealed that the primary requirement is to cook any kind of Breakfast Food. In the Design Phase, we have discovered some derived requirements. Specifically, we need an object-oriented language with multiple inheritance. Of course the user doesn't want the eggs to get cold while the bacon is frying, so concurrent processing is required, too. We must not forget the user interface. The lever that lowers the food lacks versatility, and the darkness knob is confusing. Users won't buy the product unless it has a user-friendly, graphical interface. When the Breakfast Cooker is plugged in, the user should see a cowboy boot on the screen. The user clicks on it, and the message 'Booting UNIX Version 8.3' appears on the screen. (UNIX 8.3 should be out by the time the product gets to the market.) The user can pull down a menu and click on the foods he wants to cook. Having made the wise decision of specifying the software first in the Design Phase, now all that remains is to pick an adequate hardware platform for the Implementation Phase. An Intel 80486 with 64 Megabytes of memory, a 120 Megabyte hard disk, and a VGA monitor should be sufficient. Select a multi-tasking, object-oriented language that supports multiple inheritance and has a built in GUI, and writing the program will be a snap. (Imagine the difficulty we would have had if we had foolishly allowed a hardware-first design strategy to lock us into a 4-bit microcontroller!)
The king had the computer scientist thrown in the moat.
This tongue-in-cheek story exaggerates a basic difference between engineering and computer science. Engineers are trained to make as many simplifying assumptions as possible. They are taught, "Never use a second-order equation when a first-order equation will do." Computer scientists are taught to solve specific problems by considering them to be special cases of a larger, more general problem. Solve the general problem, and all specific instances of the problem are automatically solved.
The computer science approach is reasonable for traditional computer science applications (such as the design of compilers, operating systems, and databases). One can't predict all the possible programs a compiler will be asked to compile, so a compiler has to be designed to handle any general source code. One can't predict how many tasks will need to run at once, or what those tasks will need to do, so operating systems have to be as general as possible. It makes perfect sense to design all peripheral handlers to conform to the same general format. This allows programs to open a peripheral, where "open" has slightly different meanings if the peripheral is a printer, tape drive, or disk drive. There is no way to predict how many keys the user will need to use to access a database, so general access procedures must be provided.
The techniques required for these traditional computer science applications don't work as well for embedded applications. The toaster is one example. A toaster is not a Breakfast Food Cooker. Any attempt to make it one just leads to a product that is over budget, behind schedule, too expensive to sell at a profit, and too confusing to use. When faced with a difficult problem, the proper approach is to try to make the problem simpler, not more complicated.
I'm not against planning for the future. Some thought should be given to future expansion of capability. But when the entire design process gets bogged down in an attempt to satisfy future requirements that may never materialize, then it is time to stop and see if there isn't a simpler way to solve the immediate problem.