I am trying to figure out how to setup a clean architecture for my shopping cart without over architecting it or ending up with a anemic domain model. Right now I just want to use standard ADO database logic without any ORM framework. (I am also learning EF4.1, but not good enough yet to use in production)
Ideally I would just have a POCO for each Business object/entity and a repository/data class that will handle persistence. To keep things simple, I am thinking to tightly couple the POCOs to the data layer and it will return POCOs. If I add DTO to the mix as well, then I end up having 5-6 class files for each area (gc, order, items, payments, etc) which just seems like too much for a simple app. I can always refine later.
The first class I am working on is for gift certificates. One of the methods is to create a new GC. In this method I will need to query the database to ensure the new code does not already exist in the system. Is it ok to just call the data layer/repo inside this method?
Should the data layer/repo be static? Should I only expose it through the POCO itself?
Should I drop the data layer altogether and just have the data calls directly in my POCOs (active record style)?
I need a simple architecture which will allow me some separation of concerns without over complicating things. The database provider and table structures will not change for at least the next few years.
Here is some code.. just need to figure out where the parts go.
public GiftCertificateModel
{
public int GiftCerticiateId {get;set;}
public string Code {get;set;}
public decimal Amount {get;set;}
public DateTime ExpirationDate {get;set;}
public void Redeem(string code, decimal amount)
{
//need to validate the input
//need to insert a record to the transaction log table (call the repo or does this entire method need to be in the repo?)
}
public void GetNewCode()
{
//need to create random alpha num code
//need to make sure the code is unique in the db... (again, (call the repo or does this entire method need to be in the repo?
}
}
public GiftCertificateRepo : DALBase (DALBase has methods for connecting, etc)
{
//mapping code here to map SQLDataReader values to GiftCertificateModel properties
//i can also setup separate DTOs if it makes more sense...
//should the repo be static?
public static GiftCertificateModel GetById(int GiftCertificateId)
{
//call db to get one and return single model
}
public static bool IsUnique(string code)
{
//call db to see if any records exists for code
}
public static List<GiftCertificateModel> GetMany()
{
//call db to get many and return list
}
public static void Save(GiftCertificateModel gc)
{
//call db to save
}
}
Calling code:
GiftCertificateModel gc = new GiftCertificateModel();
gc.Code = gc.GetNewCode(); //do i call the is unique here or in the GetNewCode method?
gc.Amount = 10;
gc.ExpirationDate = "1/1/2012";
GiftCertificateRepo.Save(gc);
By keeping the POCOs (representations of data) separate from the repository objects (representations of how data gets stored/retrieved) you will be able to much more easily switch from ADO to a more advanced ORM system in the future – those code changes will be isolated to one place.
Better yet, define an IRepository interface and have your ADO repostiory class implement it. Then, your app should work only with IRepository thus making it even easier to test or switch repository implementations in the future.