AstonJ
Single Responsibility Principle - what does it mean to you and your Elixir apps?
There is a wikipedia definition on this but it doesn’t really cover how you can go further in functional programming. I feel PragDave’s comment (from his course) is better from an Elixir perspective:
I know I’m like a broken record, but I can’t help it. I’m really excited to see how a functional approach makes it so much easier to honor the SRP, both at the function and module level. The fact that state is passed around, and not simply shared, means that functions can and modules can both be split and moved around.
What does the SRP mean to you? How far do you go? How strictly to you adhere to these (or your own) guidelines?
Most Liked
hubertlepicki
I have a theory that a lot of these things we learned when doing OOP, no longer make sense when you switch to functional programming. This is precisely because they solve problems that are a result of using Object-Oriented programming in first place.
Take this single responsibility principle for a review, and compare this to how things from standard library work. In either version (one responsibility, one reason to change), this is being broken all the time.
In Elixir & Erlang, modules group together the related functions. That’s it, there’s no big theory behind it. These functions may perform one or multiple things, but as long as it makes sense to keep them in the same module - they are kept there.
sasajuric
I personally believe that on some higher-level of thinking many ideas transcend paradigms. In particular, I think that a large module which deals with many things is more problematic to read and understand.
A typical example I see is a case where complex GenServer state is handled directly in the GenServer module. By moving the state manipulation to a separate module, we can separate the domain logic from the time-flow logic, and this allows us to study each aspect of our system in isolation.
For a more concrete example, see my example blackjack code from my To spawn, or not to spawn? article. The domain management is done in separate modules, which means that domain code is not polluted with GenServer and vice versa.
IMO the case for short classes (and also modules and functions) is to allow the reader to understand a single concept without worrying about non-essential details. Being able to understand a domain model without caring how it’s used from the rest of the system simplifies the code analysis, debugging, and extension.
I should also mention that I’m not a purist here. For example, if the process state is simple enough, I just bundle it inside the GenServer. If the model grows, then I split.
But tl;dr I believe that SRP and similar ideas, vague as they are, still apply in FP.
hubertlepicki
I think @pragdave might be importing some wisdom from his object-oriented life ;). I was thinking about it when I first opened Elixir’s own source code files, or sources of prominent Elixir libraries like Ecto, and was shocked by the large files containing hundreds of lines of code (+many more lines of documentation). In Erlang they even add a lot of unit tests at the end of the file to keep the tests close to the module they test! (moduledoc in Elixir but more popular I think)
But then, I realized what is a reason for having a short classes and it suddenly made more sense. The reason why we want to keep our classes short and clean is that we can mentally model how instances of this class will behave, and how they will modify the object’s attributes in it’s life cycle. So - we couple state to the functions that operate on this state, and we want this to be as small as possible - otherwise we easily loose track of how this works, and bugs sneak in.
In Elixir, the module has no state. The main reason for keeping classes short does not apply here anymore. Of course, it becomes tiresome to work with files that are thousands lines long, but there is no such thing as internal state of object to be concerned with.
Having said the above: again, the object-oriented wisdom of keeping classes short does have it’s place in Elixir, and again this is when you create processes (GenServer etc). I think it makes total sense to keep them short in terms of lines of code and focused on one thing.
Popular in Discussions
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









