OO编码 - 是否使用对象管理器?

时间:2009-07-07 14:36:00

标签: oop domain-driven-design

我喜欢你的意见的建筑风格点:

我的ORM给了我一个User对象,它对应于我系统的用户。我想开发一堆处理用户的方法 - GetByUsername(),Authenticate(),VerifyLoginPassword()等。但是我觉得其中一些方法并不真正属于User类 - 例如GetByUsername()至少感觉像是User的静态方法,但是拥有另一个类不是更“干净”,比如“UserManager”,它为我们提供了这些用户管理类型的任务吗?用户实例包含Authenticate()方法似乎有点奇怪,例如,如果它是进行身份验证的安全系统吗?

我担心的是我最终跟随这个模型到User类只不过是一个结构,而我的User Manager和Security Manager类实际上完成了所有方法的工作。让所有这些管理器类操作轻量级对象并不是“OO”。

对此哲学问题的现有技术的任何想法或链接将不胜感激!

7 个答案:

答案 0 :(得分:6)

在这一点上,您似乎正在超越将对象定义为“狗是一个动物”,并根据角色,责任和行为进入对象定义

我会推荐这本书来帮助你实现这一转变,并真正“得到它”:

Object Design: Roles, Responsibilities, and Collaboration

我对你的具体问题没有答案,因为这是一个基本的设计决定,你真的应该了解“更大的图景”。本书将为您提供责任驱动设计原理和技术的良好基础。

享受,

Robert C. Cartaino

答案 1 :(得分:3)

Martin Fowler有一些有用的views on this

  

基本选择是服务定位器和依赖注入之间。第一点是两个实现都提供了天真示例中缺少的基本解耦 - 在这两种情况下,应用程序代码都独立于服务接口的具体实现。这两种模式之间的重要区别在于如何为应用程序类提供该实现。使用服务定位器,应用程序类通过发送给定位器的消息明确地请求它。使用注入没有明确的请求,服务出现在应用程序类中 - 因此控制反转。

     

控制反转是框架的一个共同特征,但它是有代价的。当您尝试调试时,它往往很难理解并导致问题。所以总的来说,我宁愿避免它,除非我需要它。这并不是说这是一件坏事,只是因为我认为它需要通过更简单的替代方案来证明自己的合理性。

答案 2 :(得分:3)

  

让所有这些管理器类操作轻量级对象感觉不太“OO”。

我不知道这是不是“OO”,但对我而言,它感觉非常像MVC和分离问题。拥有非常轻量级的业务类(他们只是数据容器),然后是移动它们的存储库对象是一种常见的模式。

答案 3 :(得分:1)

您可以继续重构User类中的所有功能,但正如您所说,最终可能没有留下任何内容。此时,您可以选择评估您创建的所有其他类,然后对这些类中的每一个进行单独判断,如果这些类包含足够的功能以保证全新的类,则根据具体情况决定。< / p>

如果您认为其中某些类太小,则可以将其功能重新放入User类中。我认为在User上有一个Validate函数没有错,而不是只有一个UserValidation类,只有一个方法。

答案 4 :(得分:1)

当你说这些方法可能不属于用户对象时,我认为你很省钱。可以讨论Get / Search / Save方法,但我认为它们本身不应该在业务对象上,应该使用Repository(存储库模式),或者通过Query Objects你不希望在存储库中抽象出你的ORM。

就身份验证而言,最好有一组负责身份验证的类,并将其完全从用户对象中删除。这组类可以知道用户对象,或者更好的是他们应该知道诸如Credential之类的合同。

答案 5 :(得分:0)

您所描述的情况与对象是否遵循自助服务或适配器模式以保存到存储库(即数据库)有关。

自助服务会将对象保存为“{1}}中的”自身“,而适配器模式则为myObjectInstance.Save()

适配器表单通常受到青睐,因为它从对象中删除了任何存储库功能。

答案 6 :(得分:0)

我喜欢用不同的方式。由于不涉及业务逻辑,因此这些方法并不真正属于域。我想使用命令和查询隔离原则

GetByUsername() - 它一个真正不需要任何业务逻辑的查询

Authenticate(),VerifyLoginPassword() - 这些是验证逻辑,不应该在域中完成。请参阅此文档Set Based validation in Domain