Active Record vs. Repository pattern
|
Dnes se podíváme na dva návrhové vzory z oblasti přístupu k datům, které používají zcela odlišnou filosofii, ale nakonec si ukážeme, že jejich kombinací, můžeme získat celkem zajímavé výsledky.
Active Record
Návrhový vzor Active Record staví na předpokladu, že základem aplikace je databázový model a od něj se vše odvíjí. Každý řádek tabulky je reprezentován konkrétní instancí objektu. Většinou je takový objekt odvozen od bázové třídy, která implementuje potřebné rozhranní pro persistenci objektu – typicky CRUD metody.

Tento vzor se hojně využívá v různých ORM frameworcích. Je součástí dnes velmi módních frameworků Ruby on Rails, django nebo Castle, které na něm stavějí svůj datový model a díky velice snadnému mapování dokážete napsat (vygenerovat) kostru databázové aplikace během několika málo minut.
Pro velice jednoduché aplikace může být tento vzor, díky své jednoduchosti, vhodný. Jenže porušuje několik pravidel dobrého objektového návrhu (persistence ignorance, single responsibility, pevně daná bázová třída, atd.).
Repository
Návrhový vzor Repository je základním kamenem doménou řízeného návrhu. Model aplikace nemá ponětí o tom, jakým způsobem je persistován. O to se stará právě Repository. Navíc díky tomu, že se o persistenci stará cizí objekt, stačí nám znát pouze jeho rozhranní a v případě potřeby ho snadno nahradit jiným.

Kombinace
Teď zabrousím do konkrétnějších implementací a to do ActiveRecord z projektu Castle. Tako konkrétní implementace je postavená na běhovém prostření dotnet a jako svůj základ používá ORM nástroj NHibernate.
Nejpřímější cesta jak s ním pracovat, je podědit třídu z bázové třídy ActiveRecordBase
a označit ji a její vlastnosti patřičnými atributy:
[ActiveRecord]
public class User : ActiveRecordBase<User> {
[PrimaryKey] public int Id { get; set; }
[Property] public string Name { get; set; }
[Property] public string Email { get; set; }
[Property] public string Login { get; set; }
[Property] public string Password { get; set; }
}
A můžeme pracovat. Autoři si však byli vědomi toho, že vzor Active Record nemusí vyhovovat všem a přidali statickou třídu ActiveRecordMediator
, který dokáže posloužit jako základ pro Repository. Třída pak nemusí dědit z ActiveRecordBase
:
[ActiveRecord]
public class User {
[PrimaryKey] public int Id { get; set; }
[Property] public string Name { get; set; }
[Property] public string Email { get; set; }
[Property] public string Login { get; set; }
[Property] public string Password { get; set; }
}
public class UsersRepository : IRepository<User> {
public User Load(int id) {
return ActiveRecordMediator<User>.FindByPrimaryKey(id);
}
public void Save(User obj) {
ActiveRecordMediator<User>.Save(obj);
}
public void Delete(User obj) {
ActiveRecordMediator<User>.Delete(obj);
}
}
To už je o něco lepší, ale stále máme v aplikačním modelu silnou vazbu na datový model. Můžeme se posunout o level dál a zkombinovat oba vzory tak, abychom z nich vytěžili co nejvíce. Základní myšlenkou je to, že v aplikaci budeme mít jak datový model, tak doménový. Datový model se bude pomocí Active Record starat o persistenci a Repository poslouží k transformaci doménového modelu na ten datový.
Něco podobného můžete najít v seriálu, který píše Rob Conery, kde používá zjednodušenou Repository, IQueryable
jako filtry a LINQ2SQL jako datový model. Velice zajímavé, doporučuji ke shlédnutí.
Tagy: ActiveRecord, Repository, ORM