lucianonooijen
Interactors in Elixir following Clean Architecture guidelines
At the moment I am creating a plan to integrate Elixir at enterprise scale for several clients of the company I work for.
Part of this integration would mean the application should comply with the guidelines as outlined in Uncle Bob’s Clean Architecture. (A tldr version can be found here: Clean Coder Blog)
The part I am currently stuggling with is using Interactors in Elixir, without the use of any libraries.
How Interactors are usually implemented is by creating an Interactor interface (with all available functions/methods). The business-logic core expects an object where this Interactor is implemented, so the business-logic core can be fully agnostic of data sources and such.
An example of an interactor based design in Go can be found here: go-realworld-clean/uc/userGet.go at master · err0r500/go-realworld-clean · GitHub
As far as I know there is no easy way to define an interface in Elixir, the way you’d usually do in languages like Go, Typescript, Java or even Scala. I was not able to find any good examples where this kind of architecture is implemented in Elixir.
Using typespecs/behaviours/protocols seems to make the code become quite messy if the Interactors grow in size, so I am looking for a way to implement this architecture while keeping the code clean and easy to maintain.
Thanks a lot in advance!
Marked As Solved
LostKobrakai
You seems to be stuck at “type safety” which just doesn’t exist on the beam. There is no type safety. But GenServers work solely on the idea of a callback module being passed in and it’s basically the backbone behind most of everything running on the beam and it works well even without the type safety. You can have tests ensuring that a certain module conforms to a certain behaviour. You can use whitelists of some kind to allow just tested modules as inputs. If you really want to prevent someone passing in a wrong module there are ways, but not via types. I’d rather suggest making your app handle failure properly and weed out those bugs when they actually happen.
Also Liked
LostKobrakai
You can’t. I just answered this on slack a few hours ago. I’ll just paste this here:
- there’s only
module()as built-in type or
defmodule MyBehaviour do
@type t :: module()
end
-
and
MyBehaviour.tto at least be a bit more concrete for humans -
also it’s not really a good fit for dialyzer, which will only error if it can be certain about a failure. Modules can be loaded at runtime, so there’s no way for dialyzer to check callbacks in advance
LostKobrakai
There’s dialyzer, which can do type checks, but it works considerably different to e.g. typescript. Bu even typescript would have problems with checking if a certain class implements an interface if the class could be created at runtime out of nowhere.
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance








