The myth of code-centricity

Break through productivity barriers with a new software model

1 2 3 Page 2
Page 2 of 3
Table 3. Additional key high-productivity practices
PracticeDescriptionWhy so productive?
ConnectionsA formal element representing an interaction between two components, preferably at the method level for more fine-grained system assembly and higher reuse.Allows the user to "wire up" a system by connecting components as desired, as opposed to components doing it themselves, as in traditional OO design. This allows component interactions to more precisely support desired functionality and much higher reuse. Connection types, such as remote versus local, are now easier to make congruent. The effect is that connections are now first-class elements, alongside objects.
Anonymous collaborationTwo or more parts using each other without knowing about each other, such as with messaging. Requires a mediator, such as a framework. Best done with connections.Suppose Part A uses behavior in Part B. If Part A has a reference to Part B, then you can only reuse Part A if Part B (or anything with the same interface) is present. If Part A instead sends a message that is handled by Part B, then you can reuse Part A without Part B because other parts, without knowing Part B, can handle the message. In short, this greatly enhances loose coupling.
Hierarchical compositionOrganization of parts into a system tree of containers and leaves. Uses the Composite pattern.Allows very intuitive large system understanding, navigation, and management. Lets you assemble the large from the small. Best of all, if you use anonymous collaboration, then reuse is a byproduct of system construction, because you may reuse (harvest) any branch in the system tree as a component.

Voilà! Problem solved via a borrowed solution, system assembly. The solution gets a tentative name and acronym, system imagery (SI), and, just like that, it becomes the long sought after fifth-generation tool (5GT). You can build SI with today's technology, with no pie-in-the-sky promises like the previous fifth-generation contender, AI.

But, first, you may have noticed a flaw in SI: it only works if most software development requires no new code. So far, such a situation has never been achieved. But from my experience, with strict separation of DK from PK, the use of anonymous collaboration (messaging) between parts, building most parts from parts, hierarchical composition of systems, and the use of domain-neutral (J2EE and .Net are not domain neutral) foundational layers, carefully architected collections of components built with PK can be configured with DK to handle a large variety of contexts. This allows new systems to be created with no code, except for the necessary new parts not yet in inventory.

Strategic proof lies in what biology has accomplished with DNA and millions of species. All plants, animals, and bacteria are built with DNA and a mere 20 different amino acids. Using the information in DNA, different arrangements of amino acids are composed into long chains, which are proteins; proteins are arranged into cells; cells are arranged into groups; groups are arranged into larger groups; and so on, all the way up to a species instance. At the abstract level, the DK of DNA defines how to build the system from minimal parts. SI can follow the same strategy of using DK and a reasonably small number of parts to hierarchically construct surprisingly complex systems. This proves that SI's general strategy is valid, though finding the first functional technique will take many iterations.

Until you've designed or used many DK-driven parts using anonymous collaboration, you may have no knowledge of their nature. For example, many applications have multistep procedures like checkout, order entry, questionnaire, or purchase-order approval. DK could specify the order of steps, and a reusable WorkFlow part could manage them. WorkFlow would receive an anonymous message when another part completed its step. It would then determine the next step, if any, and send a message out to start that step. SI's infrastructure makes this reuse scenario easy, compared to the object-oriented development approach. As soon as behavior patterns such as WorkFlow are spotted, they are embodied into high-reuse parts. In this manner, large amounts of intellectual property flow into part inventory and DK, rather than remaining in people's heads or buried deep in application-specific code.

SI: A new development model

SI allows three main specialties in software development:

  1. System assemblers: Using advanced, easy-to-use tools and a vast part vocabulary, users and developers assemble systems in desired domains. Behind the scenes, the tools edit DK. New parts are ordered, if needed. Assembly eventually becomes the dominant activity, taking more than 99 percent of our time. (Assemble systems and assembly are other terms for SI software development, and include system creation, maintenance, and customization.)
  2. Part builders: New base parts are created with PK (code) or composed from old base and composite parts with SI. As each new domain is entered, new parts are needed. But these become fewer and fewer until an asymptote is reached. This asymptote should be quite low, since, for example, we can talk and write about most new domains without creating new English words. Custom part configurators (like property sheets) are needed for some parts, and are built with SI.
  3. Tool builders: Generic tools to assemble systems are built using SI. This is a case of infinite recursion: SI is used to build SI when new SI tools are built using old SI tools. There is a small amount of handcoding in the container framework's domain-neutral layer. We can expect some domain-specific tools.

In SI, coding is minor because only new base parts and the framework's domain-neutral layer is handcoded; the rest of the process involves editing DK with tools. Some automatically generated code -- such as remote stubs, skeletons, part wrappers, database facades, and optimization -- will exist as well.

Gone is the concept of glue code. The original, naive intent of glue code was to stitch together reusable chunks of code with small amounts of finely crafted code. In practice, it takes large amounts of code to achieve this. But the strategy was sound: stick reusables together with something to assemble systems. That role is now played by DK instead of glue code.

DK is data, not logic, so by nature it's more amenable to editing with visual tools in a look-and-choose, WYSIWYG manner. In fact, DK is so much easier to edit with WYSIWYG tools than code that, with today's technology, you can achieve high tool congruence in all domains only if your tools edit DK.

Fair warning: It takes a new mindset to build ultra-high-reuse, configurable software part suites. For example, you must design DK before PK, compose most parts from smaller ones, use anonymous collaboration instead of direct object method calls when coding base parts, and offer remote and local part versions when necessary. This is a whole new world for most developers.

SI has gone beyond a "language," and has surmounted the limiting concept of "language generations." No longer can we think in terms of system LOC or LOC per day. Instead we have a cohesive set of practices implemented as a single technology, presenting a unified face to the user in the form of a realtime, easy-to-use GUI system assembly editor. This is not to be confused with an IDE, because it has no facilities for coding parts, which are developed separately.

To summarize, SI is a true 5GT. Users or developers characterize SI's 5GT using natural mental models to visually understand, assemble, maintain, and customize software systems. There is no coding except when new base components are built; this happens much less frequently than assembly. Since product equals image, we achieve high congruence and expressiveness. This has the clear potential to increase developer productivity as much as any software generation has.

I have more good news: SI empowers all users, not just developers, to become tool builders. (A system you have built is a new tool.) That fact alone has the potential to increase productivity by an order of magnitude. But SI is not a miracle. Complex systems or those requiring tricky standards due to the need to support many users will still need development specialists, with the option of managing or being managed by users who do most of the system assembly. Actually, what we may need most is for users to customize their software to suit their own needs.

The conceptual whole

Pursuit of congruence has led us to seven key practices: components, container framework, standard services, separation of PK from DK, connections, anonymous collaboration, and hierarchical composition.

Now for the next step: merging the practices into the best possible design. This is the hardest step because it requires new abstractions, exploits the multiplier effect, and can be done in a million ways, most of which are wrong. Fortunately, my experience with three generations of experimental system assembly tools (Bean Assembler (BA), Ultra High Reuse (UHR), and Visual Circuit Board (VCB); see Resources) provides a wealth of guidance.

The multiplier effect is the net result of two or more collaborating elements. It is also called leverage or the gestalt whole. With good design, the resulting whole is much greater than the elements working alone. Bad design will result in a modestly greater outcome, or even a result inferior to that achieved by the units working alone.

To maximize the effect of these practices, we must melt them into a conceptual whole that best multiplies the effects of individual practices. The result is a minimum architecture concept map. This map clearly shows the conceptual whole of key practices working together, the roles that we must play, and how we can accomplish SI with architectural simplicity. Figure 1 demonstrates the map.

Figure 1. Key practices as part of the minimum architecture concept map

Let's look at each item in the figure in turn:

  • Components: Labeled Part on the diagram. This provides the PK for the system domain.
  • Container framework: Everything in yellow. The main plug points are the Part and Standard Service interfaces, just as in J2EE. The main difference is that the Part interface has methods for pins and for receiving DK.
  • Standard services: Labeled as such. This concept is identical to J2EE's standard services.
  • Separation of PK from DK: DK is pink, PK is yellow. Note that DK varies the mission of parts, standard services, and the engine, which is all it takes to define a system. Think of DK as the element from which a system emerges.
  • Connections: A link from a part outpin to a part inpin. A part has zero or more inpins and outpins. To keep the diagram simple, outpins and inpins are labeled Pins. A Pin is just like a pin on an electronic part, while a link is like a wire connecting two pins on two different electronic parts.
  • Anonymous collaboration: Done with Message, Pin, and Link using the Command and Observer patterns. SI parts collaborate with other parts anonymously by sending and receiving messages. These messages flow through links defined in system assembly. A message is like a collection of key values, such as a hashtable. A part never knows where a message came from or where it's going.
  • Hierarchical composition: Container and Part using the Composite pattern. A system has a root container. A container has zero or more parts. A part can be a leaf or container, so a system is a tree of parts. Messages flow along the tree's "branches" from part to part.

Plus: Tools are needed to accomplish the practices efficiently. Tools are SI systems created by SI tools, except for the primordial tools where DK was edited by hand.

Very briefly, here's how it works. A system is really just a root container, which contains many parts. Some parts are containers of more parts, so a system is a tree of containers and parts. Parts and the engine use services to do common types of work, such as transactions, persistence, and concurrency management. Parts use other parts indirectly (anonymous collaboration) by sending and receiving messages. A message travels out of a part's outpin, along a link defined by the system assembler, to another part's inpin. Pins can have many links, which means messages are multicast.

To users, SI consists of tools, systems, and parts. They use tools to assemble parts into systems and use systems to do work. The tools edit DK, not code. This lets DK vary the mission of parts, services, and the engine in different reuse cases. That's the real magic -- strict separation of DK from PK, along with anonymous collaboration, let you rearrange or configure the same parts in an infinite number of ways, to build an infinite number of types of systems. All this gives the system assembler incredibly high expressiveness and reuse, which is what makes SI so productive.

You may have a fuzzy conception of how this architecture could work. Figure 2 shows a small example of a system's root container.

Figure 2. A system's root container

The root container shows the topmost view of the entire system with all subelements encapsulated as parts. Figure 2 does not show additional tools such as part inventory, animation, or a part configurator (like a property sheet). The container has four parts, connected with four links. Inpins, such as Read, are left justified; outpins are right justified. Notice how links go from an outpin to an inpin. At the moment, in Figure 2, the user is animating the system to understand its dynamic behavior. A message has left the Start outpin in ThisDevice and traveled to ConfigPart1, which acted internally and then sent a message out of GetConfig. The message is currently paused at the small blue rectangle, which in the tool is on a moving ant line link. The down arrow on Device1 signifies that you can drill down into it because it's a container. The lightning bolts signify pins on which the user can double click to understand or test various behaviors. The ConfigStore part is selected, and could be deleted, copied to the clipboard, stretched to a different size, or dragged to a new location with its links following.

This is merely one possible implementation of the above architecture. It shows that you can use this architecture to design an intuitive SI GUI. It also demonstrates that system assembly is a totally different, higher-level way to work compared to coding. It should also clarify what containers, parts, pins, links, and messages are. This first pass at SI's key aspects will need refinement, but the guiding principle of congruence, the seven key practices, and the above architecture provide a solid initial foundation.

Moving on after decades of code-centricity

The example of SI destroys the myth of code-centricity by providing at least one better alternative. But will the software industry wake up and adopt a major new direction? Sadly enough, history shows that most industries don't. Instead they deny their fundamental problems and continue with head-in-the-sand behavior. It is too soon to tell what will happen in this case.

Related:
1 2 3 Page 2
Page 2 of 3