我正在重构一个正在结束的项目的代码,最后我把很多业务逻辑放在服务类而不是域对象中.此时,大多数域对象仅是数据容器.我决定在服务对象中编写大部分业务逻辑,然后将所有内容重构为更好,更可重用和更易读的形状.这样我就可以决定应该将哪些代码放入域对象中,以及将哪些代码分解为自己的新对象,以及应该在服务类中保留哪些代码.所以我有一些代码:
public decimal CaculateBatchTotal(VendorApplicationBatch batch)
{
IList<VendorApplication> applications = AppRepo.GetByBatchId(batch.Id);
if (applications == null || applications.Count == 0)
throw new ArgumentException("There were no applications for this batch, that shouldn't be possible");
decimal total = 0m;
foreach (VendorApplication app in applications)
total += app.Amount;
return total;
}
Run Code Online (Sandbox Code Playgroud)
这段代码似乎是对域对象的一个很好的补充,因为它只有输入参数才是域对象本身.似乎是一些重构的完美候选人.但唯一的问题是该对象调用另一个对象的存储库.这让我想把它留在服务类中.
我的问题是这样的:
谢谢你的时间.
编辑注意:不能在这个上使用ORM,所以我不能使用延迟加载解决方案.
编辑注2:我不能改变构造函数来接受参数,因为将要使用反射(不是我的想法)实现域对象的方式.
编辑注3:我不相信批处理对象应该只能合计任何应用程序列表,看起来它应该只能处理该特定批处理中的应用程序.否则,将函数保留在服务类中对我来说更有意义.
无聊的介绍:
我知道 - DDD与技术无关.正如我所看到的 - DDD就是要与产品所有者一起创造无处不在的语言,并以如此简单和结构化的方式将其反映到代码中,以至于它不会被误解或丢失.
但是这里有一个悖论 - 为了摆脱领域模型中应用的技术方面,它变得技术性 - 至少从设计角度来看.
上次我试图遵循DDD - 它最终将域对象之外的整个逻辑变成了"魔法"服务和贫血领域模型.
我已经学会了一些新的忍者技巧,并想知道我这次是否可以处理歌利亚.
问题:
class store : aggregateRoot {
products;
addProduct(product){
if (new FreshSpecification.IsSatisfiedBy(product))
products.add(product);
}
}
class product : entity {
productType;
date producedOn;
}
class productTypeValidityTerm : aggregateRoot {
productType;
days;
}
Run Code Online (Sandbox Code Playgroud)
FreshSpecification应该指明产品是否有异味.为了做到这一点 - 它应该检查产品的类型,找到产品新鲜的时间,并与之进行比较producedOn.善良一点.
但这里出现问题 - productTypeValidityTerm并且productType应该由客户管理.他应该能够自由地添加/修改它们.因为我不能productTypeValidityTerm直接从产品遍历,所以我需要以某种方式查询它们productType.
以前 - 我会创建类似的东西ProductService通过构造函数接收必要的存储库,查询术语,执行一些额外的伏都教并返回布尔值(使相关逻辑远离对象本身并分散谁知道在哪里).
我认为做这样的事可能是可以接受的:
addProduct(product, productTypeValidityTermRepository){...}
Run Code Online (Sandbox Code Playgroud)
但话又说回来 - 我无法自由地从多个规范中编写规范,这是他们的主要优势之一.
所以 - 问题是,在哪里这样做?商店如何知道条款?
我有一个银行帐户域名,如下所示.可以有SavingsAccount,LoanAccount,FixedAccount等.一个用户可以拥有多个帐户.我需要添加一个新功能 - 为用户获取所有帐户.应该写的功能在哪里以及如何?
如果解决方案遵循SOLID原则(开放 - 封闭原则,......)和DDD,那将是很好的.
任何可以使代码更好的重构都是受欢迎的.
注意:AccountManipulator将由网站客户端通过Web服务使用.
namespace BankAccountBL
{
public class AccountManipulator
{
//Whether it should beprivate or public?
private IAccount acc;
public AccountManipulator(int accountNumber)
{
acc = AccountFactory.GetAccount(accountNumber);
}
public void FreezeAccount()
{
acc.Freeze();
}
}
public interface IAccount
{
void Freeze();
}
public class AccountFactory
{
public static IAccount GetAccount(int accountNumber)
{
return new SavingsAccount(accountNumber);
}
}
public class SavingsAccount : IAccount
{
public SavingsAccount(int accountNumber)
{
}
public void Freeze()
{
}
}
}
Run Code Online (Sandbox Code Playgroud)
读: …
我目前正在开发一个项目,其中我有一个其他实体的BankAccount实体.
每个银行帐户作为银行实体的参考,帐号和可选的IBAN.
现在,由于可以验证IBAN,如何确保为帐户设置IBAN时有效.什么是干净的建筑方法?我目前有一个域层,没有任何其他层的引用,我喜欢这种干净的方法(我的灵感来自Eric Evans DDD).幸运的是,可以在不访问任何外部系统的情况下执行IBAN验证,因此在这种情况下我可以使用类似的东西
puclic class BankAccount
{
public string Iban
{
set { // validation logic here }
}
}
Run Code Online (Sandbox Code Playgroud)
但是现在我在考虑如果IBAN验证需要SQL服务器检查,或者外部dll,我会使用什么方法.我该如何实现呢?我是否会创建一个传递给服务的IBAN值对象,该对象决定IBAN是否有效,然后将其设置为BankAccount实体?或者我会创建一个允许实施IBAN并在之前执行验证的工厂?
谢谢你的帮助!