我正在寻找有关在何处添加域实体验证规则以及实施最佳实践的建议.我做了搜索,没找到我要找的东西,或者我错过了.
我想知道建议的方法是验证属性不是null,在某个范围或长度等等...我已经看到了几种使用IsValid()和其他关于在构造函数中执行的讨论的方法,所以实体从不处于无效状态,或者使用预处理和后处理,而其他实体使用FluentValidation api,不变量如何影响DRY和SRP.
当使用App Service,Bounded Context,Domain Service,Aggregate Root,Entity layering时,有人能给我一个很好的例子来说明在哪里进行这些检查.这是怎么回事,最好的方法是什么?
谢谢.
domain-driven-design dry single-responsibility-principle invariants
刚刚输入这个问题时出现了一个有趣的线索.我不认为它回答了我的问题.
我一直在使用.NET MVC3,在那里需要一个贫血的模型.查看模型和编辑模型最好是作为可以从控制器传递到视图的哑数据容器.任何类型的应用程序流都应来自控制器,并且视图处理UI问题.在MVC中,我们不希望模型中有任何行为.
但是,我们也不希望控制器中有任何业务逻辑.对于较大的应用程序的最好保持域代码单独的和独立的模型,视图和控制器(和HTTP一般为此事).因此,有一个单独的项目提供,任何事情之前,领域模型(以实体和值对象,根据DDD组合成聚集).
我做了一些尝试从一个贫血模型对域代码更丰富的一个,离开,我想放弃.在我看来,包含数据和行为的实体类都违反了SRP.
以网络上的一个非常常见的场景为例,撰写电子邮件.鉴于某些事件,在给定EmailTemplate,EmailAddress和自定义值的情况下,域的责任是撰写EmailMessage对象.模板作为具有属性的实体存在,并且自定义值由用户提供为输入.我们还为了论证而说,EmailMessage的FROM地址可以由外部服务(IConfigurationManager.DefaultFromMailAddress)提供.鉴于这些要求,似乎富域模型可以赋予EmailTemplate组成EmailMessage的责任:
public class EmailTemplate
{
public EmailMessage ComposeMessageTo(EmailAddress to,
IDictionary<string, string> customValues, IConfigurationManager config)
{
var emailMessage = new EmailMessage(); // internal constructor
// extension method
emailMessage.Body = this.BodyFormat.ApplyCustomValues(customValues);
emailMessage.From = this.From ?? config.DefaultFromMailAddress;
// bla bla bla
return emailMessage;
}
}
Run Code Online (Sandbox Code Playgroud)
这是我对富域模型的尝试之一.但是,在添加此方法之后,EmailTemplate负责包含实体数据属性和撰写消息.它大约有15行,并且似乎分散了这个类的真实意味着成为一个EmailTemplate - IMO,它只是存储数据(主题格式,正文格式,附件和可选的/回复地址) ).
我最终将这个方法重构为一个专门的类,由于以前的论点,我们自己负责组成一个EmailMessage,我对此感到非常高兴.事实上,我开始偏爱贫血领域,因为它帮助我将责任分开,使课程和单元测试更短,更简洁,更专注.似乎使实体和其他数据对象"没有行为"可能有助于分离责任.还是我在这里偏离轨道?
domain-driven-design single-responsibility-principle anemic-domain-model
我有一个案例,"告诉,不要问"似乎与"单一责任"原则相冲突.我已经查看了有关该主题的其他讨论,但尚未能够针对这种情况找出最合适的面向对象方法.
我有一个程序,可以读取和操作各种来源的数据集合.我创建了一个类来保存和操作数据("DataSet"类).它包括对数据集执行各种操作的方法,例如比较两个数据集以生成包含差异的新数据集,以及将数据集写入文件.
我现在想对数据集执行一些分析并将结果输出到报告中.我对编码的第一次尝试询问数据集从中提取信息,然后构建报告,但这似乎违背了"告诉,不要问"的原则.那么:我应该将分析方法放在DataSet类中,并告诉数据集分析自己并生成报告吗?这会违反单一责任原则吗?如果我希望将来执行其他类型的分析怎么办-DataSet类可能变得非常臃肿,有许多不同的分析例程,这与它的核心目的无关.
有谁能建议这里最好的方法?是否有解决此问题的特定设计模式?
我正在努力了解SRP,但是,虽然我理解了如何应用它的原因,但我并没有真正看到这样做的好处.考虑这个例子,取自Robert Martin的SRP PDF:
interface IModem
{
void Dial(string number);
void Hangup();
void Send(char c);
char Recv();
}
Run Code Online (Sandbox Code Playgroud)
他建议将其分为两个界面:
interface IModemConnection
{
void Dial(string number);
void Hangup();
}
interface IModemDataExchange
{
void Send(char c);
char Recv();
}
Run Code Online (Sandbox Code Playgroud)
我也一直在阅读这篇文章,它更进了一步:
interface IModemConnection : IDisposable
{
IModemDataExchange Dial(string number);
}
interface IModemDataExchange
{
void Send(char c);
char Recv();
}
Run Code Online (Sandbox Code Playgroud)
在这一点上,我理解functional(Send / Recv)和non-functional(Dial / Hangup)方面的含义,但我没有看到在这个例子中分离它们的好处.考虑到这个基本实现:
class ConcreteModem : IModemConnection
{
public IModemDataExchange Dial(string number)
{
if (connection …Run Code Online (Sandbox Code Playgroud) 我正在重构当前使用数据库和ActiveRecord的rails应用程序,因此它使用JSON API(Sinatra)而不是数据库.
重构模型的最佳方法是什么?API将返回与数据库相同的所有信息.事实上,它是相同的数据库,但是对于可扩展性和需要访问数据的多个应用程序,我们需要将其转换为API.理想情况下,只有模型需要更改,理想情况下我可以在rails应用程序中保留一些验证.
如何更改模型,以便通过API调用而不是ActiveRecord数据库调用来检索和保存实例?
假设我有一个如下所示的类:
internal class SomeClass
{
IDependency _someDependency;
...
internal string SomeFunctionality_MakesUseofIDependency()
{
...
}
}
Run Code Online (Sandbox Code Playgroud)
然后我想添加相关的功能,但是使用不同的依赖来实现其目的.也许类似如下:
internal class SomeClass
{
IDependency _someDependency;
IDependency2 _someDependency2;
...
internal string SomeFunctionality_MakesUseofIDependency()
{
...
}
internal string OtherFunctionality_MakesUseOfIDependency2()
{
...
}
}
Run Code Online (Sandbox Code Playgroud)
当我为这个新功能编写单元测试(或者更新我对现有功能的单元测试)时,我发现自己创建了SomeClass(SUT)的新实例,同时传入null以获取我不需要的依赖项对于我想要测试的特定功能.
这对我来说似乎是一种难闻的气味,但我发现自己走这条路的原因是因为我发现自己正在为我介绍的每一项新功能创建新的类.这似乎也是一件坏事,所以我开始尝试将类似功能组合在一起.
我的问题:如果一个类的所有依赖关系都被它的所有功能所消耗,即如果不同的功能位使用不同的依赖关系,那么它们是否应该存在于不同的类中?
如问题所示,
由于我们使用像IsNullOrEmpty或IsNullOrWhiteSpace这样的字符串函数作为函数显示的名称,这些函数执行多个作业,是不是违反了SRP?
相反,它不应该是string.isValid(Enum typeofValidation)而不是使用策略模式来选择正确的策略进行验证.
或者在实用程序类或静态类中违反SRP是完全可以的.
language-agnostic oop single-responsibility-principle multiple-inheritance solid-principles
我有一个ASP.NET MVC应用程序使用控制器和操作上的授权属性.这一直运作良好,但出现了新的皱纹.
对象:装运
角色:航运,会计,一般用户
装运在工作流程中移动.在状态A中,它只能由Shipping进行编辑.在状态B中,它只能通过会计编辑.
我有一个ShipmentController和一个Edit Action.我可以使用Authorization属性将Edit操作限制为仅限于这两个角色,但这并不区分Shipment所处的状态.我需要在服务调用之前在操作内部执行一些授权以确定用户是否真的有权执行编辑操作.
所以我有两个问题:
1)在Action中获得授权的好方法.Controller Action调用服务,然后服务对Shipment对象进行适当的调用(更新数量,更新日期等).我确信我希望Shipment对象不受任何授权要求的影响.另一方面,如果我希望服务对象知道授权,我没有真正掌握.这有什么好的模式吗?
2)我的问题实际上是设计糟糕的症状吗?我应该有一个StateAShipmentController和StateBShipmentController而不是ShipmentController吗?我没有在Shipment对象中内置任何多态性(状态只是一个枚举),但也许我应该,也许控制器应该反映出来.
我想我会采用更一般的解决方案,而不是针对我的情况.我只想提供一个例子来说明这个问题.
谢谢!
model-view-controller asp.net-mvc authorization design-patterns single-responsibility-principle
维基百科以这种方式描述单一责任原则:
单一责任原则规定每个对象应该只有一个责任,并且该责任应该由类完全封装.其所有服务应与该责任严格一致.
MVC中控制器的传统使用似乎导致程序员违反了这一原则.拿一个简单的留言簿控制器和视图.控制器可能有两个方法/操作:1)Index()和2)Submit().Index()显示表单.Submit()处理它.这两种方法是否代表两种不同的责任?如果是这样,单一责任如何进入?
model-view-controller single-responsibility-principle solid-principles
single-responsibility-principle ×10
c# ×2
oop ×2
api ×1
asp.net-mvc ×1
class-design ×1
dry ×1
invariants ×1