Skip to content

Retrieve / Write lifecycle contract

Defines the abstract read/write contract every concrete application manager must implement; this library supplies no implementation, only the contract and the intended call sequence.

Field Value
Operation ID retrieve-write-lifecycle-contract
Trigger Front-end page load or save postback on a derived manager
Inputs Derived-class context state
Outputs Boolean success flag; Message text; persisted business objects
Primary components AppManagerBase MustOverride members
Entry point SAIF.Application/AppManagerBase.vb

Steps

  1. SAIF.Application defines the shape of every read/write operation but implements none of it. Retrieve() and Write() exist on AppManagerBase purely as MustOverride (abstract) function signatures returning Boolean. This is a deliberate design choice: it forces every domain manager in every consuming library to explicitly decide what "load my data" and "save my data" mean for its own business object, while guaranteeing that front-end code calling manager.Retrieve() or manager.Write() works identically no matter which concrete manager it holds.
  2. The intended read sequence is a three-step guard chain. A caller invoking Retrieve() is expected (by convention, not by enforced code in this library) to first confirm the manager's context is valid via the ValidContext check, then let the framework call OnValidContext() so the derived class can react to a newly-valid context, and only then call OnRetrieve() to actually pull data from the database. Skipping the validity check is possible because nothing in this library prevents it — the contract only describes the intended order, it does not enforce it.
  3. The intended write sequence brackets the actual save with an explicit transaction. A derived manager is expected to call OnTransactionStart() before making any changes, perform the real save logic in OnWrite(), and finish by calling OnTransactionStop(commit) — passing True to commit the changes or False to roll them back. This bracketing exists specifically so that a save operation which fails partway through does not leave the database in a partially-updated state (BR-APP-006).*
  4. The reference implementation lives outside this library, in ClaimAppManager (SAIF.Application.Claim), which shows how the contract is meant to be honored in practice: its Retrieve() explicitly checks ValidContext before doing any work, and its Write() wraps the call to OnWrite() in a Try/Catch/Finally block that guarantees OnTransactionStop is always called — with True on success and False if an exception was caught — so a database transaction is never left open regardless of outcome.
  5. Two related lifecycle hooks, OnContextChanged() and OnCheckSecurity(), are declared on the base class but never invoked by any code within SAIF.Application itself. Responsibility for deciding when the business context has changed, and when security should be re-evaluated, is pushed entirely onto the derived manager — this library only defines the classification categories those checks would use (BR-APP-003).

Process flow

The following diagram visualizes the two parallel lifecycle paths this contract defines, and where SAIF.Application's responsibility (the abstract contract) hands off to the consuming manager's responsibility (the concrete implementation, shown here via ClaimAppManager).

flowchart TD
    Trigger(["Page load or<br>save postback"]) --> Read["Read path triggered:<br>caller invokes Retrieve"]
    Trigger --> Write["Write path triggered:<br>caller invokes Write"]

    Read --> ValidCheck["Derived manager checks<br>ValidContext before<br>proceeding"]
    ValidCheck --> OnValid["OnValidContext reacts to<br>a newly-valid context"]
    OnValid --> OnRetrieve["OnRetrieve loads data<br>from the database"]
    OnRetrieve --> ReadDone(["Read complete"])

    Write --> TxStart["Derived manager calls<br>OnTransactionStart"]
    TxStart --> OnWrite["OnWrite performs the<br>actual save, wrapped in<br>Try/Catch by convention"]
    OnWrite --> Outcome{"Save succeeded?"}
    Outcome -->|Yes| Commit["OnTransactionStop(True)<br>commits the transaction"]
    Outcome -->|No, exception caught| Rollback["OnTransactionStop(False)<br>rolls back the transaction"]
    Commit --> WriteDone(["Write complete"])
    Rollback --> WriteDone

Failure and edge-case behavior

  • No implementation of Retrieve/Write exists in this library; behavior on failure is entirely determined by the derived class (e.g. ClaimAppManager's Try/Catch/Finally wrapping of OnWrite()).