PhazedCRUD

also named - SplitCreate, SplitReader, SplitUpdate, SplitDelete

Problem

You need to populate an object in two distinct calls or phazes, dependant on a condition or constraint. A domain object needs to read its persisted context/data and populate itself in a versatile way. You need a more fine grained solution to the standard CRUD interface

Context

Hopefully you will have an abstracted the data from the storage device for more versatilty, (by some means - example: Data Access Component or a Reader/ Writer). For example take the action of Deleting, msot environments enjoy the DeleteFlag rather than Deleting the record entirely. If this is the case, you can separate the Delete into a physical record deletion method and a flag-based deletion method.

By implementing a phazed approach (or algorithm) with your actions using Template Method (GoF), you can separate the actions into 2 or more parts. These individual parts in the algorithm is then provided by a base class.

For example, you have information cached on the local machine for Product Information, and a Server which contains full Product Information. You have two conditions for populating your object. Population 1 when network connection is Open and Population 2 when network connection is closed.

Solution

The PhazedCRUD approach is first a way of dividing the action into more parts. Two or more parts is recommended. For example:
Creating = CreateAction1 + CreateAction2
Deleting = DeleteAction1 + DeleteAction2
etc.

Using C#, create three methods: The Template Method called Populate (Create) in this example and the algorithm sequence methods of PopulateBasic and PopulateDetail. Here it makes sense to have all three methods public and as hotspots, but use your discretion. If you wish that the algorithm not be changed/override do not mark the Template Method as virtual (c#)

abstract class MyDataClass
{
    public virtual bool Populate()
    {
        return (PopulateBasic()) ? PopulateDetail() : false;
    }

    public virtual bool PopulateBasic()
    {
    }

    public virtual bool PopulateDetail()
    {
    }
}


image
In the usual use of Populating your object with context data, Populate is always called. You then override PopulateBasic and implement your basic population. Override the PopulateDetail to add more details.

Example:

public class Product : MyDataClass
{
  
    public overide bool PopulateBasic()
    {
        //Example:
        //Load ProductID, ProductName from cache in XML format.
    }

    public override bool PopulateDetail()
    {
        //Example
        //Check if internet connection exists
        //If so,
        //Retrieve detail from a WebService for the ProductID
        //Populate the rest of the object
    }
}

A CRUD-like Example


TDomainObject here is a Class containing the data. This example shows a more stateless class.

public class MyDataStore
{
    public object Save(TDomainObject domainObject)
    {
        return (Create(domainObject) == null) ? Update(domainObject) : null;
    }

    public object Create(TDomainObject domainObject)
    {
        return null;
    }
   
    public object Update(TDomainObject domainObject)
    {
        return null;
    }
   
    public bool Read(TDomainObject domainObject)
    {
        return (ReadBasic(domainObject)) ? ReadDetail(domainObject) : false;
    }

    public bool ReadBasic(TDomainObject domainObject)
    {
        return true;
    }

    public bool ReadDetail(TDomainObject domainObject)
    {
        return true;
    }

    public bool Delete(TDomainObject domainObject)
    {
        return (DeleteFlag(domainObject)) ? DeleteReal(domainObject) : false;
    }

    public bool DeleteFlag(TDomainObject domainObject)
    {
        return false;
    }

    public bool DeleteReal(TDomainObject domainObject)
    {
        return false;
    }
}