Tag: 域驱动设计

我的DDD工厂类应该采用哪些方法?

我正在努力了解我的工厂类应该在我的DDD项目中做什么。 是的,工厂应该用于创建对象,但究竟应该做什么。 考虑以下工厂类: public class ProductFactory { private static IProductRepository _repository; public static Product CreateProduct() { return new Product(); } public static Product CreateProduct() { //What else would go here? } public static Product GetProductById(int productId) { //Should i be making a direct call to the respoitory from here? Greener.Domain.Product.Product p = _repository.GetProductById(productId); return p; […]

具有持久性无知对象的持久性和域事件

我一直在研究域驱动设计和域事件 。 我非常喜欢这些事件提供的关注点的分离。 我遇到了持久化域对象和提升域事件的问题。 我想在域对象中引发事件,但我希望它们是持久性无知的。 我用这个Checkout方法创建了一个基本的ShoppingCartService : public void Checkout(IEnumerable cart, Customer customer) { var order = new Order(cart, customer); _orderRepositorty.Add(order); _unitOfWork.Commit(); } 在此示例中, Order的构造函数将引发OrderCreated事件,该事件可由某些处理程序处理。 但是,我不希望在实体尚未持久化或以某种方式持久化失败时引发这些事件。 为了解决这个问题,我想出了几个解决方案: 1.提升服务中的事件: 我可以在服务中引发事件,而不是在域对象中引发事件。 在这种情况下, Checkout方法将引发OrderCreated事件。 这种方法的一个缺点是,通过查看Order域对象,不清楚哪些事件是由哪些方法引发的。 此外,开发人员必须记住在其他地方创建订单时提出事件。 感觉不对劲。 2.队列域事件 另一种选择是对域事件进行排队,并在持久成功时引发它们。 这可以通过using语句来实现,例如: using (DomainEvents.QueueEvents()) { var order = new Order(cart, customer); _orderRepositorty.Add(order); _unitOfWork.Commit(); } QueueEvents方法会将布尔值设置为true ,而DomainEvents.Raise方法会将事件排队,而不是直接执行它。 在QueueEvent的dispose回调中,执行排队事件,确保已经发生了持久化。 这似乎相当棘手,它需要服务知道域对象中引发了哪个事件。 在我提供的示例中,它也只支持一种类型的事件,但是,这可以解决。 3.坚持域名活动 […]

在C#中实现DDD实体类

我现在开始使用DDD,我已经找到了一个很好的ValueObject实现,但我似乎找不到任何好的实体实现,我想要一个通用的基本实体类型,它将具有一个ID(规范需要)和实现当前的平等操作。 什么是最优雅的解决方案?

具有行为和ORM的丰富域模型

在观看了Jimmy Bogard( http://ndcoslo.oktaset.com/Agenda )的NDC12演示文稿“Crafting Wicked Domain Models”之后,我正在徘徊如何坚持这种域模型。 这是演示文稿中的示例类: public class Member { List _offers; public Member(string firstName, string lastName) { FirstName = firstName; LastName = lastName; _offers = new List(); } public string FirstName { get; set; } public string LastName { get; set; } public IEnumerable AssignedOffers { get { return _offers; } } […]

如何设计具有复杂初始化的不可变对象

我正在学习DDD,并且遇到了“值对象”应该是不可变的声明。 我理解这意味着对象状态在创建后不应该更改。 这对我来说是一种新的思维方式,但在许多情况下它是有道理的。 好的,所以我开始创建不可变的值对象。 我确保他们将整个状态作为构造函数的参数, 我不添加属性设置器, 并确保不允许任何方法修改内容(仅返回新实例)。 但现在我想创建这个包含8个不同数值的值对象。 如果我创建一个具有8个数字参数的构造函数,我觉得它不会很容易使用,或者更确切地说 – 传递数字时很容易出错。 这不是一个好的设计。 所以问题是:是否还有其他方法可以使我的不可变对象变得更好..,在C#中可以用来克服构造函数中的长参数列表的任何魔法? 我很想听听你的想法.. 更新:在任何人提到它之前,这里讨论了一个想法: C#中的不可变对象模式 – 你怎么看? 有兴趣听听其他建议或评论。

DDD实体利用服务

我有一个应用程序,我正在尝试用至少一个名义上的DDD类型域模型构建,并且正在与某个部分进行斗争。 我的实体有一些业务逻辑,它使用我目前在某些域服务中的一些财务计算和速率计算,以及我在一个值对象中放置的一些常量值。 我正在努力解决如何让实体使用域服务中的逻辑,或者这些服务中的逻辑是否属于那里。 这是我到目前为止: public class Ticket { public Ticket(int id, ConstantRates constantRates, FinancialCalculationService f, RateCalculationService r) { Id = id; ConstantRates = constantRates; FinancialCalculator = f; RateCalculator = r; } private FinancialCalculationService FinancialCalculator { get; set; } private RateCalculationService RateCalculator { get; set; } private ConstantRates ConstantRates { get; set; } public int Id […]

你如何在你的DDD中编写身份validation,角色和安全性?

如何在C#域驱动设计项目中实现角色和安全性? 关于它是应该由调用应用程序(ASP.NET MVC)还是在域模型本身(模型实体和服务)中实现,我们有一些争论。 有些人认为它应该在网站本身,因为那是身份validation已经存在的地方。 但这意味着每次与核心业务系统集成时都必须重新实现安全性。 例如:管理员应该能够在系统中执行任何操作,例如编辑和删除记录(即他们可以删除用户的订单)。 另一方面,用户应该只能编辑和删除他们自己的记录(即他们可以在购物车中添加/删除项目)。 顺便说一句,这里有一个很好的论文,涵盖了有关DDD和安全性的7种不同场景: 域驱动设计中的安全性 第4章安全服务设计方案 4.1场景1:作为常规服务的安全服务 4.2场景2:UI中嵌入的安全性 4.3场景3:封装域模型的安全服务 4.4场景4:安全服务作为UI的网关 4.5场景5:安全服务作为UI的适配器 4.6场景6:AOP与适配器集成的安全服务 4.7场景7:与AOP集成的安全服务 我个人倾向于使用PostSharp进行AOP,但之前没有做过多少工作,我对犹豫不决。

洋葱建筑

我正在为即将到来的内部应用程序设置一个项目结构,该应用程序试验了Palermo提出的Onion Architecture( http://jeffreypalermo.com/blog/the-onion-architecture-part-3/ )。 我遵循他的指导方针,但到目前为止我需要对项目结构进行一些validation。 在图表之前,问题: 我认为参考文献都是正确的(根据图表设置,箭头表示’有参考’),但有些validation会很好。 我应该在依赖性解析层中添加什么? 这是帮助者去的地方吗? 这引用了所有其他项目? Web服务和UI如何与DAL通信? (通过核心?怎么样?) 应该去哪里? [我知道的广泛问题……] 简化的概念图如下(文件夹代表名称空间):

DDD:实体的集合和存储库

假设我有 public class Product: Entity { public IList Items { get; set; } } 假设我想找到一个带有最大值的项…我可以添加方法Product.GetMaxItemSmth()并使用Linq( from i in Items select i.smth).Max() )或手动循环或其他。 现在,问题是这会将完整的集合加载到内存中。 正确的解决方案是执行特定的数据库查询,但域实体无权访问存储库,对吧? 所以我要么 productRepository.GetMaxItemSmth(product) (这很丑陋,没有?),或者即使实体有权访问存储库,我也使用来自实体的IProductRepository product.GetMaxItemSmth() { return Service.GetRepository().GetMaxItemSmth(); } 这也是丑陋的,是代码的重复。 我甚至可以去看看并进行扩展 public static IList GetMaxItemSmth(this Product product) { return Service.GetRepository().GetMaxItemSmth(); } 哪个更好只是因为它没有真正使存储库的实体混乱…但仍然是方法重复。 现在,这是否是再次使用product.GetMaxItemSmth()或productRepository.GetMaxItemSmth(product) 。 我错过了DDD的东西吗? 这里的正确方法是什么? 只需使用productRepository.GetMaxItemSmth(product) ? 这是每个人都使用和满意的吗? 我觉得这不对…如果我不能从产品本身访问产品的Items ,为什么我在Product中需要这个集合? 然后,如果Product无法使用特定查询并在没有性能命中的情况下访问其集合,那么Product可以做任何有用的事吗? […]

DDD(域驱动设计),如何处理实体状态更改,以及封装需要处理大量数据的业务规则

public class Person { public IList SpecialBirthPlaces; public static readonly DateTime ImportantDate; public String BirthPlace {get;set;} public DateTime BirthDate { set { if (BirthPlace!=null && value < ImportantDate && SpecialBirthPlaces.Contains(BirthPlace)) { BirthPlace = DataBase.GetBirthPlaceFor(BirthPlace, value); } } } } 这是尝试在我的域模型中封装一个简单的规则。 我试图捕获的规则是:当出于某种原因,我们更新一个人的出生日期(例如,原始用户输入中存在错误)时,我们需要检查该人的出生地并将其替换为来自其他人的其他值。数据库,如果它在我们的数据库中列为特殊的出生地。 但是,我在实现它时有两个问题: 此规则修改域实体状态(属性),我需要在用户界面中反映此更改。 我的域名模型是POCO。 我可以把这个逻辑放在ViewModel中,但这是错误的,因为它不是UI逻辑。 这是我需要捕获的一个重要的域规则。 我的SpecialBirthPlaces列表非常大,每次我从数据库中获取客户时我都不想填充它。 此外,当规则得到满足时,我需要替换Birthplace。 正如我所说,特殊的出生地和替代品的列表非常大,并存储在数据库中。 如何在DDD风格中实现我需要的逻辑?