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.CreditCard
class should not be calling out to Singletons (I am of the position that global access to a Singleton is bad practice)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?
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.