101 lines
4.1 KiB
Markdown
101 lines
4.1 KiB
Markdown
# Object validation
|
|
|
|
Validation of objects is essential for the quality of object-oriented programs.
|
|
|
|
This page provides a rough overview of different techniques and strategies around object validation.
|
|
|
|
## Basics
|
|
|
|
### Object types
|
|
The appropriate kind of validation may differ on the kind of object, whether it is
|
|
* mutable or
|
|
* immutable
|
|
|
|
### Validation results
|
|
|
|
Validation results can be divided into:
|
|
* **Detailed**: containing a list of violations
|
|
* **Simple**: reporting just one violation (or even only success/failure), either with a simple or a generic message
|
|
|
|
### Technical possibilities
|
|
Most languages are offering the following possibilities for failure handling:
|
|
* Return values
|
|
* Exceptions
|
|
|
|
### Context
|
|
|
|
Validations can be
|
|
* context-dependent
|
|
* context-independent
|
|
|
|
### Validation time
|
|
* Before object creation
|
|
* After creation (but before actual usage of the data)
|
|
|
|
### Validation patterns
|
|
* Validation on existing objects/states during business operations (i.e. after object creation) (see https://enterprisecraftsmanship.com/posts/validation-and-ddd/) :
|
|
* validate / isValid methods (backdraw: race conditions can lead to invalid state)
|
|
* in application services (backdraw: potential business logic leakage)
|
|
* TryExecute (backdraw: no CQRS separation: potential state change AND returning data (i.e. error message))
|
|
* Execute / CanExecute => call separately „Can“- and „execute“-method, (partial) state is stored locally which means no race conditions can lead to an invalid state
|
|
* Validation during object creation (avoids invalid objects), without public validation method
|
|
* In constructor
|
|
* In factory method (e.g. create method)
|
|
* In Factory
|
|
* In Builder
|
|
* Validation before object creation with public validation method (avoids invalid objects, allows CQRS and detailed results):
|
|
* With (static/class level) validation AND factory method - (https://savoiragile.com/2012/06/28/english-object-validation-on-immutable-objects/ & https://reflectoring.io/java-immutables/ )
|
|
* Using Essence pattern (https://stackoverflow.com/questions/9776193/good-practice-to-validate-immutable-values-objects )
|
|
* Also Factory and Builder pattern could be added with a validate method (https://stackoverflow.com/questions/16221010/should-the-factory-pattern-contain-validation-logic ), but does not seem very common
|
|
|
|
|
|
## Potential strategies
|
|
|
|
When putting the basics above together, you might consider the strategies below.
|
|
|
|
### For mutable or context-dependent objects
|
|
Use strategies for validations **after** object creation
|
|
(from https://enterprisecraftsmanship.com/posts/validation-and-ddd/):
|
|
* The Execute / TryExecute pattern works best for task-based scenarios.
|
|
* For CRUD scenarios, you need to choose between Execute / TryExecute and validation in application services. The choice comes down to purity versus ease of implementation.
|
|
|
|
### Immutable and context-independent objects
|
|
|
|
Use validations **before** object creation
|
|
(first, you may want to validate as early as possible,
|
|
and secondly, it normally makes no sense to create object that never will be valid.)
|
|
|
|
* Factory method AND validation method (for less complex cases)
|
|
* Note: validation method must be static/at class level
|
|
* Essence pattern (for more complex cases)
|
|
|
|
### Validation results
|
|
Consider
|
|
* Detailed results (containing a list of violations)
|
|
* for crud-y operations e.g. when using multi-field input
|
|
* Simple results
|
|
* if detailed results would add no benefits, e.g. for task-based operations (if user just wants to execute a task and/or just wants to know if the task was successful or not resp. why not)
|
|
|
|
### Technical mechanisms
|
|
|
|
* Return values
|
|
* for “expected” failures
|
|
* Exceptions
|
|
* for “unexpected” failures
|
|
|
|
https://stackoverflow.com/questions/99683/which-and-why-do-you-prefer-exceptions-or-return-codes
|
|
https://stackoverflow.com/questions/5460101/choosing-between-exception-and-return-value
|
|
https://enterprisecraftsmanship.com/posts/error-handling-exception-or-result/
|
|
|
|
|
|
---
|
|
###Appendix
|
|
|
|
Object creation (patterns, etc):
|
|
* Constructor
|
|
* Factory method (e.g. create method)
|
|
* Factory
|
|
* Builder
|
|
* Essence
|
|
* Other creational patterns: Prototype, Object Pool, Abstract Factory, Singleton
|
|
|