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