1

How to validate a factory method (The construction of object).

  public static readonly byte MaxWorkDayHours = 12;

  public static WorkTime Create(Guid WorkTimeRegulationId, String name, byte numberOfHours, byte numberOfShortDays, ICollection<WorkTimeActivation> activations = null)
        {
            if (activations == null) { activations = new List<WorkTimeActivation>(); }
            if (numberOfHours > MaxWorkDayHours) return null;
            return new WorkTime()
            {
                Name = name,
                NumberOfWorkHours = numberOfHours,
                NumberOfShortDays = numberOfShortDays

            };
        }
  • Is it okay to check that a specific field can't be greater than a specific number ? or this type of validation should be in the model of MVC not in the domain layer ? or in both ?
  • If I make a check like this if (numberOfHours > MaxWorkDayHours) Should I throw an exception say that numberOfHours reach the limit or return null ?
Anyname Donotcare
  • 11,113
  • 66
  • 219
  • 392
  • With respect to your second question, it depends on whether the validation failure is expected or not. If it is expected, your factory method may return an error code or a null to signify failure, which *informs* the caller that it is OK to continue even if validation fails. However, if a validation failure is not expected, then you must throw an exception; this makes it clear to the caller that there is an exceptional occurrence and that ignoring it will be at the caller's own risk. – RWRkeSBZ Sep 11 '18 at 15:18

3 Answers3

2

Is it okay to check that a specific field can't be greater than a specific number ?

Yes - that's a normal thing to do when we are using domain agnostic types (like bytes) to express some domain specific concept.

this type of validation should be in the model of MVC not in the domain layer ?

Domain layer for sure; but it may also make sense to do it in the model. The motivation for checking value constraints in the model is that you want to limit the number of different places in the code that the check needs to be.

It's a common pattern in to introduce a Value Object that represents the domain concept; the check is implemented in the constructor (or factory method) that creates the value, and code that uses the value can rely on the type checker to know that validation has already happened.

If I make a check like this if (numberOfHours > MaxWorkDayHours) Should I throw an exception say that numberOfHours reach the limit or return null ?

It depends. There is another alternative as well, which is to return an or-type; the factory returns either the object or a list of validation errors.

Returning null would be my last choice - it is a bit implicit for my taste; I would rather that the fact that you return 0 or 1 objects from the method be made explicit by returning a collection. See Optional, for example.

Returning an or-type that might include a list of validation errors is basically dual to throwing an exception that includes a list of validation errors. Exceptions allow you to more easily separate exception handling from the happy path, but that has benefits and costs.

Could I ask What did u mean by return an or-type ?

An Or type is a type that will either hold a value of one type or of another type.

Or<Left,Right>

In languages where pattern matching is a first class concern, you would use a switch statement to "unpack" the type. In languages where you don't have those constructions, you often do work by passing a pair of callbacks

Or<Left,Right> thing = ...
thing.execute( onLeft , onRight )

Execute will call either onLeft(Left x) or onRight(Right x), depending on which value has been set internally.

A poor man's OrType might look like a Type with two members, at least one of which is always null

VoiceOfUnreason
  • 52,766
  • 5
  • 49
  • 91
1

I suggest you do the following:

public class Worktime
{
    int _maxWork;
    int _workHours;

    public Worktime(int maxWork)
    {
        _maxWork = maxWork;
    }

    public int NumberOfWorkHours
    {
        get { return _workHours; }
        set
        {
            if (value > _maxWork)
                throw new ArgumentOutOfRangeException("Work hours should not exceed " + _maxWork);

            _workHours = value;
        }
    }
}

then domain layer should catch the exception and handle notifying the user, I prefer that the factory should always return a valid instance not a null value unless an exception is thrown to know specifically the problem not just returning a null instance without knowing what was the problem.

Nimantha
  • 6,405
  • 6
  • 28
  • 69
Ali Ezzat Odeh
  • 2,093
  • 1
  • 17
  • 17
  • Could I ask if the code u write is in the domain layer , because u said `then domain layer should catch the exception and handle notifying the user` – Anyname Donotcare Sep 10 '18 at 11:03
  • Now this business rule should be applied to domain by preventing user from inserting value greater than this value, in case you are building an MVC application for example you can put this logic inside ViewModel if you are generating your models automatically using entity framework – Ali Ezzat Odeh Sep 10 '18 at 11:22
0

Is it okay to check that a specific field can't be greater than a
specific number ? or this type of validation should be in the model of MVC not in the domain layer ? or in both ?

From my opinion, I think you can check it where you create the WorkTime object is better than from model( in this context, it is inside your Create() method).

Let think: if in the future, another team member use your Create() method, and he don't know about this validation, and he will not care about that. => chek it here will help you handle this risk point.

In addition, in the future, maybe you use your Create() in many places, and if you validate in out out the Create() method, then you need to validate it again and again, and make a duplicate code.

If I make a check like this if (numberOfHours > MaxWorkDayHours) Should I throw an exception say that numberOfHours reach the limit or return null ?

It depend on how will you process with the result. If you need to show some details information for users, you need to throw an exception, and catch it somewhere to show the problem information for users. In case not, you can choose simpler solution: return null.

Nimantha
  • 6,405
  • 6
  • 28
  • 69
Nhan Phan
  • 1,262
  • 1
  • 14
  • 32