What were the most challenging tasks you faced and how did you solve them in Elixir?

Greetings Everyone!

Let’s discuss the challenges that we are facing in Elixir from start. Everyone can share his/her story according to their own. I love to hear your stories. :innocent:

Our topic is what are the most Challengeable task you face and how you solve it in elixir ??

5 Likes

One thing that tripped me up big time at the start.

message = ""

if some_var do
  message = "Hello"
else
  message = "Goodbye"
end

IO.inspect message

What do you think message will be? Don’t tell anyone but one night I was particularly tired four months ago… and let’s just say I spent an hour trying to debug this lil thing.

3 Likes

yeah. @sergio you are right, even at this level sometimes i got stuck in this problem and was debugging my whole logic where’s the problem is :laughing:

I don’t want to get stuck like this down the line, so I am spending time going through books and documentation, so I know as much as possible.

For instance this was covered in Elixir in Action. Excerpt:


Recall that everything in Elixir is an expression that has a return value. The if expression returns the result of the executed block (that is, of the block’s last expression). If the condition isn’t met and the else clause isn’t specified, the return value is the atom nil:


message = ""

message =
      if some_var do
        "Yay"
      else
        "Doh"
      end

IO.inspect(message)


P.S. What I am trying to say is, that it’s overwhelming getting into Elixir. I have to read a lot, so I overcome challenges. :sweat_smile:

1 Like

@derpycoder we know that whats the solution is. actually we are just discussing that we also got stuck at this problem too at minor level…

So yeah what’s your challengeable work that you done specifically in elixir. ?

1 Like

My Challengeable work was in one of my recent project i develop a complete wrapper of Redis genserver to manage the state of user in a single thread or connection.

The motivation behind the idea is that we wanna make our application efficient in terms of memory.

It wasn’t my intention to show the solution, rather I was pointing out I have to read a lot to catch upto everything.

So my challenge is how overwhelming it feels to get into Elixir & Phoenix.

When I was tasked with creating a Presence tracking app in Node, 5 years back, using Socket.IO. I was able to get going and be productive within a week.

However with Elixir, I have been reading and reading and still find something new. (Currently have 9 books in lineup) :sweat_smile:

1 Like

So why you didn’t explore websockets instead of socket.io in elixir ?

If yes then where’s the change you notice that i should explore socket.io instead of websockets in elixir ?

I was a junior software engineer back then, and was unaware of Elixir. I wish I knew back then or someone was there to guide me.

Right now I am learning Elixir, Phoenix, Channels, Presence tracker to create my own Micro SaaS.


P.S. Don’t touch Socket.IO or node with a 10 foot pole. Steer clear of anything JavaScript. I am not rallying for that language.

1 Like

okay sounds great. There are many things in elixir that will really help you to build more dynamic and memory efficient applications.

1 Like

@kwando @adamu whats your biggest challenge in elixir ?

Make a composable schemaless query builder like Ecto.Query

Something like

from("my_table")
|> where([t], t["field1"] == ^some_value)
|> join(:inner, [t], t2 in "my_other_table", on: t["foo"] == t2["bar"])
|> select([t1, ..., t2], [t1["foo"], t2["bar"]])

Subqueries and named bindings are also supported. The builder also needs to be SQL-injection-free when properly used.

How to achieve this goal? By using macros, of course. And through building this builder, I learn a whole lot of Elixir metaprogramming.

Make a custom tableau-expression-like syntax parser

I wrote a tokenizer by hand, and a parser using :leex.

Yet another workflow

There are many problems I’ve not solved yet. One of them is how to store arbitrary user-provided JSON-serializable data that embeds system data types at any level. I want to solve this problem with Messagepack with custom extension instead of JSON, but I’m not allowed to do that.

2 Likes

Some of the challenges of Elixir I had to deal with more and more in the last years due to helping (or being in charge) with fairly busy systems where efficiency matters, are:

  • Taking into account process boundaries and what data gets copied from one process to another. This has led me to discussions during which I completely scrapped a nascent mini library I wrote and replaced it with a very thin layer over the :jobs Erlang library, for example.
  • Binary copying or referencing. Every now and then we have threads on this forum where people are puzzled with growing memory usage that does not go down and the reason is binaries with too many references pointing at them, 99% of the time. Hence the need to become friends with :binary.copy, or Jason.decode(text, strings: :copy) , or others.
  • The OTP machinery is amazing, though some things in the library ecosystem remain underdeveloped in terms of convenience and ease of use and terse code – e.g. when you need to monitor a process, or make sure it traps exits and its parent is aware of it, or have a GenServer worker branch outside of itself and its parent supervisor’s children to do a long-running task etc., the resulting code is just not readable, is boilerplate-y, and it reads like incantations We still need a more English-like DSL for OTP! (Though granted, that’s more like a usability complaint but I’ve seen people get confused when shown the current way these tasks are done. That’s important; stuff should be 100% intuitive.)
  • Even though I have no good ideas on how to improve upon that, I still feel Elixir projects have way too many files. :person_shrugging:

There are likely more but these are the ones that I got off the top of my head.

7 Likes

Problems (as a 10+ year Rails dev)…

  1. Maintainability in large codebases.
  2. Easily addressing things like n+1 queries while being DRY.
  3. Efficiency/scalability.

Solutions…

  1. A (soft) type system.
  2. Some semblance of interfaces.
  3. Separating dataloading from logic (Absinthe + Dataloader, aka Elixir’s GraphQL framework).
  4. Not having to deal with excessively inefficient frameworks.
  5. Actually good documentation. External and internal.
  6. A good VM (Google about Ruby GIL or threading model).

This is just scratching the surface. I honestly wished I kept some kind of journal for this.

5 Likes

well @dimitarvp awesome.

@cjbottaro Great!

But can you please elaborate that how you manage this challenge by referencing it with an example.

Maintainability in large codebases

The product I work on is a pretty big Rails app. There is no static analysis at all, no interfaces; it’s purely interpreted and your only saving grace is writing tests.

We’re slowly porting over some of our backend to Elixir (and even experimenting with some frontend stuff)… and just having a compiler is a major step up. Then Dialyzer is awesome on top of that! We’ve gotten to the point where we pretty much typespec everything, and the immediate feedback is incredible. I can’t wait to see where the set theoretic typing stuff goes.

We definitely use less DSLs in Elixir, but compile time checking of DSL usage is great!

HEEX validates your HTML, Absinthe validates so much of your GraphQL schema… all at compile time.

I think functional is easier than OO (especially Ruby OO). Tracing through our Ruby code is a nightmare. Objects create objects that create more objects. Classes inherit and mixin several modules, so we basically have multiple inheritance all over the place. There are no interfaces, so we have to traverse tons of files to find methods that raise "implement me". Or worse, modules that expect methods to be implemented, not in the class including it, but some other module that should be mixed into the base class. And lastly (not specific to Ruby), you have to think about which methods mutate state (instance vars). In Elixir, you have arguments and a return value (for the most part). It makes reading and tracing through code 10x easier, imo.

And also, the documentation system is fantastic. I find it both satisfying and fun to write documentation now. For a lot of pure functions, we write doctests. Contrast this to our Ruby codebase where no one likes writing docs… so there are none. Our CI system builds the Elixir docs and uploads them to a static site.

All this stuff adds up to better maintainability. In short: a compiler, type system, static analysis, no OO, and documentation system. All that with the benefits of a dynamically typed language. It’s like having your cake and eating it too!

4 Likes

Exactly @cjbottaro, that’s great.

new to elixir, is this because the message bindings in the if block are local to that lexical environment and do not affect the outer binding of message?