Mat*_*att 10 activerecord design-patterns architectural-patterns
使用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() { ... }
}
Run Code Online (Sandbox Code Playgroud)
虽然这很简单,但我发现我的课程变得非常臃肿,伴随着大量的逻辑组合!
使用分层/域设计,您可以定义相同的类,如:
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(); }
}
Run Code Online (Sandbox Code Playgroud)
它是如何从Active Record =>分层设计迁移出来的?
我正在为这种分层设计寻找同行批准/建议 - 我通常不会在Active Record类型之外进行设计!任何评论赞赏.
注意 - 这个例子是故意简单的(UnitOfWork并没有真正使用,而且Repository/Validator的新版本将以不同的方式处理).
这篇文章似乎对两者都有很好而简洁的描述: https://hashnode.com/post/which-design-pattern-do-you-prefer-active-record-or-repository-cilozoaa5016o6t53mhsdu6nu
我想补充的一件事是,它不仅仅是“当您的持久性需求简单时,活动记录很好;当您的持久性需求复杂时,存储库很好”。这里图案的选择更多地与你对德墨忒尔定律的感受有关。如果您希望架构的不同部分完全分离,以便某人可以理解一个部分而不理解另一个部分,那么您需要德墨忒尔定律。也就是说,我认为,特别是在项目的早期,当规范可能发生变化时,过于痴迷于这些抽象是非常危险的。不要再猜测你的项目未来的维护者,他们可能很聪明,他们应该能够一次考虑不止一件事,如果他们不能,那么你可能会遇到使用存储库模式无法避免的更大问题。
两种方法都有其优点和缺点。
假设您正在将 Active Record 样式的对象传递到某个地方(BL 深处)。你可以阅读它,你可以改变它,你可以保存它。在这种情况下,那块 BL 仅与您实体的接口耦合。使用分层架构,您必须以某种方式将存储库传递给该代码。您可以显式传递它或使用 IoC 容器 - 由您决定。
另一点是,当您有了存储库的概念时,您可以轻松定义诸如“we-have-a-new-object-in-repository”或“one-object-has-been-deleted-from-repository”之类的概念,这些概念基本上是如果您正在使用分布式环境,那么这是非常有用的通知。