| By William Paul Fiefer (home) |
|
What's New, Spring 2000
|
| Current | New by season | New by subject |
|
Joy Division
(m.s.b) What catches people short as they select a programming language to do this are the conventions of syntax. The symbols seem familiar. But the computer wants hard-to-remember instructions. They are not even as good or clear as the little programs called recipes that you find in The Joy of Cooking. Hard-to-remember, however, is not mysterious. It is just hard-to-remember. In the early years of software development, when computing power was limited and expensive, the instructions needed to be easy on the machine, which usually meant they were hard on the human beings. The tradeoff was acceptable because machine-time costed more than people-time. The languages created then persist today even though now the machines are cheaper than the people. The legacy is that your program will crash if you use a period where a semicolon belongs, or when you ask for Sara's record where you want Sarah's. Experienced programmers navigate these shoals by defensively coding their systems to quickly isolate unorthodox uses of syntax and strange user inputs. Novice programers must trawl through yards of code for the flyspeck that is making their routines explode. Adhering to syntax means that (Which representation is best, if any? The moment of thought spent on this is a moment spent thinking like a language designer. This is the joy of lex.) Such specificity of expression is alien to the ambiguous reality of how life is lived. Yet it is the only way to produce symbols that control a machine. To tell a machine to perform a particular task you must say it precisely the same way each time. With a little keyboard practice, however, the obscurities of the language dissolve and the properties of programming begin to emerge. As you cross this threshold, the expressive power becomes incredible. You sense that syntax is not programming any more than reciting a chocolate almond shell recipe makes a batch of cookies. The bit, for example, is the architectural fundamental of software just as the electron is for hardware and the molecule is for the packaging of your workstation. The bit, the one or zero, is indivisible software machine code. In programming, you move quickly from thinking in bits to thinking in larger aggregations like instructions, procedures, interfaces, the operations they represent, and the strategic business operations that depend on this code. You climb and descend this tower frequently, coalescing multiple aggregations into new representations to accomplish new tasks. Good programmers are exceptionally nimble and fast as they traffic in these constructions. At each layer, you work with the language in less, or more, granular abstractions. At one extreme is the bit; at the other the familiar concepts of user preferences, customer traits, and business models. Good languages support it all and the masterwork is to realize this structure inside a machine. This mind-boggling, elastic quality is the heart of programming. It is the reason you can truthfully assert that programming languages and activities are internally consistent abstractions erected over machine code. The only other disciplines that beckon you to cross abstraction barriers at these orders of magnitude are mathematics, which begins with the numeral, and music, where you think down to the note, up to Beethoven's Ninth, and out to the majestic ideas this symphony represents. [header] | [seasons - subjects] Next breath
(m.s.b) [header] | [seasons - subjects] Heavy Rotation
(beef!; a version of
this article appeared in volume 1, issue 15, of the ACM
magazine Ubiquity
.)
NASA produces a class of software known as "hard real-time." Real-time software responds interactively to its environment, which it monitors through sensors. The speed of the response is critical, and the fact that it is called "real-time" should clue you to the deadline of the expected response. Hard real-time software takes this concept to the extreme the software is guaranteed not to fail. The software controlling the robots on an assembly line is typical hard real-time code: if a robot miscalculates its response, it might fail to bolt an engine to its frame. An anti-ballistic missile shield is another example, as is a spacecraft landing-control system. In each case, a failure scrubs everything. It makes sense not to stress faster-better-cheaper under real-time conditions and NASA's original decision to proceed otherwise under hard real-time conditions was a lethal analytic blunder. This was, after all, rocket science. Business software is different. Contrary to the blink-of-an-eye combat and sports analogies touted by executives and consultants, business proceeds at a leisurely pace relative to the processing speed of a computer. The best business software is produced at low cost and discarded quickly as new revisions and better competitive versions appear. The worst business software (a) requires a long development cycle, which increases the odds of it referencing an outdated environment and delivering outdated responses to that environment, and (b) is so expensive that its users have disincentives to dumping it for something better. Unless a business is in a mature, static environment, long development cycles and expensive code expose it to the risk of running products that produce irrelevant results. A program that takes 20 months to build, for example, encapsulates a nearly two-year-old model of how the business works. A business within a dynamic, rapidly changing environment may malfunction when it consumes and acts on the output of this stale product. The worst casualty of long and expensive cycles, however, is the lost future value from improvements and innovations not undertaken because the code base costs too much to change. Fresh code is better code, but surely all of this upgrading and replacement will frustrate and antagonize the users. Here, too, the assumption is wrong. Churning the code base to make it better need not disrupt its end users. They won't even know it is happening. How? Contemporary software design emphasizes a modular construction where the various modules communicate using a standardized, stable vocabulary called an "API" (application programming interface; the software is the "application" and the vocabulary is the "programming interface"). The care that programmers apply to creating this vocabulary when they initially design a piece of software corresponds closely to the final quality of that software. (See Better Than The Real Thing for the softer side of APIs.) The chief feature of this design style is that it isolates programmers working on one part of the software from changes made by other programmers working elsewhere in the software. If one module requires a "sort," for example, regardless of how programmers implement that sort and regardless of how often they modify the sort procedure, any call to the sort module will work fine. The calling modules never deal directly with the changed code; they deal only at the level of asking for a sort. A short way of describing this chief feature is to say that an API tightly controls the degree of abstraction needed to use the software. Asking for a "sort" serves as a semantic barrier, eliminating the need to specify, in many words, the exact details of conducting a sort. This is a very powerful idea. An extension of this chief feature is that these abstractions can be grouped into higher level abstractions. Good APIs are built of small elements that compound. A word processor, for example, might have an API that lets someone "open" a file, "add" to its contents, "save" the additions, and "close" the file. These little elements easily compound to a larger "edit" function. When a programmer requests an edit, they save the time and space needed to say "Open the file, add to it, save it, and close it." APIs are not only efficient, they are extensible as well: when entirely new procedures are required, a term is simply added to the API vocabulary. If the software is designed with a final layer of abstraction at the level corresponding to the interface where users interact with it, then any changes taking place below this layer are transparent to, and do not disturb, the end user. This top-layer API vocabulary is sweetest when its collection of terms closely mirrors those used by the business practitioners. At that level, its compounded elements are often referred to as "objects." Using these concepts in an organization allows rapid innovation to occur below a more stable layer of behavioral API terms. All the users ever experience is the active vocabulary of the organization as expressed by the software they use ("Click here," "If this is what you want, select 'Yes,'" and so forth). Below this abstraction layer, the procedures the business logic quickly adapts to a rapidly changing environment. Business software is a commodity that must be produced fast and at low cost, modified frequently, and trashed quickly as situations change. Full-featured scripting languages such as Python, as opposed to compiled and quasi-compiled languages such as Java, are ideal for this heavy rotation production because they allow rapid, robust software development by less skilled (less expensive) programmers. This all can be accomplished without disturbing the smooth operation of the business. And none of it takes a rocket scientist to accomplish. [header] | [seasons - subjects] Better Than The Real Thing
(m.s.b) When you talk to your cooking pals to tell them what you are doing, you say "I am making raisin bread stuffing" or "I am separating an egg to glaze my crust" in lieu of providing details of how you accomplish these tasks. You hide the details of what you do behind a vocabulary that serves as a shorthand. You do this all the time in every aspect of your life. You tell a florist to "deliver" roses to beef! at the Uberweiss Dairy. You tell an associate to "clip" all newspaper articles referring to chocolate and cashews. You do not tell the florist which vehicle to drive and the route to travel. You do not tell your associate how to use scissors. These little terms shield you from describing how you want the people working with you to do what you want done. You suppress detail. In most cases, you do not even know how things get done. You tell a carpenter to "add a dormer" to the garage and you tell a doctor to "splint" an injured finger and trust them to get it right. The sophistication of your mental world is reflected by the degree to which you abstract and then knit elemental ideas into a tapestry of large, complex ideas. These abstractions are convenient. They are the APIs, the application programming interfaces, of our lives. In agreeing on common definitions for the pieces of our world we save lots of time that otherwise would be spent repeating the same mundane details to everyone describing what "baking" is, for example, when we chat about it, rather than just saying "I am baking apricot coffee cake this Sunday. Care to stop over for some?" Most usefully, these abstractions allow for easy improvement and innovation. By hiding what is really going on behind the handle of a term, we can change how we do what the term refers to without invalidating that term. A "car" today is different from what it was 50 years ago but we still call it a car. Sally's Flower Shop can "deliver" flowers one way, say with her spiffy Lexus coupe, and Joe's Flower Shop can deliver them another way, say with his antique Model-T. It's all a delivery, just the same. Improvement and innovation occur by reimplementing, compounding, and extending our collection of terms. Nobody needs to reinvent the vocabulary to change things. This is better than sliced bread. Happiness! [header] | [seasons - subjects] Good Vibrations
(m.s.b)
|