Elixir: Strengths
Cody Daigle
Posted on May 27, 2024
In this article I plan to go over just a few of the strengths and advantages that the Elixir programming language has to offer. Applications today often have issues with scaling and concurrency and Elixir provides that solution. Large-scale sites and applications that you may be familiar with, such as Discord, Pinterest, and even PepsiCo, utilize these advantages.
What is Elixir?
Elixir is a robust, functional programming language, inspired by Ruby, excelling in Fault-tolerance capabilities, Scalability, and Concurrency, focusing on productivity and readability. Elixir prioritizes pure functions, higher-order functions, and immutable data, encouraging expressive, clear code writing. I mention robustness due to Elixir's utilization of a functional approach which provides clear, concise code, reduction of bugs, and upon
troubleshooting or debugging the problems are solved in small, testable units. Considering functions are treated as primary elements, or first-class entities, they are passed as arguments to other functions or returned as a result allowing strong composition and abstractions.
Strengths
Erlang's goal is to provide the ability to create highly available systems that run consistently and provide meaningful responses to client requests. But in order to achieve a highly available system you have to overcome fault tolerance, scalability, and distribution so that the provided service has minimal failures as well as downtime.
- Fault tolerance: Minimize, isolate, and recover from the effects of run-time errors.
- Scalability: Handle a load increase by adding more hardware resources without changing or redeploying the code.
- Distribution: Run your system on multiple machines so that others can take over if one machine crashes.
Concurrency
Elixir’s processes communicate asynchronously.
Concurrent operations are efficient and responsive.
Elixir is a concurrent language as well as a functional language. The concurrent characteristic allows you to improve the availability of your system and organize your runtime, whereas the functional portion allows clean and organized code. One of the major benefits to using Elixir is it's support for concurrency and thanks to Erlang's virtual machine (BEAM), and it's tools and techniques, this has been a central role in doing so.
Scalability
Elixir’s lightweight processes enable easy concurrency.
Scalability and concurrency is essential for Applications we use and build today. Elixir allows us to build applications where performance isn't compromised when dealing with large quantities of requests. Additionally, the distributed environment that Elixir provides allows applications to scale horizontally which is perfect for indulging rapid growth in businesses. Elixir's concurrency model gives developers access to create lightweight processes, called Actors, that communicate seamlessly with other processes via passing messages. And with that level of communication systems can scale over multiple nodes with ease.
Fault-Tolerance
Within BEAM, fault tolerance is a first-class concept that gives the ability to develop reliable systems. The ultimate concept of fault tolerance is to recognize failures while diminishing their impacts upon a system and it to recover without human interference. Now it's not to say that failures or bugs won't happen. In any complex system things can certainly go awry, whether it's hardware, components, bugs, or even the inability to cope with a large request rate. Luckily the failures that do occur are isolated and then managed to ensure that the system continues running, hence Erlang's philosophy of 'let it crash'.
Supervision Trees
A supervision tree is a hierarchical structure that contains a list of child processes it will manage using Supervisors. Supervisors are specialized processes that monitor other processes to ensure system resilience by forcing child processes to automatically restart when they happen to fail. The capabilities of managing the children processes are defined within the strategies you desire the supervisor to use. Currently there are three supervision strategies that supervisors have available to them.
one_for_one
- Restart only the child process that terminated
one_for_all
- In the event of a failure, restart all of the child processes.
rest_for_one
- Restart the process that failed as well as any process that was started after it.
This is an example of what a Supervisor Tree would look like:
def start(_type, _args) do
children = [
worker(:root_worker),
supervisor(
:one_for_one,
[
worker(:worker_1),
worker(:worker_2)
],
name: :supervisor_1
),
supervisor(
:rest_for_one,
[
worker(:worker_3),
worker(:worker_4),
worker(:worker_5),
supervisor(
:one_for_one,
[worker(:subworker_1)],
name: :subsupervisor_1
)
],
name: :supervisor_2
),
supervisor(
:one_for_all,
[
worker(:worker_6),
worker(:worker_7),
worker(:worker_8)
],
name: :supervisor_3
),
worker(:transient_root_worker, :transient)
]
# The root of the tree is a supervisor that runs everything we defined above
opts = [strategy: :one_for_one, name: SupervisorSample.Supervisor]
Supervisor.start_link(children, opts)
end
Conclusion
I am still in the early stages of my software developer journey and I am always fascinated when it comes to learning new items the software world has to offer and Elixir has made it's way up into my list of next languages I'd like to learn in it's entirety. I hope this short introduction to some of Elixir's strengths intrigued you as much as it did me. I plan to continue my research with Elixir and Erlang and provide more information for those that are also interested in working with it.
Posted on May 27, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
November 30, 2024