Functional objects on Ruby programming language
- Less questions asked. E.g:
- More consistent style among classes definitions.
- Message passing is natural;
- Emphasize what system does rather rhan what system is;
- Usage of mocking frameworks can be dropped off;
- Start class names with a verb;
- ("do thing" instead of "thing doer");
- Public contract is a
- Enables SRP;
- Enables composition/polymorphism through proc/callables objects;
- Receive stateful/impure collaborators through the object initializer;
- This permits easy mocking/substitution.
- This resembles curry-like functions;
- Receive "pure function" inputs through the
- Collaborators are also other functional objects (they're named as verbs);
#call calling always returns a value, preferably 'result'-like objects;
- This avoids 'primitive obssesion' anti-pattern;
- Consider monadics operations;
- Define stateful/impure functions as default implementation, in case nothing is received;
@get_page_title ||= begin
lambda do |url|
mechanize = Mechanize.new
- Object internal state is used only for stateful/impure collaborators.
- Stateful/impure functions are always returned as closures/lambda;
Quote from "Functional and Reactive Domain Modeling" book
extract_utm_campaign_value_from(url) # is pure
get_page_title.call(url) # is impure
# Why mixing domain logic and side effects is bad
### Entanglement of domain logic and side effects.
Violates separation of concerns. Domain logic and side effects are orthogonal
to each other—entanglement violates a basic software engineering principle.
### Difficult to unit test.
If domain logic is entangled with side effects, unit testing becomes
difficult. You need to resort to mocking stuff that leads to other
complications in your source code.
### Difficult to reason about the domain logic.
You can’t reason about the domain logic that’s entangled with the side effect.
### Side effects don’t compose and hinder modularity of your code.
Your entangled code remains an island that can’t be composed with other