当创建的类也需要运行时值时进行依赖注入?

发布于 2024-09-07 00:16:06 字数 738 浏览 7 评论 0原文

假设您将系统划分为价值对象和服务对象(如“以测试为指导,发展面向对象的软件”中所建议的那样。Misko Hevery 称这些为“可更新对象”和“可注入对象”)。

当您的某个价值对象突然需要时会发生什么访问服务来实现它的方法?

假设您有一个很好的简单 Value 对象,它是不可变的,包含一些信息,就这样吧:

CreditCard card = new CreditCard("4111-1111-1111-1111", "07/10");
if (card.isValid())
{
  // do stuff
} 
else
{
  // don't do stuff
}

到目前为止,一切都很好。 isValid() 在卡号上实现校验位算法并返回 true/false

现在,假设我希望通过根据当前时间验证到期日期来增强系统,您建议如何完成此操作。破坏值对象/服务对象范式?我希望此类继续可进行单元测试,

  • 现在具有依赖项,但由于它的创建方式无法注入,因此依赖项。 。
  • CreditCard 类不应该调用 Singleton(我认为全局访问 Singleton 是不好的做法)
  • 将行为放在 CreditCardVerificationService.validateCard()< 上 /code> 意味着必须重新访问所有现有代码。 isValid() 的实现正在泄漏。

我知道可以采取一些措施来解决这个问题,但是最干净的方法是什么?

Assume you divide up your systems in Value objects and Services objects (as suggested in "Growing Object-Oriented Software, Guided by Tests". Misko Hevery calls these "newables" and "injectables".

What happens when one of your value objects suddenly needs to access a service to implement it's methods?

Let's say you have a nice simple Value object. It's immutable, holds a few bits of information and that's about it. Let's say we use it something like this:

CreditCard card = new CreditCard("4111-1111-1111-1111", "07/10");
if (card.isValid())
{
  // do stuff
} 
else
{
  // don't do stuff
}

So far so good. isValid() implements a check digit algorithm on the card number and returns true/false.

Now, let's say I wish to enhance the system by validating the expiry date against the current time. How would you suggest this is done without breaking the Value object/Service object paradim? I should like this class to continue to be unit testable.

  • CreditCard now has a dependency, but because of the way it is created it can not be injected, so dependency injection is out.
  • The CreditCard class should not be calling out to Singletons (I am of the position that global access to a Singleton is bad practice)
  • Putting the behaviour on CreditCardVerificationService.validateCard() means all the existing code has to be revisited. The implementation of isValid() is leaking out.

I know there are things that can be done to get around this, but what is the cleanest way?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

失退 2024-09-14 00:16:06

我认为验证任何东西并不是 CreditCard 对象的工作。工厂将验证校验位以确保它正在实例化合格的卡,而验证服务将验证卡的有效期/$限制。

I would argue that it isn't a CreditCard object's job to validate anything. A factory would validate the check digits to ensure that it is instantiating a conforming card, while a verification service would validate the card for expiration/$ limit.

谜兔 2024-09-14 00:16:06

我很想说 CreditCard 不是值对象。

来自 C2 wiki

价值对象的例子是事物
例如数字、日期、金钱等
字符串。通常,它们很小
使用相当广泛的对象。
他们的身份基于他们的状态
而不是他们的对象身份。
这样,您就可以拥有多个副本
具有相同的概念值对象。

值对象不是
业务对象/参考对象。一个
BusinessObject/ReferenceObject 是
你在世界上发现的东西,同时
ValueObject 是一个度量或
某事物的描述。

如果CreditCardNumber 可以是一个值对象,那么CreditCard 看起来更像是一个包含一些业务逻辑(例如验证)的业务对象。

我通常有价值对象、服务和业务对象。我不知道“发展面向对象的软件”,但将自己限制为仅值对象和服务对我来说似乎很奇怪。

I would be tempted to say that CreditCard is not a Value Object.

From the C2 wiki:

Examples of value objects are things
like numbers, dates, monies and
strings. Usually, they are small
objects which are used quite widely.
Their identity is based on their state
rather than on their object identity.
This way, you can have multiple copies
of the same conceptual value object.

A value object is not a
BusinessObject/ReferenceObject. A
BusinessObject/ReferenceObject is
something you find in the world, while
a ValueObject is a measure or
description of something.

If CreditCardNumber could be a value object, CreditCard looks more like an business object which contains some business logic, e.g. validation.

I usually have Value Object, Service and Business Object. I don't know about "Growing Object-Oriented Software", but restricting yourself to only Value Object and Service seems odd to me.

妞丶爷亲个 2024-09-14 00:16:06

我会将 CreditCard 称为实体,而不是值对象,因为它可能是持久的并且具有唯一的标识。

不管怎样,实体类使用服务类应该是完全没问题的。如果不需要在运行时根据外部配置选择所述服务的实现,那么我只需在客户端方法内实例化并使用所需的服务类。与某些人的想法相反,这并不排除单元测试,因为可以使用模拟工具进行隔离。

如果需要在运行时选择服务实现,则可以使用服务定位器。该模式可以为模拟/伪造提供直接支持,而不需要专门的模拟工具。使用支持注入“新”对象的 DI 框架将是另一种选择。

I would call CreditCard an entity rather than a value object, since it's likely to be persistent and have a unique identity.

Anyway, it should be perfectly fine for an entity class to use service classes. If the implementations of said services don't need to be selected at runtime based on external configuration, then I would simply instantiate and use the desired service class inside the client method. Contrary to what some may think, this doesn't preclude unit testing, as a mocking tool can be used for isolation.

If the service implementation does need to be selected at runtime, than a Service Locator could be used. This pattern can provide direct support for mocking/faking, without the need for a specialized mocking tool. Use of a DI framework supporting injection into "newed" objects would be another alternative.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文