编程模式/架构问题

时间:2010-01-05 14:07:06

标签: architecture domain-driven-design design-patterns

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

每个银行帐户作为银行实体的参考,帐号和可选的IBAN。

现在,由于可以验证IBAN,我如何确保为帐户设置IBAN时有效。什么是干净的建筑方法?我目前有一个域层,没有任何其他层的引用,我喜欢这种干净的方法(我的灵感来自Eric Evans DDD)。幸运的是,可以在不访问任何外部系统的情况下执行IBAN验证,因此在这种情况下我可以使用类似

的内容
puclic class BankAccount
{
  public string Iban
  {
     set { // validation logic here }
  }
}

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

感谢您的帮助!

6 个答案:

答案 0 :(得分: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");

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

答案 1 :(得分:2)

而不是IBAN号码是一个简单的字符串,如果它是一个真正的类?您可以在构造函数中实现验证(如果验证没有外部依赖关系),或者您可以使用工厂提供IBAN实例(如果您需要外部验证)。重要的是,如果你有一个IBAN实例,你知道它是一个有效的IBAN号码。

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

答案 2 :(得分:1)

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

可以找到更多详细信息here

答案 3 :(得分:0)

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

答案 4 :(得分:0)

您可以使用委托进行验证,您不需要传递整个界面,谁想要设置它必须有验证器。

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

答案 5 :(得分: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 BankAccount 的基类调用,它遍历具有validation属性的所有属性。验证属性是从ValidationAttribute类派生的自定义属性,可以定位类属性。

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