Quantcast
Channel: MOBILE C# CAFÉ
Viewing all articles
Browse latest Browse all 15

The Compleat History of Data Access Patterns

0
0
Datasm2
Data

One of the great things about Xamarin development is that we get to use many of the concepts we learned in pre-mobile development. Software architecture is a good example. Most of the software patterns that we used in web development are still applicable.

Let’s look at the data access patterns outlined by the master of enterprise software architecture, Martin Fowler. We can still use the pre-OO procedural approaches to coding like his Transaction Script, Table Module, and Table Data Gateway. Then we can code using strictly object-oriented patterns such as Domain Models, Data Mappers, and the ever-popular Repository. Many of these are the equivalent of or have evolved into the patterns we use today such as POCO, Controller, ViewController, and ViewModel.

If you want to explore the Xamarin Data Access Layer(DAL) in the context of traditional enterprise design patterns then read on. If you just want to know how to create a DAL using the Repository pattern in Xamarin, then stay tuned for my forthcoming blog entry on the Repository.

Let’s begin at the beginning with the old-skool patterns.

Procedural Patterns

The point of object-oriented design was to wean us off of the procedural approach. Before we created domain models, data objects, object-oriented business logic and the like, we created a list of procedures to call, which is now called the Transaction Script pattern.

Transaction Script

We make calls to these procedures that return the data we need. Using the Transaction Script pattern (though most of us don’t call it that when we’re using it) and some pseudocode, our app looks something like this:

class void MyEntireApp 
{
    public GetSomethingAndDoSomethingWithIt() 
    public GetSomethingElseAndDoSomethingElseWithIt() 
}

Data access and business logic were wrapped up together in this construct. Until…someone became annoyed with how long this list of procedures was (and sadly we used let it hit the floor sometimes). They would call this a long method code smell and say that the Transaction Script had become an anti-pattern. Another approach was employed to break up these procedures according to the tables in the database.

Table Modules

Blocks of table-specific business and data access logic are now called Table Modules. This one is for the Item table.

class void ItemTableModule() 
{
    public GetPersonAndDoSomethingWithIt(int ID)
    public GetPersonAndDoSomethingElseWithIt(int ID)
}

Mind you, we haven’t yet introduced a domain model, so the business logic is probably operating on database-specific entities, such as Record Sets or variables from rows specified using numeric IDs. What we have here is a coupled business and data access layer grouped by table, violating Separation of Concerns (SOC).

The next step is to break out the data access logic into separate table-specific data access components which Fowler calls Table Data Gateways.

Table Data Gateways

A Table Data Gateway handles all of the data access for a particular table: usually CRUD-style (create, read, update, delete), using row ids.

class void ItemTableGateway 
{
    public Get(int Id)
    public Put(string Name)
    public Update(int Id, string Name)
    public Delete(int Id)
}

The Table Data Gateway houses basic data transactions as well as more advanced queries and inserts, but the results are generally record sets.  The record sets are generally passed back to the Table Module which can then handle the business logic. Using a Table Module with a Table Data Gateway gives us separation of business and data access logic, all without much object-oriented programming.

If all of the tables in the database are handled using Table Modules and Table Data Gateways, a facade class can be laid on top of all of them to provide easy-access to all data calls in one place. This pattern is a monolithic Table Data Gateway which I’m going to call a Database Gateway (my term, not Folwer’s). A Database Gateway has all table CRUD calls for all tables in the same class( and hints at important things to come when we get to the Repository pattern in OOP).

Database Gateway

Here’s a Database Gateway for both Item and Person tables.

class void DatabaseGateway
{
    public GetItem(int Id)
    public PutItem(string Name)
    public UpdateItem(int Id, string Name)
    public DeleteItem(int Id)
    public GetPerson(int Id)
    public PutPerson(string Name)
    public UpdateItem(int Id, string Name)
    public DeletePerson(int Id)
}

Not very pretty but, for a small number of tables, quite concise and organized. You’ll see soon why a Database Gateway is important in Xamarin development.

Those are some oldie-but-goodie non-OO patterns  useful in simple apps or in simple components of OO apps.  Now, fast-forward to the present.

Domain Model Patterns

Enter domain models! Create classes that represent specific entities within the workflow and have a one-to-one relationship between a business entity and an object instance (like a physical car and a Car object). Here is where we stopped sticking all of our logic in procedures (pre-OOP-speak for method), and started constructing classes to represent our domain logic. In simple apps that means an Item class or a Group class, which pretty much correspond to our table names.  In more complex apps this means lots of classes which correspond to different entities and processes that arise as a result of defining user stories or system architecture.

Let us begin with the simplest of the object-oriented patterns.

Domain Model

Now called a ‘model containing business logic’, Folwer’s Domain Model is an OOPified Table Module pattern. This class reflects our domain logic with names like Item, Person, Building, Conversion, Forecast, Event, and Reimbursement. Each object instance generally corresponds to a single physical thing. For example, each instance of an Item class represents a single physical item. A Domain Model class for an item entity might look like this.

class void Item() 
{
    public int Id {get;set;}
    public string Name { get; set;}
    public BuyItem(Item item)
    public ReturnItem(Item item)
}

Today, most apps separate the Domain Model into its constituent data fields and data access calls. POCOs (Plain Old CLR (or C#) Object) contain primarily strongly-typed data fields and sometimes property attributes and a method or two. Typically, ViewControllers or Controllers house the business logic and handle data using data models.  This is an important point, but meanders away from our data access pattern topic. This article doesn’t cover the much-discussed MVC and MVVC patterns.

Back to the Domain Model and data access. All of our logic surrounding the processing of an Item is now  tucked into the Item class.  Unfortunately, that also includes the data access logic. So, once again, now we have business logic and data access logic that is tightly coupled. We require the same type of decoupling solution that Table Data Gateway offered us, but in the world of OOP. Enter the Data Mapper.

Data Mapper

A domain object-oriented data access class is called a Data Mapper, which is an implementation of CRUD for a specific table or entity.

class void ItemMapper() 
{
    public Item Get(Id id)
    public void Put(Item item)
    public void Update(Item item)
    public void Delete(Item item)
}

This Data Mapper, called ItemMapper, is the data access component for the Item Domain Model. Now the Item class discussed earlier can contain only business logic and make data calls to ItemMapper. We have appeased the great god SOC (Separation of Concerns).

Data Mappers typically handle only single objects, not collections. If you want to return and handle collections you’ll need a to use a Repository pattern.

Repository

The most common choice for a data access pattern by Xamarin developers in their apps, a Repository for a Domain Model is basically a Data Mapper for a collection, such as ItemRepository for Items.

class void ItemRepository
{
    public List[Item] GetAllItems();
    public void PutAllItems(List[Item] items);
}

Using Domain Models, Data Mappers, and Repositories in this way will result in a pile of class pairs like Item and ItemMapper (or ItemRepository), Person and PersonMapper, Building and BuildingMapper, and Conversion and ConversionMapper.

So many Mappers (or so many Repositories)!

Some developers might be pleased with the elegance and OOPness of this architecture.  Others might think that it spreads the code out too much. Multiple Data Mappers and Repositories can smell of code duplication, so sometimes we want all of our Mappers available in one place. Creating a facade or an additional layer of abstraction over the mappers offers a single location where all data access can take place, which is divided behind the scenes to the appropriate data mapper. Filtering and code reuse all take place in methods to optimize the data access layer.

A simple Database Repository for the Item and Person classes might look like this.

Add this:

    public List[Item] GetAllItems()
    public void PutAllItems(List[Item] items)

to this:
class void Repository
{
    public Item GetItem(Id id)
    public void PutItem(Item item)
    public void UpdateItem(Item item)
    public void DeleteItem(Item item)
    public Person GetPerson(Id id)
    public void PutPerson(Personitem)
    public void UpdatePerson(Personitem)
    public void DeletePerson(Personitem)
}

The Repository is the OO version of the Database Mapper that we discussed earlier. It provides an app-wide location for all data access calls, but this time the calls employ the object-oriented Domain Model instead of procedures that execute some SQL and return record sets.  Repository methods call the appropriate Data Mappers, then filter and process the data that is returned.

class void Repository
{
    public Item GetItem(Id id)
    public void PutItem(Item item)
    public void UpdateItem(Item item)
    public void DeleteItem(Item item)
    public Person GetPerson(Id id)
    public void PutPerson(Personitem)
    public void UpdatePerson(Personitem)
    public void DeletePerson(Personitem)
    public List[Item] GetAllItems()
    public void PutAllItems(List[Item] items)
}

So that’s a Repository. Awesome. Study it closely. You’ll need this one.

Note: The definition of the repository pattern has evolved since its inception.  It was originally intended as an abstraction to decouple the data layer  implementation (for example, SQLite) from the rest of the app with the added benefit of providing in-memory data-object collections. Over the years, many C# apps needed the decoupling but not the in-memory data objects, so those collections have evolved to become data objects returned by methods in many cases, not persisted in repository properties. This is true in most mobile apps as well.

That’s the compleat data access story. Here’s the recap.

Summary

Pre-OOP we built coded everything in Transaction Scripts, code that made calls to procedures for everything. Then we divided code into Table Modules, organized by the data in our tables which contained both business logic and data access. Record ids were passed into these procedures and they returned record sets. Awareness of the importance of decoupling led to data layer code called Table Data Gateways which handled CRUD transactions for each table. Table Data Gateways were sometimes aggregated into facades, which I call Database Gateways, which handled all data access in the application.

OOP gave us the ability to do all of this using data models instead of record sets, which means a more powerful and more app-specific toolset for data access. Domain Models, like Table Modules, let us build entity-specific objects except that the actual data fields used.  Domain Models are data models combined with business logic. Loosely couple the data access from that business logic by making a Data Mapper, implementing of CRUD for a specific table for a single table or entity: Get, Put, Update, and Delete.  Even a few Data Mappers can create a confusing data access interface. Simplify with a Repository, which is a facade over top of all your Data Mappers, providing a single entry point for all data access without compromising SOC.

Most mobile app development uses a Repository of some kind.

Data Access Using Xamarin

What does any of this have to do with Xamarin development?

Here’s what: The SQLite.NET ORM has already created Data Mappers for us. Let me say that again. SQLite.NET is a big library of table-specific Data Mappers. SQLite.NET will return Item objects from the your Item table, Person objects from your Person table, etc., etc., assuming that you’ve mapped the fields correctly in your data models.

Creating a data access class (or classes) which uses a bunch of calls to SQLite.NET is often an implementation of the Repository pattern. Now we can code our mobile DAL in the context of design patterns that are familiar.

In a later post I’ll talk about how to use the Repository pattern to implement SQLite.NET in a Xamarin app.


Viewing all articles
Browse latest Browse all 15

Latest Images

Trending Articles





Latest Images