Используя ActiveRecord, вы можете определить класс следующим образом:
class Contact
{
private String _name;
public String Name
{
get { return _name; }
set
{
if (value == String.IsNullOrWhiteSpace())
throw new ArgumentException(...);
else
_name = value;
}
}
public Boolean Validate() { ... /* check Name is unique in DB */ }
public Boolean Save() { ... }
public static List<Contact> Load() { ... }
}
Несмотря на то, что это красиво и просто, я обнаружил, что мои классы стали очень раздутыми из-за большой логики!
Используя многоуровневый / доменный дизайн, вы можете определить тот же класс, например:
class Contact
{
[Required(AllowEmptyStrings=false)]
public String Name { get; set; }
}
class ContactService : IService
{
public List<Contact> LoadContacts() { return (new ContactRepository()).GetAll(); }
public Contact LoadContact(int id) { return (new ContactRepository()).GetById(id); }
public Boolean SaveContact(Contact contact)
{
if (new ContactValidator().Validate(contact))
new ContactRepository().Save(contact);
}
}
class ContactRepository : IRepository
{
public List<Contact> GetAll() { ... }
public Contact GetById(int Id) { ... }
public Boolean Save(Contact contact) { ... }
}
class ContactValidator : IValidator
{
public Boolean Validate(Contact contact) { ... /* check Name is unique in DB */ }
}
class UnitOfWork : IUnitOfWork
{
IRepository _contacts = null;
public UnitOfWork(IRepository contacts) { _contacts = contacts; }
public Commit() { _contacts.Save(); }
}
Как он был перенесен из Active Record => многоуровневый дизайн?
- Проверка уровня объекта в установщике имен => остается (возможно с помощью аннотации данных)
- Проверка бизнес-логики / правила (уникальное имя) => перемещена из сущности в новый отдельный ContactValidator
- Сохранить логику => перемещено в отдельный класс шаблонов репозитория (также с UnitOfWork)
- Загрузка логики => перемещена в отдельный репозиторий
- Взаимодействие с репозиторием осуществляется с помощью новой службы ContactService (которая будет обеспечивать использование ContactValidator, ContactRepository, UnitOfWork и т. Д., В отличие от того, чтобы вызывающая сторона теряла связь с ContactRepository!).
Я ищу одобрение / предложения коллег для этого многоуровневого дизайна - я обычно не проектирую за пределами типа Active Record! Любой комментарий приветствуется.
NB. - Этот пример намеренно прост (UnitOfWork на самом деле не используется, и обновление Repository / Validator будет обрабатываться иначе).