Return to Kinexis Home Page
 

 
Intermediary Objects for Transactional Systems: Introducing "Proposals" 

by John Tibbetts and Barbara Bernstein 

Object Magazine, November 1997 



With Proposals as mediators between front-end consumers and back-end domain objects, the possibilities for reuse improve dramatically 


 
     Of the many benefits of an object approach, probably none has been more attractive to developers of commercial applications than reuse. Clearly, the more code that can be recycled, the more development time can be saved, the more risks avoided, and the more efficient the whole application-writing process becomes. 
     Object insights have made significant inroads into the world of commercial applications in the last 5 or 7 years, often with very beneficial results.  And yet, we have been puzzled to observe that the record on reuse has been spotty at best. The massive, end-to-end automation of business application development that we expected has not materialized. 
 
Where’s The Reuse? 

     There is reasonable reuse of domain objects in the back and of UI gadgets at the front. Yet at the heart of the development job, at that stage devoted to creating the so-called application itself, reusable objects are virtually non-existent. These application middles are written as they always have been—on a case-by-case basis, almost entirely from scratch. Even a commonplace activity like relating master records to their detail records gets programmed anew for every new application. 
     The problem stems from a fundamental lack of clarity about what should happen in the stretch of an application that is called "businesss rules," "application logic," or "transactions."  The multiplicity of names is a tip-off that we lack a crisp undersanding of what the proper job is here. Conventional architectures leave it to individual designers and developers to bridge from UI to database in whatever idiosyncratic, opportunistic ways they can come up with. 

 

     No wonder these middle regions have resisted abstraction and re-use. Object modeling done here has missed the mark because it has tried to model a misconception, or at least a serious imprecision.We introduce here a more promising way of thinking in object terms about the central portions of transactional applications, and discuss our experiences in implementing an architecture based on this insight. 
 
What’s In A Name? 

     Object technology teaches the importance of accurate names that reflect clearly-delimited responsibilities, and this is what we have come up with:  The application middle is the region where proposed changes to enterprise resources are assembled. It is where transactional requests take shape, in a tentative and provisional form, before they are finally submitted to the back-end database manager or TP monitor. 
     The appropriate object here is something we call a Proposal. It encapsulates is all state and behavior associated with a given transaction-in-formation. Using this crisp name and clear role for the territory between front end and back end, as we hope to demonstrate in this article, brings the entire application design dramatically into focus. 
 

Proposal Philosophy
 
     As we see it, the Proposal object sits in the center of a transactional application and acts as broker between the consumer at the front end (usually, but not necessarily, a human user) and the back-end resources that the consumer seeks to update. 
     Conventional transactional technology uses intricate programming to put these two parties in direct touch with one another, but a Proposal separates them and interposes itself as mediator. Developers no longer hard-wire UI to database manager in huge, monolithic, front-to-back applications. Users no longer engage in real-time transactional “sessions” with the back-end software. 
     Proposals opens up a space between UI and database manager where reusable infrastructure, generic navigational intelligence, and flexible interfaces to both back and front can live. 
 
Proposal Objects vs. Domain Objects 

     In the human world, a proposal—to buy a house, get married, do a certain job for a certain fee—is a necessary step between mulling something over and signing an iron-clad contract.  Proposals are how deals gets shaped. They tend to be tentative, negotiable, and probably not perfect right off the bat.  They may go through multiple versions.  And every proposal eventually reaches a point where it either turns into a contract or is abandoned. 
     A Proposal object serves a similar function in hammering out the transactional “contract.” It encapsulates the process of assembling a request for a change in enterprise resources. Since it is a “thing” and not an “activity,” it can be long-lived.  It can be worked on over time, passed from one user to another, rolled back to previous versions, firmed up as it moves through the organization, and tried out against the back-end resource manager multiple times until it “takes.” 
     Contrast Proposal characteristics with those of its more straight-laced cousin, the domain object. A domain object strives to be complete, synchronized, and 100% correct.  A Proposal object, by contrast, can tolerate erroneous, provisional and incomplete information. It is tentative rather than definitive, remember: a proposal, not a contract. 
 
Adding Proposal Space to Transactional Apps 

     Proposals revolutionize both the building and the use of transactional applications. On the building side, they provide developers with a great deal of reusable infrastructure.  Much of the code that now has to be done from scratch for every new type of application comes built in to the Proposal framework, ready to be picked up and used. 
     For starters, a Proposal takes over the job of mapping front-end input to back-end data structure. It contains an intelligent hierarchic framework that lets the programmer assign each field or group of fields to a certain level in the hierarchy.  The transactional request gets structured automatically, with Proposal fields automatically and rigorously mapped to domain fields. 
     Also “at no extra cost” to the developer, a Proposal provides advanced transaction-forming behaviors such as document navigation, error- and annotation-handling, versioning, and archiving. As a reusable object, it can implement features that would be too expensive to program into an individual application. 
     Since a Proposal is free-standing and disconnectable, it acts as a kind of universal connector. It can interact with a variety of front-ends, then turn around and interact with a variety of back ends. It well accommodates the increasing need to support various new front-end technologies. In fact, with front and back decoupled, most kinds of changes can be accomplished with localized programming rather than sweeping, application-wide rewrites. 
     Applications built according to a Proposal-based architecture make more effective use of both humans and computers. They model the way humans actually work— collaboratively, sporadically, sometimes on-line and sometimes off. Proposals represent a kind of a staging area for information where errors are not fatal and incompletions can be filled in later. And they increase the usefulness of computers as tools. Where current technology kicks in only at the end of what can be a long, collaborative, start-and-stop process that has to be assembled on paper and routed through the organization by people walking from desk to desk, Proposals get the computer involved from the beginning. For example, a new-hire procedure could start on the day a resume arrives, follow an applicant through the interview/background check/skills test process, and finally, if all goes well, turn into a formal AddEmployee request to the HR database. 
 

Proposal Implementation
 
Having sketched out a theory of Proposal objects, we now report briefly on our own experience building a Java-based framework to implement a Proposal-based architecture.  While what we describe below is not the only way to design and built a system that features intermediary transactional objects, it seems to us the approach that offers, among other things, maximum reuse benefits. 

 Where Does a Proposal Live? 

     Proposals are not tied to any specific platform, tier, or machine. They move freely; in fact, they can change location on a moment-to-moment basis.  Proposals add a mobile element to systems where every other process is fixed in place. The front end has to be near the user, the back end has to be near the data, but a Proposal can be placed sometimes close to the front, sometimes close to the back, or anywhere in between. 
     In a client/server interaction, the Proposal would typically reside either on the client (fat client) or the server (thin client). In a three-tier system, it would probably occupy the middle tier. In a monolithic system, it would sit between user and data on the mainframe. Again, these are typical arrangements, but there is nothing imperative about them. 

What Are Proposal Responsibilities? 

To accomplish its job, a Proposal object must assume responsibility for keeping its own metadata and data, and for many navigational, organizational, and interfacing chores.  We have come up with the following: 

    1. Knowing its own specification 
    2. Acting as a container for proposal data 
    3. Keeping versions of itself 
    4. Retaining and tracking errors 
    5. Holding annotations 
    6. Protecting against stale data 
    7. Interacting with the back-end server 
    8. Interacting with consumers
As with any object, responsibilities are implemented by means of State and Behavior.  In the section that follows, we build up a picture of a Proposal object by describing (very superficially; in some cases, a behavior like Navigate might involve several classes and dozens of methods) these responsibilities along with the relevant State and Behavior. 
 

1. Know Its Own Specification

The first responsibility of  a Proposal is to hold developer-supplied metadata that makes it a NewHire Proposal, a ShipProduct Proposal, a DebitAccount Proposal, or whatever. 
     Metadata resides in what we call the PropSpec (short for Proposal Specification), the developer-customized template for a specific Proposal type (there is a NewHire PropSpec, a ShipProduct PropSpec, etc.). The PropSpec contains: 
  •  Field definitions (name, type, size, description, default value)
  •  Field consolidation into fieldGroups (which fields aggregate; which are key)
  •  FieldGroup inter-relationships (parent-child or peer-peer relationships; whether   groups are required or optional)
  •  Definitions of “Assumptions” used to detect and handle stale data
  •  Any special processing, in the form of Java code.
State: Metadata, the PropSpec itself 
Behavior: Create builds PropSpec metadata from adapter input 
                 Access allows outside objects access to internal metadata 
 

2.  Act as a Container for Proposal Data

Once a PropSpec has been created, it becomes possible to instantiate Proposals based on that pattern.  Each of these Proposals can be used as a container for specific data related to a particular new hire (John Smith, born 6/9/64, attended Rutgers), a particular shipment (Shipment # 37702, leaving 3/3/97 from Long Beach pier 73), etc. 

Data can be saved in any partially-completed form.  Hierarchic navigation through the data, a sort of “page-turning” through a complex document, comes built in, thanks to the hierarchic “map” contained within the PropSpec. Users move through and interact with the data in standardized ways. 

State: Proposal Data, the hierarchic collection of end-user supplied data 
Methods: Access allows outside objects access to Proposal data 
                 Navigate supports movement through the Proposal hierarchy 
                 Mutate performs reasonable data re-organization when metadata is changed 
 

3.  Keep Versions of Itself

The Proposal maintains a record of every change made to it, down to field-level granularity. With this Version list in place, a Proposal can undo actions that have already been accepted, then redo previously-undone actions. Combining undo and redo operations, a user can scroll back and forth through previous versions of the Proposal to check something in an earlier version, to recover from a mistake, or to return to the most productive point from which to continue. 
     Versioning also enables auditing. Since a Proposal may pass among numerous parties during its life span, it is useful to be able to review exactly what changes were made when and by whom. All versions are retained for the life of the Proposal, or until explicitly disposed of. 

State: Versions, each containing a summary of changed data, time of change, person making change, etc. 
Behavior: Undo/Redo 
 

4.  Retain and Track Errors

In a conventional transactional system, incorrect or incomplete data will usually not even make it through the user interface, and may terminate the transactional conversation. But a Proposal, being provisional, can accept erroneous or incomplete data, flag it as such, and monitor it for fix-up at a later time All errors must be eliminated before the Proposal turns into a formal transactional submission. 
     Any number of error-messages can be associated with any Proposal element down to field level. Error notices persist across sessions and across locales; they travel with the Proposal.Our Proposal infrastructure includes an error-search mechanism that makes sure all errors are resolved prior to submission. 
     Error messages are most often added at data entry, but  they can also be set by an external “review agent” or by the back-end process when a commit fails. 

State:  Error Messages and what parts of the Proposal they are associated with 
Behavior:  Error Management involves searching for, locating, and summarizing errors 
 

5.  Hold Annotations

User-written notations can be “stuck” to any field or fieldGroup.  Annotations signal work to be performed, ask questions, note problems, give instructions, provide explanations, make comments, etc. They are an important facilitator of collaborative Proposal preparation. 
     Any number of Annotations can be associated with any Proposal element.  As with Errors, Annotations can be externally manipulated and scanned for summary review. Annotations are versioned, and are thus undo/redo-able. 

State: Annotations:  text of annotation, source, time, field attached to 
Behavior: Annotation Management involves searching for and summarizing Annotations 
 

6.  Protect Against Stale Data

Proposals allows users to work with their own copy of enterprise data, so that back-end resources are not tied up during the life of the Proposal. Since a Proposal can “live” anywhere from a few milliseconds to several months, there is a significant risk that the original data back on the server might change out from under it, causing data corruption when the Proposal is eventually submitted and the data rewritten. 
     Proposal-based architecture resolves this problem via optimistic concurrency control, known less formally as optimistic locking. A record is kept of data values as they were copied at “check-out” time, and at submission time these values are checked against their back-end equivalents to make sure there has been no “data interference” by another user in the interim. Although it is a sound strategy, optimistic locking is infrequently used because it places so many demands on the programmer, who must specify in detail what data should be rechecked and what should happen if interference is detected. 
     Under Proposal-based architecture, however, optimistic locking becomes simple.  Built into the infrastructure are mechanisms that: 
  • allow the adapter to indicate which fields are candidates for stale-data checking;
  • implement a default response when stale data is detected, namely rolling back the commit and notifying the user;
  • allow the adapter to include Java code specifying any customized detection, notification or fixup algorithms.
State:  Assumptions, metadata that supplies the names of candidate fields and names of Java methods for detection, notification and fixup 
           Assumed Values, a snapshot of the original values of candidate fields as              replicated 
Behavior:  Stale-data handling 
 
7.  Interact With Server 

A Proposal has to both extract data from and submit data to a back-end data store.  It must be able to translate between its own hierarchic structure and a back end that could be either relational, function-oriented, or object-oriented. 
     The Proposal’s back-end interface is responsible for replicating data from the datastore to the Proposal object (populating the Proposal) and, later, submitting the Proposal to the back end and requesting a commit. 
     Because back ends come in three different styles, the Proposal provides a separate interface for each: 

  • Interface to a database system (JDBC) can automate “data-mapped back ends.
  • Interface to a transaction processor defines the protocol for “function-mapped” back ends.
  • Interface to an OO database can automate “object-mapped” back ends.
In most operating environments a developer implementing Proposals would only use one of these three back end alternatives, depending on the needs and legacy of the particular system architecture. 
     A Proposal is able to perform populates and submits between each of these three back ends and four distinct Proposal types: New, Exists, Update, and Delete. 

State:  Interaction Mode defines various Proposal interaction patterns with the back end 
Behavior:  Populate/Submit 
 

8. Interface with Consumer

The final Proposal responsibility is to interface with the front-end consumer.  The Proposal object itself presents a complete public programming interface that enables any consumer object to communicate with a Proposal.  In addition, it provides a standard Observer object (Publish-and-Subscribe pattern) that will notify interested consumers of various changes to the state of the Proposal. 

State:  Observer Registry of interested consumers 
Behavior:  Notify consumers of  changes to Proposal state 

 
 
 
 
Proposal Side Benefits
 
We alluded above to the tendency of Proposal-based architecture to sharpen up numerous aspects of transactional system structure.  Here are some second-tier benefits that follow fairly quickly from the initial insight. 
 
Proposals Simplify Domain Objects 

Once a Proposal object joins the design scene, it acts as a natural “attractor” for task-specific application behaviors that would otherwise be dumped into domain objects. 
     Take an example from the human resources world. Many simplistic object designs show an Employee domain object that includes a method called HireEmployee. This seems superficially appropriate, but it results in a very cluttered Employee object, since “hiring” touches many other domain objects (JobHistory, EducationHistory, Position, BenefitsEnrollment, etc.). Rather than cramming all this cross-domain activity into the Employee object, it makes more sense to put it into a generic Proposal object called NewHire, whose job it is to link up with JobHistory, EducationHistory, etc. The Employee object becomes simplified and more specialized, with fewer collaborations to adjoining domain objects. 
     In general, Proposal objects suck task-dependent behaviors out of domain space and into their own. This not only shrinks domain objects but make the whole application structure significantly more coherent. 
 
Proposals Redefine Model/View Separation Concepts 

Most object designers use some form of Model/View separation (e.g. Smalltalk’s widely-copied MVC paradigm) to maximize understandability and reuse. This is a powerful design construct that we highly recommend. However, designers familiar with this notion sometimes shy away from Proposal-based architecture because it introduces a third entity that doesn’t seem to fit into the model/view dyad. 
     The key here is that Proposals (which, in our implementation at least, are completely non-visual) are just another kind of model. Proposal models can have their own proposal-oriented viewers, just as domain models have domain-oriented viewers. This taxonomy is simple to think about and adds new precision to the definitions used in application construction. 
 
Proposals Imply Workflow 

Once Proposals get designers thinking in terms of long-running, malleable, pendable business functions, it’s a short jump to thinking about controlling the definition and maintenance of the outer business process itself. This is workflow territory.  Workflow and Proposals are strongly compatible. Workflow is the train; the Proposal is the container that the train transports. 
     There are, it seems to us, actually three kinds of objects in a Proposal-based application architecture: Domain objects that support domain-specific behaviors; Proposal objects that encapsulate the proposed changes to domain objects; and FlowControllers that deploy, move, and submit Proposal objects. Simple applications may need only minimal FlowControllers or perhaps none at all, but as business re-engineering leads to increasingly collaborative applications, all three elements will need to be fully architected. 
     This larger picture lies beyond the scope of this paper, but it does show that once an insight like Proposals clear up a part of the picture, the more we suddenly see needs to be done. 
 
Metadata in the Middle 

New component-oriented visual construction techniques use some form of “data-aware control.” Think of those demos where a developer drags a bunch of GUI or Web components onto a blank window and builds an application that magically  knows how to make all the connections to the database. 
     Unfortunately, this appealing approach leads to a kind of architectural “squeeze play” that limits its usefulness in complex systems. Data-aware controls require easy access to the metadata of the objects that they are rendering. When that metadata living at the system’s back end—the only place it can live under conventional design—interesting middle-tier objects are impossible, for they would occlude the front-end objects from the back-end metadata. 
     Proposals solve this problem because they move metadata from the back of the architecture into the middle. (In fact, a Proposal carries considerably more metadata than a back-end object, since it also includes information about the relationships that domain objects have assumed to accomplish a particular task. For example, a ReorderPart Proposal knows exactly how the Product object relates to the Supplier objects.) 
     Once the self-aware Proposal object is in place, a “Proposal-aware” front-end component can automatically represent mid-tier assets. This moves much more of the system’s self knowledge forward in the architecture, where it can do the most good. 
 
Cascading Proposals 

We usually think of Proposals as preceding Domain objects in the application lifecycle.  But sometimes it’s useful for Domain objects to spawn Proposals. 
     Consider a NewHire Proposal that, upon submission, updates numerous domain objects. A business rule could be added to the Employee domain object so that it  would spawn several new Proposal objects--OrientationEnrollment, BenefitsEnrollment, and FootballPoolRegistration—and fire them off to the new employee. Business events can cause processes which fire further events. 
 
Life After Proposal Death 

Even after a Proposal has been submitted to domain space and resulted in a successfully committed transaction, it can be archived and continue to perform posthumous service. 
     Proposals contain far more detailed information than most domain spaces would ever consider holding. For example, a Proposal that has passed through four desktops before commitment carries a  record—right down to the field and timestamp level—of who made what changes when. It also contains (in the form of annotations) the “chatter” that reveals the rationales behind changes that are only summarized in the formal data. 
     Thus, an archive of Proposals provides a complete record of questions, comments, explanations, approvals, and changes that could prove invaluable in the case of later litigation, quality control, auditing, process re-engineering, etc. 
 
 

Conclusion
 
It may be clear by now that Proposals perform a classic OO transformation: they turn a process into an object. Currently, transactions are conducted by means of an organized conversation between a consumer requesting an update and  resource software that evaluates that request. This conversation is a real-time, short-lived, two-party activity; a Proposal renders it as a hard-edged thing. The benefits that follow are the benefits of objects in general, well-appreciated by all readers of this magazine. 
     Proposals concretize the problem, so that design becomes easier to think about. They model a familiar piece of the real world, so that a complex technical process becomes easier to explain and intuitive to use. They abstract common behaviors, so that  re-use becomes not just possible but natural. 
 
 
Return to Kinexis Home Page