编程模式/架构问题

问题描述 投票:0回答:6

我目前正在开发一个项目,其中我有一个其他实体的 BankAccount 实体。

每个银行账户都是对银行实体、账号和可选的 IBAN 的引用。

既然IBAN可以验证,那么如何确保为账户设置IBAN时有效呢?什么是干净的架构方法?我目前有一个领域层,没有任何其他层的参考,我喜欢这种干净的方法(我受到 Eric Evans DDD 的启发)。幸运的是,可以在不访问任何外部系统的情况下执行 IBAN 验证,因此在这种情况下我可以有类似的东西

public class BankAccount
{
  public string Iban
  {
     set { // validation logic here }
  }
}

但现在我在想,如果 IBAN 验证需要 SQL 服务器检查,或者外部 dll,我会使用什么方法。我将如何实施?我是否会创建一个传递给服务的 IBAN 值对象,该对象决定 IBAN 是否有效,然后将其设置为 BankAccount 实体? 或者我会创建一个允许实例化 IBAN 并之前执行验证的工厂吗?

感谢您的帮助!

architecture domain-driven-design design-patterns
6个回答
5
投票

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

具体来说,我会有一个名为 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 号码的对象,其结构如下(未经过任何拉伸优化):

Boolean SetIBAN(IIBANValidator validator, String iban) {
  Boolean result = false;
  if (validator.Validate(iban)) {
    Iban = iban;
    result = true;
  }

  return result;
}

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

最终的代码看起来像这样:

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

显然在运行时你可以传递任何你想要的验证器实例。


2
投票

IBAN 号码不是一个简单的字符串,如果它是一个实际的班级怎么办?您可以在构造函数中实现验证(如果验证没有外部依赖项),或者可以使用工厂来提供 IBAN 实例(如果需要外部验证)。重要的是,如果您有 IBAN 实例,您就知道它是有效的 IBAN 号码。

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


1
投票

您可以为存储库实现使用依赖注入规范。不过,你会失去一点凝聚力。

更多详细信息可以在这里找到。


0
投票

验证逻辑放置在哪里取决于执行验证所需的信息。验证应该在具有足够信息的类型内执行。另一方面,还必须考虑验证逻辑的复杂性。例如,如果您仅将电子邮件数据附加到人员类型,则可以在人员类型中“就地”进行验证,因为验证并不复杂(假设仅检查电子邮件格式)并且人员是唯一的使用者。另一方面,如果您有商店和车库(出售旧东西)类型消耗的交易数据(以商品数据和价格数据为特征),并且验证逻辑表明商品必须属于交易发起者,则将验证放入交易类型中是有意义的.


0
投票

你可以只使用委托来验证,你不需要传递整个接口,谁想要设置它就必须有一个验证器。

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

0
投票

我会让它面向方面并减少耦合。

    [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 的基类调用的,它会迭代所有具有验证属性的属性。验证属性是从 ValidationAttribute 类派生的自定义属性,它可以针对类属性。

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

© www.soinside.com 2019 - 2024. All rights reserved.