The Doctrine of Useful Objects is the codification of the design rules that are applied throughout the implementation of the Eventide toolkit, and all of its libraries.
The doctrine reinforces the nature of objects as behavioral units, and except in the case of de facto data structures and entities, encourages the separation of behavior from tangentially-related state.
A useful object:
- Is usable immediately upon initialization without any nil reference errors resulting from uninitialized dependencies (eg: NoMethodError, undefined method for nil:NilClass)
- Doesn't have any logic in its initializer other than assigning the value of initializer parameters to the object's instance variables
- Formalizes the difference between initializer arguments and setters, and the circumstances when one is used rather than the other
- Doesn't require a foreign mechanism outside of the class's own namespace (including inner namespaces) to initialize it and its dependencies (a.k.a.: an Inversion of Control container, etc)
- Doesn't invite the passing nils or dummy values to its initializer for the purposes of setting up the object for testing
- Doesn't rely on test doubles (stubs) to disengage dependencies that would cause undesirable side effects while exercising or otherwise testing it
- Doesn't rely on test doubles (mocks, spies) to be used to inspect an object's execution path