Uncle Bob’s talk inspired me to try to isolate away my business rules into a separate gem. Here was the concept I came up with (more or less):
SApp Gem Directory Structure
... other gem crap ...
|-- lib
| `-- sapp
| `-- authenticate_user.rb
| `-- display_receipt.rb
| `-- finish_account.rb
| `-- finish_transaction.rb
| ... more use cases/interactors ...
| `-- sapp.rb
|-- test
| `-- authenticate_user_test.rb
| `-- display_receipt_test.rb
| `-- finish_account_test.rb
| `-- finish_transaction_test.rb
| ... more use cases ...
... other gem crap ...
lib/sapp/authenticate_user.rb
Now you can imagine that my code could be interacted with from a rails controller or a sinatra application or a desktop application with this API:
Rails Example
Sinatra Example
test/authenticate_user_test.rb
It is important to note that I intentionally did not pass the entire params hash to the interactor. The interactor should explicitly specify the required parameters it needs to complete the use case. As a result of this new design, I don’t need to write acceptance tests that run through the web application because my core business layer has been decoupled and the API that my web application interacts with is dumb and dead simple.
I intentionally left out the Entities from my examples and you might also notice that I am making calls to the database from my use cases. I will explain my reasoning in the next chapter on my quest for a better architecture… which is coming soon.