存储库模式和/或/ vs业务逻辑层

Ass*_*sin 28 c# design-patterns

我有一个问题,我想知道你的意见.

我正在尝试使用Repository Pattern.我有一个存储库对象,可以将数据加载到POCO.我还创建了一个业务逻辑层,它增加了一些功能但基本上包装了POCO.所以最后我有一个BLL,它使用存储库来加载DAO.

我对这个解决方案不是很满意.我有三层,但我觉得BLL没有提供enought功能来保持它.另一方面,我不想把我的逻辑放在存储库层或数据访问层?

所以我的问题是我应该在哪里应用逻辑?你使用哪种解决方案(DAO + repo或DAO + BLL + rep或其他任何解决方案)?

Jar*_*yer 27

在设计域时,有两种基本的方法可以考虑业务规则.

1.)域实体是基本的POCO/DTO.然后你将它们交给域名服务.这些服务可以像另一个类一样简单,或者它们实际上可以是位于另一个服务器上的实际服务.

var user = repository.Find(x => x.UserName == userName);
if (userLogonService.IsValidUser(user, password)) {
   userLogonService.UpdateUserAsLoggedOn(user);
}
repository.SaveChanges();
Run Code Online (Sandbox Code Playgroud)

2.)域实体包含它们自己的操作逻辑.这更接近许多MVC模式将遵循的内容.既然你问过,这就是我喜欢的模特.

var user = repository.Find(x => x.UserName == userName);
if (user.CheckPassword(password)) {
    user.LogOnNow();
}
repository.SaveChanges();
Run Code Online (Sandbox Code Playgroud)

两者都是完全有效的模式.#1具有离散的业务操作层,但遭受了贫血域模型的困扰.如果您的域开始变得复杂,或者模型可以执行很多操作,#2可能会导致大型域实体.

编辑#1:对John Kraft的回应

Oven.Bake(myPizza)与myPizza.Bake()

我大多同意.你有一个单独的烤箱服务,或者你有几十个可用的烤箱存储在烤箱存储库中烤箱只是另一个域实体?在#2中,烤箱是域的一部分.我倾向于进行域建模的方式,大多数名词都是域实体,除非你100%确定只有一个东西.

但披萨在烘烤时会发生一些事情.

interface ICanBeBaked {
    int BakeMinutes { get; }
    int BakeTemp { get; }
    void Bake();
}
class Pizza : ICanBeBaked {
    int BakeMinutes { get { return 15; } }
    int BakeTemp { get { return 425; } }
    void Bake() {
        // melt cheese!
        this.isBaked = true;
    }
}
class Oven {
    void Bake(ICanBeBaked thingToBake) {
        // set the temp, reserve this oven for the duration, etc.
        thingToBake.Bake();
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 我更喜欢选项#1到#2.我将这些等同于一个例子:#1 => Oven.Bake(myPizza)#2 => myPizza.Bake()#2对我来说感觉不对,因为披萨在现实世界中什么都不做. (7认同)