UHR Generation 2 Guide

11/15/99 - Status is beginning implementation, starting document - Go Back


Overview

UHR is a technology of effects, principles and mechanisms as expressed in the UHR Technology Grid. The closest it comes to a product is a reference implementation. This is the second generation of that implementation, called "Gen2" for short.

Gen2 has great improvements over Gen1 such as no separate kernel, very customizable core, cleaner architecture, elimination of the many optional command interfaces, elimination of use of reflection, suitability for embedded work, and removal of the MessageRouters from Message senders. It is a 100% redesign and rewrite based on the work of Steve Alexander and Jack Harich, plus various other contributors. This implementation does not yet reflect full systhesis with Steve's parallel implementation which is also in progress.

See Downloads for Generation 2.

Summary of UHR

UHR stands for Ultra High Reuse. UHR is a collection of best practices rolled into a carefully thoughtout framework that allows assembly of systems from reusable parts, which greatly increases productivity. UHR has also been called a "framework for frameworks". This is a small open source project.

The three essential elements of UHR are:

  1. Parts - Systems are assembled from highly reusable parts.
  2. Declarative Knowledge (DK) - Tells parts what to do in a reuse case.
  3. Datatrons - Like electrons and electricity, this is what flows between parts.

The outstanding features of UHR leading to higher productivity are:

  1. Assembly of systems from reusable parts is the norm.
  2. Parts are assembled with no code. We use DK instead.
  3. Parts are organized in a standard, easily understood hierarchy.
  4. Editing running systems is the norm. Gone is the wasteful edit, compile, run, stop cycle.
  5. Parts can be assembled from parts.
  6. The system designer starts with a standard framework, not a blank slate.
  7. Totally domain neutral framework. Systems of any kind are possible.
  8. Very small framework of core parts, under 50 classes..
  9. Self referential system. The framework uses itself to run itself and domain parts, eliminating a separate kernel and making core customization easy..
  10. Reuse is a by product since any container in a System Tree is a reusable part.
  11. Part behavior is varied for each reuse case by DK (Declarative Knowledge).
  12. Parts collaborate with Datatrons, not methods.
  13. Service architecture is provided via part and message service parts.
  14. The architecture allows simple, powerful, intuitive Visual Tools.
  15. Systems are optionally customized by users with the Visual Tools.

Getting Started

(This is not yet possible with Gen2 since the implementation is barely started. The current status is only the Minmal Core is done, and subject to probable revision.)

Sample Systems

(later)

Part Inventory

(later)

Implementation Plan

1. Node Structure Layer (done)

2. MinimalCore. Cellular Structure Layer. This takes us to where prototype 2 was and demonstrates the self referential system. (done)

3. LifecycleCore. Lifecycle Layer, partial, no Messages or Params.

4. Datatron Layer, not used yet. Do PropList later when needed. (done)

5. DK Layer, not used yet, do unit test. Use XML, simple at first.. Design Container DK to be flexible, no reflection.

6. DKCore, see details above.

7. Message layer, not used yet.

8. FullCore, see details above. We now have 4 cores and 4 simple regression tests.

------ Convert generation 1 systems -----

Various, lots of work to convert data framework

------ Next are Visual Tools -----
These are part systems. They begin to build our part inventory.

1. MainMenu, System Tree. No file mgt at first.

2. DK Editor, text style.

3. Inspector.

4. SystemTree file mgt. Tricky.

5. DK Editor look and choose, with DTDs or such. Difficult.



Architecture

Architecture is many things to many people. To us it's the choice of key high level abstractions, partitions and their relationships, in that order of importance. The rest is low level design such as component selection, class identification, interface definitions, data structures and the UI.

Rationale

Rationale is the reasoning behind action. We can reduce ours to:

1. Software productivity has huge room for improvement.
2. Reflection shows that most development work should only be done once.
3. Thus the unifying theme for improvement should be reuse.

1. The place to start is reusable parts. (a bit of a leap)
2. The less parts know about each other the greater the reuse.
3. The less parts have to do the greater the reuse.
4. Domain parts cannot do this themselves.
5. Thus domain parts need reusable infrastructure to maximize reuse.

1. The power of an abstraction varies inversely with its domain neutrality.
2. Perceived complexity varies with size more than anything else.
3. Thus infrastructure should be as small and domain neutral as possible.

1. A line in the sand needs to be drawn between what to do and how to do it.
2. Parts should specialize in how to do things.
3. People should specialize in deciding what to do.
4. Thus a medium such as DK should carry what to do to parts that know how to do it.

1. Usually PartA must collaborate with some PartB to get its job done.
2. If PartA knows about PartB then PartA can only be reused with PartB.
3. All forms of collaboration can be expressed as routing data between parties.
4. Thus parts should collaborate anonymously through a medium such as datatrons.

To summarize, we can achieve higher productivity through higher reuse by using reusable infrastructure to assemble reusable parts into systems. People should express their intentions with DK, not code. DK should drive the behavior of reusable parts that collaborate anonymously with datatrons.

This yields 4 abstractions upon which to build UHR:
1. Reusable infrastructure of a minimal and domain neutral nature.
2. Reusable parts that specialize in how to do things given:
3. DK which tell them what to do in this reuse case.
4. Datatrons that parts use to collaborate anonymously.

Now that we've determined our key high level abstractions, what are our key high level partitions? Consider Ockham's Razor, "Entities are not to be multiplied beyond necessity". Ideally our partitions should be the same as our 4 abstractions. But a severe lesson learned from generation one (and examination of other frameworks) was that infrastructure itself quickly becomes the dominant, intractable, limiting aspect. What if we could vanish it into the other three, or morph the other three into the infrastructure? Why must infrastructure be separate from domainness in form?

Indeed it need not be. Taking a cue from life forms, an experiment led to the conclusion that self-referential systems can be built from parts where the infrastructure uses the same 3 partitions (parts, DK, datatrons) that domain behavior does. This vanishes reusable infrastructure as a separate partition. Boom! The separate kernel of generation one is gone. If perceived complexitity of a system varies with the square of the number of partitions, we have just reduced it from 16 to 9.

This yields 3 partitions:
1. Reusable parts.
2. DK.
3. Datatrons.

What really happened to the infrastructure partition? It didn't vanish. It changed from a separate abstraction to an emergent property of the 3 partitions. Emergent properties are highly desirable because they leverage off of existing entities. They cause higher output to input ratios, and can dramatically increase the efficiency of systems.

The final question is what are our key high level relationships between these 3 partitions? Due to the small number and clarity of partitions, this falls into place easily as:

DK ---varies behavior of---> Parts ---which collaborate via---> Datatrons

Architectural Model

This model is the result of the Kernel 2 Project, which culminated in Candidate Architecture 6. The model reflects what was learned from generation one, two prototypes and six architectures, plus frequent communication with Steve Alexander.

Tools are shown as the top layer, but the are really just a domain application built on top of the 3 essential elements. The difference is tools will use core parts far more directly and heavily than most domain parts.

Open Issues

How should we handle separation of part specification DK from mission DK? The former describes in messages, out messages, the mission DK structure, etc. The latter describes only what it takes to vary a part's behavior for a particular reuse mission. A part's Spec DK never changes (except new versions) but Mission DK varies for each mission.

One possibity is associating Part Definition IDs with data about the part, such as Spec DK, change history, use history, searchable attributes, implementations available, etc. This is similar to product model IDs.

One way to handle this is all parts implement a standard interface like:

    public interface Part {
        public String  getPartID();
        public PropMap getPartInfo();
        public void    setPartInfo(PropMap);
    }

For example a PartID might be "org.jcon.inv.io.FileOpener". This looks like a class name, but is really a globally unique ID. The actual class name could be anything.

The PropMap is set for the part by getting the PartID, finding the Spec DK for that PartID, converting the Spec DK to a PropMap property called "Spec", and then calling setPartInfo(PropMap). Additional data can be put in the PropMap by the part or other parts. PartInfo is used at runtime for things like tools editing Part DK, parts querying parts about what they can do, or the designer trying to understand a part.

I shudder to use an interface all parts must implement. A lesson learned from other frameworks is no matter what interfaces they started with in requiring parts to use, these interfaces turned out to be very confining later. Perhaps our solution is a required interface for a single abstraction (ID and related information) and optional interfaces for other abstractions.

(more issues later)

x

x

x

x