Repositories in the Abstract Domain Pattern

In this blog entry I will further discuss the repositories as they relate to my previous blog entry A Proposal for an Abstract Domain Pattern.   

1.  The Identity Class 
In the pattern I specified that the abstract domain class defines identity.   So an interesting possibility is to create an actual identity class that inherits from the abstract domain class.    The identity class can throw an exception if you attempt to access any data other than the identity fields.   In C# if you aren’t to picky about the exception that it throws you can just let visual studio generate the class for you and just add the constructor.  Here’s some sample code.

 public class PersonIdentity : APerson
 {
  public PersonIdentity(int personID)
  {
   _personID = personID;
  }
  public override string Name
  {
   get
   {
    throw new Exception(“The method or operation is not implemented.”);
   }
   set
   {
    throw new Exception(“The method or operation is not implemented.”);
   }
  }

  public override APerson Father
  {
   get
   {
    throw new Exception(“The method or operation is not implemented.”);
   }
   set
   {
    throw new Exception(“The method or operation is not implemented.”);
   }
  }

  public override APersonSet Children
  {
   get { throw new Exception(“The method or operation is not implemented.”); }
  }
 }
2.  Making the Domain Class IComparable
For a large repository you can’t work with the entire repository in memory so you need a way to specify part of a repository.  A convenient way to do that is to make the domain class implement the IComparable interface.   Then we can use the concept of a range of values to specify a section of the repository.  See  Caching using a Generic Step Function for an example of how you might define an IRange interface.

We can easily make our APerson class IComparable using the following code.

    public int CompareTo(object obj)
    {
     if (obj == null)
     {
      throw new Exception(“Cannot compare to null”);
     }
     APerson person = obj as APerson;
     if (person == null)
     {
      throw new Exception(“Must be compared to a person”);
     }
     return _personID.CompareTo(person.PersonID);
    } 

2.  Repository Basics

To give some flexibility on how domain objects are identified I’ve decided that the pattern for a repository is that it takes an arbitrary abstract domain object as the lookup key.  In particular since the Identity class inherits from the abstract it can be used to get data from the repository.   Or if you already have a view object perhaps obtained from a pick list you can use the view object directly to get the full object.   A revised example of an abstract domain class APersonSet would be as follows.

public abstract class APersonSet
{
    public abstract APerson Get(APerson person);
    public abstract bool Contains(APerson person);
    public abstract void Add(APerson person);
    public abstract void Remove(APerson person);
    public abstract void Update(APerson person);
    public void Save(APerson person)
    {
         if (Contains(person))
            {Update(person);}
         else
            {Add(person);}
    }
 } 

For the user of the repository the previous code

_person = _repository.GetPerson(_id);

becomes instead

personIdentity = new PersonIdentity(_id);
_person = new _repository.GetPerson(personIdentity);

3.   Retrieving Sets of Objects from a Repository

I think the most general way to access a set of objects in the repository would be something like

public  bool ReadForward(out IList<APerson> list, Range<APerson> range, Criteria<APerson> critera, int maxCount)
public  bool ReadBackward(out IList<APerson> list, Range<APerson> range, Criteria<APerson> critera, int maxCount)

These routines would read an unpredictable number records (but never more than maxCount) and add them to the list.   The unpredictablie record count allows the repository to provide more efficient access through reading multiple database records at a time.  The routines would return true if there was more data to be read and false if not.   The range argument allows us to implement GetNextPage methods and the criteria object allows us to filter the data we retrieve.

These routines would use a default sort sequence based on the identity fields (typically primary key in the database).   We might want to create some other sort sequences based on alternate keys in the database.   This might require some methods like the following.
public class APersonIndex<TIndex> where TIndex : IComparable {…}

public  bool ReadForward(out IList<APerson> list, Range<TIndex> range, Criteria<APerson> critera, int maxCount)
public  bool ReadBackward(out IList<APerson> list, Range<TIndex> range, Criteria<APerson> critera, int maxCount)

4.  Criteria Classes
But what exactly is this Criteria<APerson> class I’ve mentioned above.   At its most basic level a criteria is any test that can be applied to APerson and return true or false depending on whether the APerson object passes the test.  Of course this is just the Specification Pattern in Domain Driven Design.   So we might define an generic interface to indicate this.

public Interface ICriteria<APerson>
{
      bool IsSatisfiedBy(APerson person);
}

If performance didn’t matter that would be all you needed since the repository could sequentially retrieve every person in the database and test each one to see if it satisfied the criteria.   In practice though there will be one or more criteria classes that can be executed with reasonable efficiency.   A simple application might rely only on a few hard coded criteria tests perhaps implemented as stored procedures.  More complicated applications might include a programmable query interface which would require the ability to generate SQL queries within the application itself.

We might have the repository include separate read methods for each PersonCriteria class we define and let the compiler choose the right one to use based on the class.   I’m not really happy with this approach since I don’t see why these different criteria classes belong in the core definition of the domain but I think I’ll leave that subject for a later blog.

Advertisements

One Response to “Repositories in the Abstract Domain Pattern”

  1. jeanettajuarez6377 Says:

    Thanks for visiting, vivacious. I just realized it’s been so long since I updated this page and it’s time now. Click http://d2.ae/hool090745

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s


%d bloggers like this: