Functional Web Development with Elixir, OTP - Is OTP part of the entity layer?

First, I want to echo what @keathley and @peerreynders had to say. They covered a lot of good ground pretty thoroughly, so I’m going to take another direction in trying to answer your question.

I’d like to start by making a distinction between design patterns and design principles.

The Gang of Four book is probably the most famous source of design patterns, but the architectural patterns you mentioned - hexagonal and onion - are as well. My sense of design patterns is that they’re fairly strict. There are rules to follow. There are definitions and technical terms to learn.

Design principles are more loose and general. These are often just phrases like “build in layers”, “minimize complexity”, “name things expressively”, and so on.

Design principles most often use common terms with their everyday meanings. They tend not to emphasize hard and fast rules, but this doesn’t make them any less useful. In fact, their flexibility makes them applicable in a broader range of cases.

That flexibility gives the developer a lot of discretion, but it requires the developer to exercise more of their own judgement as well.

Here’s where this applies to the concern you raised that we might be throwing hard won knowledge out the window.

When folks started to write Gang of Four style books for other languages (GoF was originally written for C++ iirc), they needed to change and adapt the patterns. Sometimes they needed to make considerable changes. Sometimes they needed to throw patterns away completely because they didn’t make any sense in the new target language. (I’m thinking of the Ruby one especially.)

This reinforces the idea that patterns aren’t very flexible. It’s really hard to apply them across languages. It’s way harder to apply them across the OOP/FP border.

Principles are much more likely to make that trip successfully. My suspicion is that in the line you quoted from Dave Thomas, he’s talking about something closer to principles than patterns. (But that’s only my suspicion, and I don’t want to put words in Dave’s mouth.)

Also in this respect, Elixir isn’t really new, as you say. Elixir semantics are very close to Erlang’s, and Erlang has been around for decades. Elixir and Erlang are just different from most other paradigms. So this idea that we can readily apply patterns, not principles, from OOP seems really unlikely to me.

4 Likes

Ahhh, I think I get it now.

All this time I have been investing my time in reading Patterns and Rules, not realizing that Erlang’s landscape requires a different approach from the get go.

After reading evryone’s replies, I have concluded the following:

  • I need to focus more on architectural design principles and not patterns (specially the ones translated from other languages)
  • I need to invest more on books and courses on how to model applications in Elixir (I suppose it doesn’t change much from erlang, right?)

When I started the book I had a copy of the GoF design patterns right alongside it. I still do, it’s a book I cherish a lot. But I now understand that the Elixir best characteristics are better fostered in a environment not restricted by the patterns of 15 years ago, made for C++.

In a way, this is both humbling and freeing. Humbling because I have cemented my position as a beginner. It somehow feels like after years of being a Senior in other areas where I had nothing more to really learn, coming to Elixir is almost like going back to level 1.

But I also feel free, because now that I understand this, I am more open minded and reading new books and posts from the community will be easier for me. I am not perfect, there will always be a part of me that goes “This really looks like pattern X or goes against rule Y” but now I feel I don’t have to compare everything against this huge database of past experiences and accepting new information (while still applying critical thinking ofc) will be easier.

It also makes me feel better about buying more books about Elixir, so I guess it’s good for everyone :stuck_out_tongue:

When folks started to write Gang of Four style books for other languages (GoF was originally written for C++ iirc), they needed to change and adapt the patterns. Sometimes they needed to make considerable changes. Sometimes they needed to throw patterns away completely because they didn’t make any sense in the new target language. (I’m thinking of the Ruby one especially.)

This is an important piece of history I didn’t know of and I can only wish I had heard it before!

2 Likes

Consider it the more senior position to be able to answer with “It depends” and being able to select the way forward given your own constraints and not sticking to patterns just for the sake of it.

1 Like

Just a couple of comments. I also like patterns, but I understood they were guidelines, not recipes that should be strictly followed. Hence, I could always find ways to adapt a particular pattern to the situation at hand.

What I like the most about them is the way they communicate experience. In particular, how experienced developers approached a particular problem, and why. I think that’s a great way to learn from others.

On that note, you might find this book useful: " Functional Programming Patterns in Scala and Clojure". I haven’t read it yet, but I find the theme very interesting. From the book description:

For each pattern, you’ll first see the traditional object-oriented solution, and then dig into the functional replacements in both Scala and Clojure. These patterns are common in the functional world and deserve to become part of your problem-solving toolkit. On the object-oriented side, you’ll see many common patterns, such as Command, Strategy, and Null Object. On the functional side, you’ll learn core functional patterns such as Memoization, Lazy Sequence, and Tail Recursion.

Saludos!

1 Like

Ok, I feel I need to answer regarding this assumption people are making about me.

Patterns are pre-fabricated solutions extracted from the industry. In the case of the GoF, it took them years to collect all the patterns published.

If you jump into any problem expecting that a pre-fabricated set of solutions is going to be the perfect fit for everything, then you will suffer. However, if you go on with the mindset of re-inventing the wheel, you will be in a world of pain as well.

Obviously, in the end, the “it depends” meme applies to a lot, but you will eventually have to make decisions and having a set of pre-fabricated solutions that you can adapt to your problems is a very useful tool.

Most Seniors know this, and I personally defend that if you just apply patterns right and left without considering their cost, then you are not really a Senior. As Zack says in his mailing lists: “If you don’t know the downsides of the tools you are using, then you don’t really know the tools you are using” (sorry for bad paraphrasing, but this is the conclusion).

Thanks for the book recommendation @Cruz , but I have another one in mind (Functional patterns in F#) :stuck_out_tongue:

To what extent?

One issue with a large part of the readership of Design Patterns: Elements of Reusable Object-Oriented Software is selective reading which focused on applying patterns and not much else.

Seems a lot of people were possibly skipping the Intent and Motivation sections and more importantly the Applicability and Consequences (benefits and liabilities, tradeoffs).

Also a significant value of patterns is to serve as a vocabulary for more precise and effective communication. It makes it possible to reference the pattern in the context of a solution without having to go into nitty gritty detail (repeatedly).

Even with SOLID - “principles” may be too strong, “guidelines” would be more appropriate. And even those guidelines are not context-free. Following those guidelines still makes certain tradeoffs - tradeoffs that may be acceptable in many circumstances, not so much in others.

It’s always important to consider context and understand the tradeoffs.

While you may not agree with every aspect of The SOLID Design Principles Deconstructed (2013) it is interesting to see them challenged (if you’re still following the SOLID principles and you regard yourself as a competent developer, you need to start giving them up).

An earlier discussion - applying SRP to Elixir:

1 Like

I actually saw that talk a long time ago and it was illuminating. I actually do agree with him in a lot of keypoints :smiley:

Honestly, this is the most important bit in the whole thread for me. Reading (and listening!) with an open mind is an incredibly valuable skill. May it serve you well!

2 Likes

Erlang Master Class 1: Video 8 - Discussion

So you likely got sucked in by the functional (yet sequential) programming part and now are consciously perceiving the third hurdle: thinking concurrently.

I also think there is a fourth hurdle: supervision - i.e. designing effective supervision trees.

1 Like

When I started the book I had a copy of the GoF design patterns right alongside it. I still do, it’s a book I cherish a lot. But I now understand that the Elixir best characteristics are better fostered in a environment not restricted by the patterns of 15 years ago, made for C++.

Just to add some more history: Peter Norvig put together a nice analysis of the GoF patterns from the point of view of a Lisp programmer (http://norvig.com/design-patterns/design-patterns.pdf). This was in 1996 and revised in 1998. The short summary: In most cases, you don’t need a pattern, you simply use a function or closure. In Elixir, you will find exactly the same situation, including Lisp macros. Don’t try to use OO patterns in a functional programming language…

In a way, this is both humbling and freeing. Humbling because I have cemented my position as a beginner. It somehow feels like after years of being a Senior in other areas where I had nothing more to really learn, coming to Elixir is almost like going back to level 1.

Yes, this is the most shocking experience when changing your programming paradigms. I still remember the long time of confusion around 1990 until I understood OO coming from a Pascal background. Similar happened again when changing towards functional / actor-style programming (do you already know about functors and monads :wink:?) And I am pretty convinced that the same will happen when I dive into logic programming, may it be classical prolog or miniKanren. Take a look into the wonderful book “Structure and Interpretation of Computer Programs” from Abelson and Sussman on how to implement all these programming concepts in a functional setting.

4 Likes