axelson

axelson

Scenic Core Team

ElixirConf US 2018 – Growing Applications and Taming Complexity – Aaron Renner (@aaronrenner)

Growing an application is hard. We started our app with the best of intentions and promised ourselves we were going to “design it right". However as the app grew, complexity increased, dependencies piled up, and changes that were once small now felt like slogging through mud.

Driven by the need to keep our sanity, we decided to apply ideas from Phoenix’s contexts and Domain Driven Design with the hope that we could put boundaries around the complex parts of our system and keep the code from turning into a tangled rat’s nest. This talk covers many of the lessons we learned along the way, including:

  • How to start tackling complexity by teasing apart the app into multiple layers.
  • How to simplify testing and reduce mental burden by defining contracts between these layers.
  • How to verify contracts using tools like dialyzer, automated tests and mocks.
  • How to document these contracts and use them to guide the application design.

After applying these ideas to our codebase for almost a year, we’re eager to share our experiences and provide strategies you can use to tame complexity in your own applications.

Audience: Intermediate
Topics: phoenix

All talks are available in the ElixirConf US 2018 Talks List or via the elixirconf2018 tag

Showing Posts 1 to 6

bartlomiej

bartlomiej

I am having mixed feelings about this, the examples in repository (GitHub - aaronrenner/crowdfundr: Example crowdfunding app for ElixirConf · GitHub) even define some very common cases like user entering an email that is already used as an exception (Crowdfundr.EmailAlreadyRegisteredError) and then use that in {:error, exception} tuple.

I am just learning Elixir but I have went through some materials already and I must say this approach looks totally foreign to me. I would even say that it looks like a total oposite of why I turned to Elixir in the first place. The Behaviour/Impl/DefaultImpl thing reminds me too much of the “interface with single implementation” ceremony that used to be common in some OO languages.

What do you think? I would love to hear what others have to say.

LostKobrakai

LostKobrakai

I‘ve not had a look at the repo yet, but it‘s probably created by driving the point of the talk all the way to make a point.

On the other hand having clear interfaces is something, which is by no means inherently OO. Interfaces are something your code has even if they‘re not written out somewhere explicitly. At the least you should have it as soon as there are multiple implementations, which can be switched out (and as @josevalim argued when creating Mox, this stands also if a second implementation is just used for testing). This was one point in the talk, that it makes testing easier. But I‘m with you that it‘s quite a bit of ceremony if there‘s only one implementation. It just makes is super clear, which functions are meant to be public interface vs. what is implementation detail. In bigger projects, this might otherwise not be as clear.

Naming errors is imo a good thing like anywhere else in programming, especially for the common cases, which are the ones one has to deal with all the time. It could‘ve been an atom instead of an exception struct, but the latter has the ability to later be enhanced with metadata, while with a plain atom to start with the interface would probably need to change in a backwards incompatible way.

stefanchrobot

stefanchrobot

I really liked the talk! It’s basically advocating the use of the Hexagonal Architecture as a way of tackling growing complexity. Just as any pattern, Hexagonal Architecture has pros and cons. The cons are: more abstractions and indirection. It’s up to the developer to decide if the pros outweigh the cons.

Functional programming does not solve complexity on it’s own. I’m working on a Rails app with a god-class - I can clearly see how one could translate this line-by-line into the Elixir land and cause the same pains. Really, there’s no such thing as an anti-pattern: if you’re hacking a throwaway prototype, then cramming business rules into controllers is fine in my books. I guess most web apps would be fine with the “defaults”, i.e. Ecto leaking into the controllers. But that’s not always the case, especially with growing complexity.

slashdotdash

slashdotdash

The behaviour/impl module and separate implementation approach is used by the new Elixir Telemetry library.

aaronrenner

aaronrenner

Phoenix Core Team

I know it’s over a year later, but I just posted an in-depth article covering the layering and swapping mechanisms I gave an overview of in this talk.

slashdotdash

slashdotdash

The behaviour/impl module and separate implementation approach is used by the new Elixir Telemetry library .

Unfortunately this no longer applies as the Telemetry library has been rewritten from Elixir to Erlang.

— All posts loaded —

Where Next? Top

Trending in Talks Top

Other Trending Topics Top

budgie
A little off-topic, but I feel like people here have a good head on their shoulders. I used to be quite good at making software. Was luc...
New
KristerV
Hey. Is there anyone here who creates agents in their apps? Not talking about using agents, but creating them. I’m finding it pretty diff...
New
mudasobwa
I fully migrated to my own harness from Anthropic/Gemini and I think it’s time to share it. Welcome DSH, the DeepSeek Harness, fully writ...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
juhalehtonen
There has been a thread to discuss the Stack Overflow Developer Survey on this forum every year since 2018, so here’s yet another one for...
New
budgie
I love Elixir. It’s one of 2 programming languages I’ve ever fallen in love with. But I don’t use it anymore. Serverless was the promis...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews