Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should the factory pattern contain validation logic

When using the factory pattern, should the factory itsel contain validation logic or should that be left up to the calling classes to take care of validation before passing the context data in?

I have a simple factory method but it relies on a config tree being passed to it to decide what object to instantiate.

There could be a situation where the config xml might be well formed, but not in the correct format the factory is expecting and I dont know where this should be validated.

like image 523
Marty Wallace Avatar asked Apr 25 '13 17:04

Marty Wallace


3 Answers

When using the factory pattern, should the factory itsel contain validation logic or should that be left up to the calling classes to take care of validation before passing the context data in?

There are two distinct alternatives to organize validation:

  1. Validation as a separate process

There is a separate validation method Validate(Config). This method is called before construction method and returns information whether Config is valid or not. If Validate method returns that Config is valid, then construction method is called. Any error during construction process is considered to be an exception.

  1. Validation as part of construction process

There is no separate validation method. Instead validation happens inside construction method when needed. Construction method is allowed to fail and to return either a constructed object or a result indicating an error.

The second variant can be nicely implemented using monads with almost zero code and performance overhead.

like image 160
Lightman Avatar answered Oct 13 '22 00:10

Lightman


What do you mean by validation? And what makes you think code that is part of an instance of the Factory design pattern is different from any other code?

If by validation you mean checking of input values read from the user or an input file, the answer is no: the code for parsing the input is responsible for validation, not a Factory that subsequently uses the read values.

If by validation you mean having the factory methods of the Factory checking that their callers have supplied values that conform to the preconditions of those methods, the answer is the same as for any other method that imposes preconditions on its arguments: the consensus style for Java is for methods to check their preconditions and to throw a suitable RuntimeException if the preconditions are not met.

Now, in practice, this means some input values will be checked twice. First by the input validation code, and then by the precondition checks of the Factory. Partly that is the cost of breaking code into modules (here, a separate input module and service layer).

But it it also allows the checks to report in different ways, which are more appropriate for their purposes.

  • A failed precondition check (in the Factory in this case) indicates a bug in the program. We want the precondition failure to report fast and hard, before the program state is altered, to get the most useful information for debugging (In many cases the location of the bug will be a method in the call stack).
  • For input validation failures we typically want the program to report as many faults in the input as it can for one parse of the input, so the user can fix them all. Think of the compiler you use: you would be frustrated if it stopped after finding the first syntax error in your source code. Throwing exceptions to implement this is inappropriate. The code should note the fault and continue parsing, if possible, rather than ejecting to a higher level part if the program (which is what throwing an exception does).
like image 39
Raedwald Avatar answered Oct 12 '22 23:10

Raedwald


Why not offer both? With this, you pass the responsibility to the caller as to whether he wants his input validated or not.

Take this example from Apache Commons - InstantiateFactory:

Its default constructors offer no validation:

InstantiateFactory(java.lang.Class classToInstantiate)

Constructor that performs no validation.

But offers validation in getInstance:

static Factory getInstance(java.lang.Class classToInstantiate, java.lang.Class[] paramTypes, java.lang.Object[] args)

Factory method that performs validation.

like image 21
Jops Avatar answered Oct 12 '22 22:10

Jops