Architecture 编程模式/架构问题

Architecture 编程模式/架构问题,architecture,domain-driven-design,design-patterns,Architecture,Domain Driven Design,Design Patterns,我目前正在从事一个项目,其中我有一个银行账户实体,用于其他实体 每个银行账户作为银行实体、账号和可选IBAN的参考 既然可以验证IBAN,那么如何确保为帐户设置的IBAN有效。什么是干净的体系结构方法?我目前有一个域层,没有任何参考任何其他层,我喜欢这种干净的方法(我的灵感来自Eric Evans DDD)。幸运的是,IBAN验证可以在不访问任何外部系统的情况下执行,因此在本例中,我可以使用 puclic class BankAccount { public string Iban {

我目前正在从事一个项目,其中我有一个银行账户实体,用于其他实体

每个银行账户作为银行实体、账号和可选IBAN的参考

既然可以验证IBAN,那么如何确保为帐户设置的IBAN有效。什么是干净的体系结构方法?我目前有一个域层,没有任何参考任何其他层,我喜欢这种干净的方法(我的灵感来自Eric Evans DDD)。幸运的是,IBAN验证可以在不访问任何外部系统的情况下执行,因此在本例中,我可以使用

puclic class BankAccount
{
  public string Iban
  {
     set { // validation logic here }
  }
}
但现在我在想,如果IBAN验证需要SQL server检查(例如)或外部dll,我将使用什么方法。我将如何实现这一点。我是否会创建一个IBAN值对象,该对象被传递给一个服务,该对象决定IBAN是否有效,然后将其设置为BankAccount实体? 或者我会创建一个工厂,允许它实例化iBAN并在之前执行验证吗


谢谢你的帮助

我会使用某种形式的控制反转

具体来说,我会有一个名为IIBANValidator的接口。验证IBAN的各种方法应实现该接口。例如:

interface IBANValidator {
    Boolean Validate(string iban);
}

class SqlBanValidator : IBANValidator {

    public bool Validate(string iban) {
        // make the sql call to validate..
        throw new NotImplementedException();
    }

}
然后,我的BankAccount类中会有一个方法,它接受一个实现IIBANValidator和IBAN编号的对象,其结构如下(未经过任何扩展优化):

此时,您的BankAccount类不必依赖于您的验证器,您可以随意交换它们,最终它是非常干净的

最终的代码如下所示:

BankAccount account = new BankAccount();
account.SetIBAN(new SqlBanValidator(), "my iban code");

显然,在运行时,您可以传递所需的任何验证器实例。

您可以实现一个规范,该规范使用依赖项注入。不过,你会失去一点凝聚力


可以找到更多详细信息。

将验证逻辑放在何处取决于执行该验证所需的信息。验证应该在具有足够信息的类型中执行。另一方面,也必须考虑验证逻辑的复杂性。例如,如果您仅将电子邮件数据附加到Person type,则可以在Person type中“就地”验证,因为验证并不复杂(假设仅选中电子邮件格式),Person是唯一的消费者。另一方面,如果商店和车库(出售旧物品)类型使用的交易数据(以商品数据和价格数据为特征)具有验证逻辑,即商品必须属于交易发起人,则有必要将验证放在交易类型中。

而不是将IBAN编号作为简单字符串,如果这是一门真正的课呢?您可以在构造函数中实现验证(如果验证没有外部依赖项),也可以使用工厂提供IBAN实例(如果需要外部验证)。重要的是,如果你有一个IBAN实例,你知道它是一个有效的IBAN号码


BankAccount是否应该有一个可变的IBAN号码?我对银行业不是很熟悉,但这听起来像是个可怕的想法。

您可以使用委托进行验证,您不需要传递整个接口,想要设置它的人必须有一个验证程序

public delegate bool Validation(IBAN iban);
void SetIBAN(IBAN iban, Validation isValid){ 
  if(!isValid(iban)) throw new ArgumentException();
...}

我将使其面向方面并减少耦合

    [IBANVlidator(Message = "your error message. can also come from culture based resouce file.")]
    public string IBAN
    {
        get
        {
            return _iban;
        }
        set
        {
            this.validate();
            _iban = value;
        }
    }
this.validate()是从BankAccount的基类调用的,该基类遍历具有validation属性的所有属性。validation属性是从ValidationAttribute类派生的自定义属性,它可以以类属性为目标


IBAN验证责任则交给IBANValidator验证属性。当然,此设计可以改进,这超出了本答案的范围。

我想您最终回答了自己的问题。Evans域驱动设计中的规范模式突然出现在我的脑海中。我会对验证器进行空检查,以防没有可用的验证器。
    [IBANVlidator(Message = "your error message. can also come from culture based resouce file.")]
    public string IBAN
    {
        get
        {
            return _iban;
        }
        set
        {
            this.validate();
            _iban = value;
        }
    }