I have a value object to hold a user id number as a string. This number has a unique format throughout my domain. So, it's being validated inside the object during instantiation and an exception is thrown if it's not of the correct format. The sample class is given below (all codes are in PHP):
class IdentityNumber
{
public function __construct(string $id)
{
$this->validate($id);
$this->id = $id;
}
private function validate(string $id): void
{
if (! preg_match('/^\d{2}-\d{5}$/', $id)) {
throw new \Exception("Invalid identity number");
}
}
}
Up to this everything makes sense.
Now, the issue is: if I need to know whether a string is a valid identity number, I'll have do the following:
function isValidIdNumber(string $id): bool
{
try {
new IdentityNumber($id);
return true;
} catch (\Exception $e) {}
return false;
}
Which is very ugly!!
So, I suggested writing the validator as a static function, and changing the class to this:
class IdentityNumber
{
public function __construct(string $id)
{
if (! static::isValid($id)) {
throw new \Exception("Invalid identity number");
}
$this->id = $id;
}
public static function isValid(string $id): bool
{
return (bool) preg_match('/^\d{2}-\d{5}$/', $id);
}
}
This way, I could check the validity of an id number, outside the class without instantiation, like:
IdentityNumber::isValid($id)
But a senior, who is much more familiar with the DDD concepts, said that this is bad practice since it makes the value object look like a service object. But I cannot see how this could be bad and now I'm confused.
Can someone tell me if there is something wrong in using static validator function in value objects that are certain to be the same format throughout the domain (strictly within DDD concepts)? If yes, what are the alternatives?