This consists of the introductory sections from a much longer document with the same title. The longer document describes a multitasking executive called TaskMaster and a set of Objective-C syntactic extensions, `action expressions', that provide source-level support for TaskMaster's exception handling and lightweight multiprocessing extensions .
The companion papers, Planning the Software Industrial Revolution[27][[??]] and There is a Silver Bullet[28] describe the longer-range vision behind this work. These papers characterize the software crisis as an obstacle to moving from the Age of Manufacturing to the Age of Information, where computers become everyman's personal vehicle into a global information network, the Model T Ford of the Information Age. They see the software crisis as being solved as the telephone operator shortage was once solved, by making every computer user a `programmer'.
Of course, programmer will not mean what it does today. The word will acquire many different meanings appropriate to the skills and interests of diverse classes of users at different levels of a software architecture that is as heterogeneous as the architecture of everyday objects such as computer hardware. For example, consider three `programmers' of entirely different skills and interest sets; Tom, Dick, and Harry:
Tom is a programmer in the C++ sense of this word. Tom plays the role that silicon fabrication companies play in hardware, fabricating gate- and block-level silicon components into chip-level components that others with less specialized skills, such as Dick, can use. Gate- and block-level technologies, whether in hardware or software, are tightly-coupled activities in which optimization of the product, not their developer, is paramount.
Dick is an programmer in the Smalltalk or Objective-C sense of the word. Dick plays the role that board vendors play in hardware, assembling chip-level components that Tom produces into card-level components that others with even less specialized skills, such as Harry, can use. Chip-level technologies, whether in hardware or software, are loosely-coupled activities in which developer concerns such as pluggability, interchangeability, and reusability are paramount. Chip-level technologies support that crucial demarcation between tightly coupled fabrication technologies that only highly-skilled specialists use, such as silicon foundries, and the much simpler, loosely-coupled assembly technologies that non-specialists can use, such as screwdrivers and soldering irons.
Harry is an end user, one of `the rest of us'. Harry is a problem-domain expert with no specialized software expertise at all. The goal of the architecture to be discussed in this paper is to make Harry a `card-level programmer' in precisely that limited but nonetheless very real sense that end-users are card-level hardware designers when they choose which cards they'll buy to customize a personal computer.
Harry might be a clerk in an insurance office, a manager of a bank branch office, or in the following example, a homeowner using a personal computer to manage household finances. Today, Harry might be using an off-the-shelf personal finance program like ManagingYourMoney (MYM) on the Macintosh[29]. Such programs let Harry manage his assets, liabilities, income, and expenses to provide an instantaneous reading of net personal worth. What today's programs and systems do not do is to help this class of users build their own custom solutions to their problem-specific needs. The Macintosh does not support end-user programming.
For example, suppose that some of Harry's assets are in stocks, bonds and mutual funds, whose contribution to net worth varies daily. When Harry tires of typing stock prices from the newspaper he might venture into the Information Age by programming his terminal emulator to acquire price information from an information service like Compuserve electronically. Although Harry unlikely to ever program in C or even Smalltalk, he might well reach the point of using a spreadsheet such as Excel to manage a database of price trends over time, perhaps using Excel's charting facilities to show trends graphically. Today's non-programmable solutions are adequate only so long as Harry remains persuaded that all this mousing around[[??]] to open and close documents, start and stop applications, and cut and paste numbers is a major improvement over typing each number manually If Harry should insist on a way to build his own application to compute, with a single click, a graph of his personal net worth as it changes over time, his desires have exceeded what the Macintosh in particular, and the software industry as a whole, can deliver today.
The solution envisioned in this document is shown in Figure 1.
Figure 1: A
program as might be created by an end-user, written in an iconic non-procedural card-level
object-oriented `programming language' of the type envisioned in this document.
This figure is composed of Macintosh icons and screen dumps to imply that each icon behaves individually much as on the Macintosh today. However there are significant differences. The picture is not a collection of what-you-see-is-all-you-get icons that can only be used manually, and (except for manual cut and paste) individually. The figure is the `source listing' of a `program' that Harry has `written' in an iconic card-level `object-oriented programming language', whose `objects' are based on the lightweight multi-tasking facilities of this paper.
The icons represent lightweight tasks, or card-level objects. Harry might save his `Compute Net Worth' program as an new card-level component and use it alongside those shown here. However Harry didn't build the ones shown in this figure. He purchased them elsewhere, from Dick, who assembled them from chip-level components fabricated by Tom.
The tasks are initially inactive, each awaiting input on the incoming arrows. When the `Compute Net Worth' button (on another screen not shown here) is clicked, this produces the signal that the terminal emulator icon is waiting for. This triggers the task that the terminal emulator icon controls, which might be a card-level incarnation of a program like SmartComII, to dial the telephone, log into Compuserve, and type commands to download financial information.
The three string search icons are Harry's way of dealing with the fact that Compuserve does not provide financial information in a format that his spreadsheet can accept. He used a stream splitter process (the small black circle) to send the data to three string search processes, and has programmed these to find specific stock prices and format them as the three history spreadsheets expect. And so forth...
Unix programmers will recognize this as a variation on the pipes and filters scheme of Unix. But there is one big difference that my use of familiar Macintosh programs does not bring out clearly. Unlike Unix pipes that can only carry streams of bytes, the arrows in this figure can carry streams of chip-level objects. Unlike Macintosh spreadsheets that only accept text, the programs in this figure are written to accept data expressed as objects.
Objects can represent any structured data-type, including pointer-based structures like lists and trees. The arrow representing the input stream to the spread sheet icon need not be tab-delimited strings that the spreadsheet must parse and reformat internally. The arrow to the spreadsheet object could carry a stream of objects, instances of class Record, not a tab-delimited character stream as spreadsheets require today.
This document will use that fashionable but poorly understood buzzword, `object', with precisely the looseness of meaning this word has in hardware. That is, object will carry no technical meaning whatsoever, unless qualified to make the architectural context clear. Just as a gate-level hardware object has nothing in common with a chip-, card-, or rack-level hardware object, so it will be with the diverse software `objects' in the multilevel software architecture.
The architecture was motivated by appreciation for the multilevel architectures of hardware engineering, where high-level hardware objects such as office equipment are built from lower-level objects such as cards, card-level objects from lower-level objects such as silicon chips, and chip-level objects from lower-level objects such as silicon blocks and gates. It expects that the solution to the software crisis will evolve as it did in hardware, by stratifying users/programmers according to skill levels and interests, just as the plumbing supply market is stratified into homeowner, plumbers, retail outlets, factories, refineries, and mines.
End users, such as Harry, will use simplified modularity/binding technologies sufficient for limited categories of problems, such as the card-level objects described here. They will acquire the needed objects by subcontracting the work to more specialized lower level workers such as Tom and Dick. Figure 2 shows the five levels of this architecture. Although the `objects' at every level meet the classic definition of objects as inseparable units of state and behavior, the modularity/binding mechanisms by which this is accomplished is totally diverse at the different levels:
Figure 2: Object-oriented
means different things at different levels of integration. Pie slices represent the
extent to which popular languages support work at each software architectural level.
The figure shows that C++, unlike Ada, provides limited support for chip-level programming in its virtual function mechanism, a form of dynamic binding. C++'s support for loose coupling is limited by its emphasis on tight-coupling, inheritance-based compile-time type-checking and static binding.
Just as in hardware, what distinguishes chip-level modularity from gate- or block-level modularity is loose coupling, dynamic binding, or pluggability. Whereas gate and block-level technologies are fabrication technologies; ways of fabricating things from first principles, chip- and higher-level technologies are assembly technologies; ways of assembling things by plugging together off-the-shelf components from libraries of ready to use parts.
None of these levels are panaceas that eliminate the need for other levels. On the scale of any significant system, gate-, block-, and even chip-level objects are extremely small units of granularity--grains of sand where bricks are needed. But the rack-level modularity of operating systems like Macintosh and Unix go too far in the opposite direction. The rigorous encapsulation that makes rack-level modularity so useful for packaging software packages as independent programs, obstructs the free interchange of information between these objects so rigorously that end-user programming is not possible. Card-level modularity provides a middle ground, intermediate between the tightly encapsulated rack-level objects of operating systems like Unix and the chip-level objects of programming languages like Smalltalk.
The relationship between Fabrik[30] and Smalltalk is an excellent example of how card-level objects relate to lower-level objects. Fabrik was written in Smalltalk, so it consists internally of chip-level objects. Smalltalk programmers manipulate them via the Smalltalk programming language; a textual object-oriented user interface appropriate to software specialists like Dick.
Fabrik projects a higher-level kind of object onto the user interface; a `card-level' object. Non-programmers manipulate these via Fabrik's iconic user interface, which is a non-textual programming language suited to non-specialists like Harry. From Harry's perspective, these new objects are intuitively appealing for they are amenable to the reasoning skills of everyday life. They communicate, not synchronously through procedural invocation (something that only programmers find natural), but by an asynchronous model that is more closely related to how the familiar objects of everyday experience behave.
Card-level objects encapsulate a copy of the machine's thread of control on a software card, alongside the chip-level objects used to build that card. They are objects of the sort that programmers call lightweight processes; objects that operate as coroutines of one another, not subroutines. They communicate asynchronously by sending chip-level objects through communication channel objects such as streams.
Since software cards appear to run concurrently, their user interface is uniquely intuitive. For this reason alone, they are objects in a far more fundamental sense than the procedural, single-threaded languages of today. Like the tangible objects of everyday experience, card-level objects provide their own thread of control internally, they don't communicate by procedural invocation, they don't support inheritance, and their user interface is iconic, not textual.
Card-level objects are similar to Unix pipes and filters. They share the same non-procedural notion of concurrent processes communicating through asynchronous communication channel objects, or pipes. They differ in that card-level objects are lightweight processes. They share a common address space and are therefore not restricted to communicating value streams, or bytes. The streams between them can be reference streams that may contain embedded pointers such as linked lists or trees. Whereas pipes only carry bytes, streams can carry objects.
Metaphor[31] is an related example with significant differences. Fabrik and Metaphor are similar in that both support an iconic programming language oriented towards non-programmers. Both are based on a non-procedural bubbles and arrows programming paradigm like the Unix pipes and filters paradigm. Both differ from Unix in that the bubbles can exchange reference streams (pointer-based structures) such as objects, rather than only value-streams as with Unix pipes.
The significant difference is the absence of the open architecture that Fabrik acquires from being based on an open standard like Smalltalk.
I understand that internal coding standards do exist whereby Metaphor's card-level objects communicate by a tabular representation oriented towards spreadsheet data. I understand that Metaphor now views this representation as an obstacle to continued growth, presumably because difficulty of forcing non-tabular data that occasionally recurs in customer applications to fit within Metaphor's tabular data model. I understand that relieving this and other barriers, such as non-portability, is the motivation for the recent Metaphor/IBM joint venture; Patriot Partners.
The multi-layered approach advocated in this document addresses the problems that Metaphor encountered by trying to represent all lower-level data structures with a single closed standard representation for tabular data. A chip-level object technology like Objective-C provides an open-ended standard for representing structured data. They allow programmers to develop new data representations by defining new classes of objects, using object-oriented features like encapsulation, inheritance and polymorphism. The languages are supported by state of the art programming tools like browsers and by comprehensive libraries of trust-worthy, ready-to-use, pre-tested classes. Since chip-level objects are, by definition, loosely-coupled, pluggable, polymorphic and dynamically type-checked, newly-created objects can be immediately recognized and processed by pre-existing applications without having to recompile or otherwise modify the applications.
Stepstone's experience with Objective-C is a final example of why a multilevel software architecture is desirable. Whereas Metaphor's experience shows that skilled programmers need lower-level architectural standards than Metaphor's card-level objects, Stepstone's experience shows that users need higher-level kinds of objects than the textual, synchronous objects of Objective-C; objects that communicate by sending each other messages where the receiver computes as a subroutine of the sender, rather than as a coroutine.
The key concepts that distinguish higher-level user-programmable systems from the specialized programming languages of today, of which Objective-C is a typical example, are an iconic user interfaces (instead of a textual programming language) and concurrent (asynchronous, non-procedural) objects that operate as coroutines of one another, not subroutines.
Stepstone has not taken, and is unlikely to take, the final step of building user-programmable systems ourselves. We see our role as the provider of horizontal components that customers will use to build vertical end-user solutions.
These libraries are based on Objective-C, which Stepstone also markets as the enabling loosely-coupled chip-level binding technology for providing large class libraries that are sufficiently loosely-coupled to their environment that they can be used in diverse customer applications. Objective-C is a hybrid object-oriented programming language that supports the Smalltalk chip-level object model as a strictly upwards-compatible extension to the gate- and block-level objects of a conventional programming language like C or C++:
Stepstone does not view itself as primarily a language vendor even though one of its most popular products is a compiler for the Objective-C programming language. Stepstone is a software components vendor, with the language as enabling technology for gluing components together. Objective-C does not compete with other popular programming languages, whether they be C, Ada, Smalltalk, C++, or the Unix shell. Objective-C is an extension to C.
Insofar as C++ is a better C, it provides even stronger and more tightly-coupled gate- and block-level software fabrication technologies than predecessors such as C. Loosely coupled assembly technologies can easily be added as extensions; notably the chip-level technologies of Objective-C and the card-level technologies of TaskMaster.
So much for the destination. The rest of this document is a tour of a vehicle for going there, from stateroom to boiler-room. It will show how user programmable card-level systems can be assembled from chip-level software components of Objective-C, and these from the gate- and block-level technologies of C or C++. Since the presentation will be progressively narrower and more technical from here on, those uninterested in boiler-room matters may wish to refer the more technical portions to a specialist.
[27] Brad Cox; IEEE Software; November 1990
[28] Brad Cox; Byte magazine; October 199
[29] I chose this example because of personal experience. Although my programming skills are like Tom's and Dick's in other programming environments, I am like Harry on the Macintosh. If the Macintosh provides any solution to the example in this section, the solution has proven inaccessible to me, and by extension, to the Harrys of this world.
[30] Dan Ingalls, Scott Wallace, Yu-Ying Chow, Frank Ludolph, Ken Doyle; "Fabrik; A Visual Programming Environment"; OOPSLA `88 Proceedings.
[31] Metaphor is a office automation product of Metaphor Computer Systems; Mountain View, CA. Since I have only limited access to information about this system, this section may contain errors of misunderstanding. I believe that is essentially accurate with respect to Metaphor's philosophy and architecture, but potentially inaccurate with respect to its implementation.