Background
I am currently reading Unit Testing Principles, Practices, and Patterns to improve at TDD.
The book has object oriented languages in mind and follows the classical school of TDD, but I overall find value in reading. Many of the patterns and ideas the book has, can after all be brought to Elixir and other non-OOP languages. TDD does not adhere to a specific paradigm after all.
Functional architecure
The book mentions two main types of architectures. Hexagonal Architecture and Functional Architecture. The second one (FA), is considered by the author a subset of HA, an extreme where all the side effects and collaborators are pushed to the service layer, thus keeping the core purely functional and easily testable. In reality, his idea of FA is very compatible with what some people know as Functional core, Imperative shell.
Problems with FA
The author mentions that FA works best when the actions to be taken are in the following order:
- Get data from external dependencies
- Make decision
- Apply decision to ugly outside world
This has a major drawback. In many cases, the decision making process (point 2) can’t be done without querying for more external information, aka, the flow is something like:
- Get data from external dependencies
- Make decision A
- Get more data from external dependencies
- Make final decision
- Apply decision to ugly outside world
Solution?
They author suggests two possible solutions:
- Use the CanExecute/Execute pattern
- Send messages to a queue and have external dependencies read from such queue
In the first one, the external dependency, asks the core if it can perform a given action. If so, it performs it.
In the second one the external dependency reads from a queue of actions it needs to perform.
Opinions!
I personally don’t like the first solution. If I have a controller, for example, this means my controller will be littered with if statements. I want my controllers as dumb as possible.
The second one is more akin to what I believe makes sense using in Elixir. But the book mentions no processes nor mailboxes. Just a simple module that has a list of actions that need to be done, it works with mutable state. I am not really sure how to translate this to Elixir.
What do you guys think? What are your opinions?