Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should Value Objects Contain Technical Validation For Input Parameters?

As DDD practitioner advise, business rule's validations must be implemented inside domain objects (Entities, Value Objects and Domain Services) and follow their own context also somewhere i've read that we should put technical validations (such as check length, correct input formats, correct data type, ...) out of domain model and somewhere like application layer to keep domain object clear.

Now my question is this:

If we had a Value Object for credit card number, should we still keep technical validation out of our Value Object? In other words the "Self Validated" term is not involved with technical validations when we deal with Value Objects?

When an incorrect debit card's number or even an email address has a potential to break business rules, what then?

For more clarity please notice this Value Object which represent an Debit Card Number:

    public class DebitCardNumber : ValueObject
{
    public string Number { get;private set; }

    public CreditCardNumber(string number)
    {
        Validation(number);

        this.Number = number;
    }

    private void Validation(string number)
    {
        if (String.IsNullOrWhiteSpace(number))
        {
            throw new CardNumberCanNotBeEmptyException();
        }

        if (number.Length != 16)
        {
            throw new CardNumberLengthMustBeSixteenDigitException();
        }

        int sum = 0;
        for (int i = 1; i <= 16; i++)
        {
            if (!char.IsDigit(number[i - 1]))
            {
                throw new ValueContainsSomeNonDigitCharacterException();
            }

            int m = (i % 2 == 0 ? 1 : 2);
            int a = (int.Parse(number[i - 1].ToString()) * m);

            while (a > 9)
            {
                a -= 9;
            }

            sum += a;
        }

        if ((sum % 10) > 0)
        {
            throw new ValueIsNotCorrectAsACardNumberException() 
                { Message = "Perhaps some digits has been entered in wrong order or they are incorrect." };

        }
    }
}

According to this code there is a Validation method that carry out an algorithm to find out either is it Card Number's format correct or not? do you think is it right place for this type of validations?

like image 854
Masoud Sedghi Avatar asked Aug 30 '16 10:08

Masoud Sedghi


People also ask

Should value objects have logic?

Value objects are identified by the immutable value they carry, are always valid, can have logic, and portray domain meaning.

What is the purpose of value objects?

Value Objects can be especially useful as a means for describing concepts in an application that have intrinsic rules but which are not themselves entities. In many applications, some concepts that are described as entities would be better off implemented as value objects.

Can value object have logic?

Value objects are not only containers of data - they can also contain business logic. The fact that the value objects are also immutable makes the business operations both thread-safe and side-effect free.

What is value object in clean architecture?

“In computer science, a value object is a small object that represents a simple entity whose equality is not based on identity: i.e. two value objects are equal when they have the same value, not necessarily being the same object” – Wikipedia.


1 Answers

as DDD practitioner advise, business rule's validations must be implemented inside domain objects (Entities,Value Objects and Domain Services)

Yes.

also somewhere I'd read that we should put technical validations (such as check length,correct input formats,correct data type,...) out of domain model and somewhere like application layer to keep domain object clear.

A little bit confused here; the main point is that the entities shouldn't need to be worrying about a bunch of input validation, that isn't their job (separation of responsibilities). So instead of passing raw data (strings, primitives) to the entities in our model, we first use the primitives to construct value types that the entity will recognize, and then pass those entities in.

The rules for which primitives can be used to create a well formed value type are properly implemented within the value type itself (constructor) or in a dedicated factory provided for that purpose). The application component has the responsibility to create the value type from the message/DTO it has received before passing that value to the model.

So in your example, the DebitCard validation logic looks like it is in the right place.

A caution - your model evolves over time; when the model changes, you'll still need to be able to read the data written by the earlier version of your model. Adding validation rules that treat your current data as invalid can get messy - so you want to make sure that the validation rules have business motivation. Are you saving money/cutting costs by ensuring that a debit card number has a valid checksum?

(Example: suppose a customer submits a purchase order with an invalid card number. Does the business want to reject that order, or accept that order but defer acting on it until a valid form of payment is provided? If it's the latter choice, you want to make sure that your validation logic doesn't get in the way of accepting the order).

like image 78
VoiceOfUnreason Avatar answered Sep 21 '22 13:09

VoiceOfUnreason