Please introduce yourself.
What is it that took you from Ruby to Elixir?
To be honest, what brought me from Ruby to Elixir was a coworker. He was really interested in Elixir and he saw it and said, “Hey, this could probably solve some problems that we have. Why don’t we try it out on a project?” And it took a couple of months, maybe six to eight months of talking and working before we finally got the approval to say, “Yes, go ahead and use that,” and introduce it as an experimental language in our microservice stack.
We had a bit of leeway there, and through that process, he really grew to like Elixir and wanted to spread it more. He said, “Hey, Steve, you should check this out. Hey, check out Elixir. Hey, have you looked at Elixir yet?” And he really encouraged me to look at the language and helped me learn it as well.
How does that work in a corporate setting when you want to introduce a new language or adopt a new style of development? Everyone could potentially be on an existing deadline or have other workloads. How do you make that transition?
Many companies have a tech radar. As you become more established, you start doing this tech radar. At startups, it’s more freeform and you stick with your stack. But as you grow, you want to give people the opportunity to try something new.
That’s where the tech radar comes in. The general idea of the tech radar is that for a particular technology, you have different quadrants. These quadrants are Hold, Assess, Trial, and Adopt. Through this tech radar, you tell the team, “Hey, these are the languages that we use.”
Maybe you can say that one language we’re really using in the org right now is Ruby, but maybe we’re at the assess or trial phase with Elixir. Typically, there are a few people, let’s say one to three people, interested in a particular technology. (There’s always a reason why you’re looking at it in the first place. It doesn’t just come out of nowhere.) There’s always someone in the company who wants to use it, and you have to give some guidelines to those people.
You can’t just adopt and start from ground zero with a clean slate. It doesn’t work like that in the real world. You have certain requirements, like all services needing a specific amount of reporting, instrumentation, observability, and security. You establish these baselines and then work with the team to find patterns and solutions. If everything goes well and the service meets all the requirements over time, it shifts from the trial phase to the adopt phase.
During the trial phase of this process, are you conducting a formal panel to persuade people? Or are you simply utilizing allocated time? How do you establish a structured approach to implementing technological changes in your business?
It is important to adopt a new technology that the technical team at the company supports. This support should start at the top level, ideally with the CTO or a high-ranking VP of engineering. To successfully adopt a new technology, it is important for the software engineers, architects, and product managers at the company to be on board.
“It is important to adopt a new technology that the technical team at the company supports. This support should start at the top level, ideally with the CTO or a high-ranking VP of engineering.”
This group of people needs to be convinced of the benefits of the technology, which can be achieved through presentations, prototypes, and developing an initial version of the new service.
All these things are to gain buy-in from people, people who want to use the language, people who see an advantage in it, people who may be a little bored with their current language and want to try something new. Here’s this new thing, and if you want to try it, you get buy-in from these people, whatever their reasons may be. And those are the people who will make it successful.
In the past when I’ve done this, I’ve been on a team of one to three people who are really pushing for a new technology, but around that core, there may be a whole product team split up into different segments.
Maybe the specific group you work with is focused on this technology and supports it. However, not everyone in the organization has to support it. Some people may not even want to use the language. That’s why the idea of the tech radar is to give people choices. But you still need a core group of people around you.
How do you measure what is a healthy technology and how do you convey that message to reluctant stakeholders?
It is admittedly very difficult to measure things sometimes. It’s often easier to do something than to actually measure the thing being done. That’s just a reality of technology, for better or worse. When looking at adopting a language, there are definitely things that you can use, some of them quantitative, some of them things that you can point at and say, “This is a metric, let’s look at that.”
The others are a little bit more qualitative, based on the reaction of the team and how people respond to a particular technology. A mix of both is necessary. Let’s say you had a quantitatively large boost to productivity, but no one liked using a particular language. That wouldn’t be healthy for the business because if someone doesn’t like the work they do, they may look for a new job, which is not something that a business usually wants.
On the flip side, let’s say there’s a language that people really like using, but it takes longer to ship features overall. Or the team is recreating a lot of things from scratch all the time, project after project. Some things have to be done the first time; you have to figure out a pattern in how you want to do that in your organization, but you don’t want to be doing that for every project.
The team may love working with it, but it’s just not productive for the organization. You could look at the velocity of the team as they trial out the language, as they build their service, as they build a second service, see how that velocity changes over time. Ideally, the velocity is getting back to what it was before the technology switch.
There will be some initial impact, but you need to overcome that. You have velocity and sentiment from the team. Are they happy and engaged? Do they feel that this is a good initiative and are they excited to be a part of it?
Additionally, you have quantitative measures to consider. Do the services we’re building perform better and serve our customers well? Product managers have multiple ways to approach these questions related to the product, team sentiment, and metrics of productivity.
"You have quantitative measures to consider. Do the services we’re building perform better and serve our customers well? "
You talked about the degree of technology replacement. Can Ruby and Rails coexist as you phase in Elixir and LiveView and Phoenix and so forth?
Languages can coexist together in different organizations, and the way this happens may vary. In my opinion, the easiest form of coexistence is when a company has an established microservice architecture. Now, I’m not advocating for or against this, but logically speaking, if a company has a microservice architecture, they can write their microservices in Elixir.
This is exactly what I did in the past when Elixir was introduced to the organization I worked for. We already had a microservice pattern in place, so we integrated Elixir into that pattern, ensuring that all necessary tasks were accomplished. Elixir coexisted alongside our Ruby application, and as an API consumer, you couldn’t tell if the API was written in Ruby or Elixir. So it didn’t really matter. The microservice architecture we had was quite complex though.
There is another reality that most applications, especially in the startup world, are just going to be a single monolith. There’s a single code base for the entire application, and you can still have coexistence in that type of architecture, but typically it’s a little bit of a larger lift because it means that you’re probably going to have two monoliths. You’re going to have the Ruby monolith and the Elixir monolith.
That can be challenging. It’s an architecture that needs to be carefully planned in advance. It can work, but it ultimately depends on the team’s goals. If they want the systems to coexist, then microservices might be a better solution. If they want to replace the old system, they could create a new repository and gradually migrate endpoints and behavior until they can fully cut off the old system. There are software patterns that can help with this. In the end, you’ll have a new monolithic system in the new language, replacing the old one.
People who have been using Ruby love it passionately. Do you think that’s a fair assessment?
Yes, it’s true that people who use Ruby love it. The reason for that is because that’s a goal of Ruby. When the language’s goal is to be loved by the developers, it’s a good sign that the developers love it because it’s living up to that goal.
“People who use Ruby love it. The reason for that is because that’s a goal of Ruby. When the language’s goal is to be loved by the developers, it’s a good sign that the developers love it because it’s living up to that goal.”
I find that those doing Elixir are almost as passionate about it as Ruby developers. However, these two languages differ greatly in terms of expressiveness, structure, libraries, and more. So, how does one create a bridge between these languages? How do you let go of your familiar idioms in Ruby to explore unfamiliar territory in Elixir?
Yeah, it’s also true that people who program in Elixir seem to really love it. That includes me. I love both Ruby and Elixir, so I can say that I fall into both of those camps. I’ve been using Elixir as my main language for longer, so that’s where my priority is.
It took me a moment to shift from one to the other. When you’re going through a shift like that, you have to have some reason for doing it. You have to have some objective that you want to get out of it. If you’re doing it just to do it, then you’re going to go through all the struggle of learning and adopting the new language. And that can be great from an educational point of view because you’re going to learn something new, you’re going to see new patterns, and it’s going to impact your work.
“[Adopting a language] can be great from an educational point of view because you’re going to learn something new, you’re going to see new patterns, and it’s going to impact your work.”
If you want to adopt a language, you need a reason for doing so. The idioms in one language may not carry over to another language. This is especially true when transitioning from Ruby to Elixir, as their idioms are dramatically different due to the shift from an object-oriented language to a functional language. Even libraries in these languages have different philosophies and operate differently at a fundamental level.
There’s a level of acceptance in approaching this from a different way. Instead of thinking, “I’m a Rubyist, and I’ll program in Elixir as if it were Ruby,” you should think, “I’m a Rubyist, but I’m learning Elixir, so I need to learn these new idioms and adapt over time.” You should have a reason for wanting to learn Elixir, and as long as you’re making progress toward that goal, you’ll learn the idioms along the way. You’ll pick it up quickly and achieve the initial reason for wanting to learn it. That’s the golden moment of adoption.
“You should have a reason for wanting to learn Elixir, and as long as you’re making progress toward that goal, you’ll learn the idioms along the way.”
Having a background in Ruby, what areas does it give you a head start in?
Even though you’re transitioning from object-oriented to functional programming, moving from Ruby to Elixir, one of the biggest advantages is that you already have experience with web development. At a high level, disregarding the specific languages, many of the terms and concepts you’re familiar with will still apply.
That’s a big part of the book, going from Ruby to Elixir. The second part of the book is all about familiar concepts and how to accomplish them in Elixir with different libraries. It’s about constructing applications and grasping the programming language. There’s a specific style of syntax that plays a significant role in providing you with a sense of ease, but it’s essential to keep in mind that these languages are very distinct from each other.
Syntactic sugar helps you gain comfort with your work, but there are distinct idioms and styles in the language. The key advantage of both Ruby and Elixir is their elegance and simplicity. They aim to be familiar to programmers and achieve this through the creation of custom DSLs.
“The key advantage of both Ruby and Elixir is their elegance and simplicity.”
As you program in these languages, you start to feel like you know what you’re doing even though you’re just learning it. I think that’s it. Having that experience with Ruby helps with that. But a lot of it is going through trial and error, learning different things, learning the libraries, and getting comfortable over time.
In the context of Elixir, what are some newly emerging patterns to adopt in order to be effective in development work, especially for those transitioning from Ruby?
Every language has its own patterns and idioms. Looking at Elixir, one of the first challenges people encounter is learning about pattern matching. This is a very hands-on keyboard type of learning. Getting comfortable with pattern matching is important because many tasks in other languages, even simple ones like an
if statement, are achieved through pattern matching in Elixir.
“Every language has its own patterns and idioms. Getting comfortable with pattern matching is important because many tasks in other languages, even simple ones like an
if statement, are achieved through pattern matching in Elixir.”
There are still
if statements in Elixir to help people feel comfortable, but really they’re pattern matching at the end of the day. That’s usually the first hurdle people hit because it’s a totally different, very powerful, and very expressive way of writing code. Elixir does it in a way that’s more integrated into the language than it is in other languages.
The next obvious topic for most people familiar with Elixir is the Process Model. Elixir’s concurrency model is different from other programming languages. People may have heard of the term “GenServer,” referring to Elixir’s concurrency model. This is not just a coding pattern, but also a way to architect your program. It’s important to understand when to use processes.
You probably need to know about processes, but you don’t need to write your own in the beginning. As you get more comfortable with Elixir and see how other libraries are using processes and GenServer to solve problems, you can truly adopt and use Elixir’s process model. You sort of absorb it over time, so you don’t need to know and use it from day one.
Elixir is known for its support of massive parallelism and scalability. Can you provide some insight on this?
The book definitely covers Elixir’s ability to scale and its parallelism model. I say parallelism model, not concurrency model because it’s about how Elixir’s VM, the BEAM, executes code. It does it in a highly parallel way, which is really cool. It’s rare for a language to do it as well as Elixir, and the BEAM does it.
“Elixir’s VM, the BEAM, executes code. It does it in a highly parallel way, which is really cool. It’s rare for a language to do it as well as Elixir, and the BEAM does it.”
The other cool thing about scaling in Elixir is that there are two different types of scaling. You have vertical scaling, which means that if you make a machine bigger by giving it more RAM and more CPU, will your application perform better? Will you have more request throughput on that server?
And then you have another type of scalability, which is horizontal. All of your nodes are the same size, and instead of making the node bigger to get more throughput, you add another node. Next thing, you’re running ten nodes in production, then running twenty—just scaling up in horizontal capacity.
The really cool thing about Elixir is that it does both really well out of the box. I won’t say it’s free because nothing’s ever truly free, but it’s as close to being free as you can get. Basically, if you give it a bigger CPU, it will just perform better. If you give it more nodes, you can build your application to work across those nodes really well, and you’ll just have a better performing application. The fact that it does these things without any external libraries is just supported by the VM, which is really powerful.
"If you give [Elixir] a bigger CPU, it will just perform better. If you give it more nodes, you can build your application to work across those nodes really well, and you’ll just have a better performing application. "
Can you tell me about the Open Telecom Platform, OTP, and its role in the Elixir ecosystem? How does it relate to someone who has experience working with Rails and similar technologies? What exactly is this technology and what does it correspond to?
OTP is an intimidating thing when people first come into the Elixir ecosystem because of what it stands for: Open Telecom Platform. It’s a little confusing at first—I’m not building a telecom application—but there’s actually nothing to be worried about.
What it really is is a collection of libraries built on top of Erlang and the BEAM, which is Erlang’s virtual machine. It provides a ton of functionality for building applications, including fault tolerance, supervisors, and the way applications work. OTP provides these concepts and primitives. OTP is something that is just part of Erlang and is shipped alongside Erlang.
You often see Erlang/OTP as one phrase, and it effectively refers to the version of Erlang that you’re using. It’s a library that you don’t need to think about too much, but Elixir directly uses it or is heavily inspired by it. GenServer in Elixir, for example, is actually an OTP concept that has been adapted to make it feel more like Elixir instead of something made in Erlang.
I couldn’t list all the concepts because there are probably hundreds of different libraries in the OTP package. OTP has been around since the late 1980s and is still being developed. There are very smart people working on making Erlang faster and more efficient. There have been significant improvements in the last year or two. It may be intimidating at first, but there’s nothing to worry about. It’s just a set of libraries.
What about fault tolerance? Can you talk about fault tolerance in terms of Elixir and the web, given your background and perspective?
Fault tolerance is one of the things that people often highlight as a major advantage of Elixir and BEAM-based languages. It is indeed true. The reason for this is that in an Elixir application, you have what I’d call micro applications running.
A web request can be considered as a micro application. It follows its own stack and memory and requests certain tasks to run on the CPU to accomplish its objectives. If it encounters an error, there are guarantees at the VM level that the error will be reported.
One of the only guarantees that the BEAM provides is that if there’s an error, you will receive an error message. This guarantee is really understated in terms of its importance. If something were to crash, if a request were to fail, or if your database connection encountered an error and the connection process crashed, you can be sure that the error will be signaled somewhere in your application.
“One of the only guarantees that the BEAM provides is that if there’s an error, you will receive an error message. This guarantee is really understated in terms of its importance.”
This is where the power of the process model comes in. There is a special type of process called a supervisor that manages other processes. If that process fails, you have choices. You can choose to restart it or back out of the application. You get to decide what happens.
Fault tolerance is about guaranteeing that my application will work in a certain way. If something crashes, I can restore it to a healthy state and my application will continue functioning. In other scenarios, a crash may not be recoverable, and you have to restart the server or perform some kind of operation to make the application healthy again. These problems can still occur in Elixir or any other language, but fault tolerance greatly reduces them.
Ruby is known for its phenomenal expressiveness. So how much of that expressiveness carries over to Elixir? Is Elixir a much smaller language? How does that work?
Ruby is the prime example of an expressive, joy-to-use programming language. It makes sense because that is the goal of Ruby. Elixir looks to Ruby as inspiration for how the language should feel. When programmers use it, they should feel that it’s expressive and a joy to use. That’s the part of Ruby that they really took and applied in the design of Elixir.
The syntax can feel very similar sometimes because that is a goal of Elixir as well. It’s definitely inspired by Ruby, but it’s not quite the same. Ruby is the number one programming language in my book when it comes to expressive programs. Elixir may be number two, right? It’s close; it’s not like other languages where that’s not a goal of the language. It is definitely a goal of Elixir. (laughs)
“When programmers use it, they should feel that it’s expressive and a joy to use. That’s the part of Ruby that they really took and applied in the design of Elixir. The syntax can feel very similar sometimes because that is a goal of Elixir as well.”
Another thing that Elixir has going for it in terms of being a joy to use is that it has a fairly small footprint from the language itself. There are a certain amount of functions and syntaxes that you have to learn, but it’s pretty manageable overall, which is the case with Ruby as well. You have a few syntaxes that really shine and let you build expressive apps, and Elixir takes that to heart as well.
In functional programming, there’s a lot of decomposition and small elements. When you’re coming from Ruby, which is object-oriented, how do you transition into the mindset of functional programming?
One great thing about functional programming is that once you start to understand it and really get into it, there is a certain simplicity where you can clearly identify functions. Not all functional languages have to be immutable, but the idea of immutability plays a role here. When you have a variable that holds a certain type of data, you know that the data won’t just change unexpectedly. This ties into the functional immutable side of Elixir.
However, it can be difficult when you first start working with a functional language, especially when manipulating data structures. For one of my first projects, I worked on an in-memory data structure that stored data. This data was then consumed and interacted with through an API, with real-time functionality being critical to the project.
The performance of the data structure was key. The code I wrote on that, I don’t know if I’d want to go back to it today. It was not very good code because manipulating these immutable data structures in the functional programming language is definitely a little bit trickier than Ruby and it can also be a little bit less performant.
So there are these aspects of functional programming that can trip people up. The best advice I would give someone struggling with adopting and adapting to the functional mindset is to practice the basics of manipulating some of the core data structures. In Elixir, that’s really gonna focus around maps and lists. Thinking about things like updating a key of the map, how do I do that?
How do I update a nested key of a map? (Let me clarify that it’s a nested key, specifically a list with a map inside—I want to update values of the nth element in that list.) These types of programming challenge questions come up as you learn how to use the
Enum module in Elixir and discover what tools are at your disposal for modifying these functional immutable data structures.
As you practice and become more familiar with it, it becomes second nature. However, there is a learning curve when you first begin working with it.
Can you discuss correctness?
It’s difficult to ensure correctness in most programming languages. However, some programming languages are designed with the goal of achieving this. So, proving the correctness of a program or using certain techniques is easier in those languages. But in most languages, it is very challenging to prove that something is correct.
When I consider this, I focus on how to determine if the input data will be what I expected. In Elixir, for example, I can use pattern matching to ensure that a function has an invariant where it will only receive a specific type of input. This gives me a 100 percent certainty that the function will receive the expected input. Therefore, it eliminates a certain type of bug from my program.
If something passes a value into that, it’s not allowed and the function won’t run. It will cause an error that will be reported, and maybe my test suite can catch it, or I can use some static analysis to help catch that specific type of error. Pattern matching can play a part in this. Another aspect of correctness that I think about is the idea of thinking here. This will be a cut section as I’m thinking about something related to correctness and pattern matching.
The other part, the thing that contributes to correctness, is the immutable side of Elixir. This aspect is likely to be the most helpful to people when it comes to writing correct programs. When you want to change a data structure, you have to do it in a specific way and assign the variables accordingly.
This allows you to use the updated data structure and gives you some guarantees. It ensures that something else in the code isn’t updating a data structure in a different location that you cannot currently see. For example, when you’re reading a file, that can’t happen in Elixir.
There is mutable state via processes, so there are always nuances to everything. But for the majority of data manipulation in Elixir, if you’re reading it on the screen, there won’t be surprises. There can’t be. And that goes a long way in writing correct applications.
“For the majority of data manipulation in Elixir, if you’re reading it on the screen, there won’t be surprises. There can’t be. And that goes a long way in writing correct applications.”
How does testing differ?
Elixir, to my knowledge, is one of the only languages that has built-in testing. ExUnit deploys with Elixir. It’s not something that you install; it’s just available, which is really cool. This idea of testing is similar to Ruby. It’s very big in Ruby.
Ruby was one of the first languages that I came into that had a very particular ethos of testing that holds true in the community. The libraries that are written there, the way people write their internal code testing, is very important in Ruby, and that holds true in Elixir as well.
It’s important to note that testing is highly valued in the Elixir ecosystem, as evidenced by the well-tested libraries and the emphasis on testing in writing internal programs. When it comes to actually testing, the process is similar to other languages with the setup and assertions. From the very beginning, it feels familiar.
Elixir provides tools to test complex things like processes and message sending, of course. But when it comes to actual testing, it just feels familiar. Even on day one, you’ll be able to write tests and know that due to the VM immutability and functional nature, the function you’re writing and testing will work a certain way, so you can be pretty confident about it now.
There are always bugs; people write bugs. There will always be bugs in programs, and Elixir doesn’t get rid of that. You can integrate error reporting and such to help in your journey of having a correct application, but there’ll always be bugs and exceptions. And Elixir does a good job at giving you a foundation for writing correct, well-tested programs.
“There are always bugs; people write bugs. There will always be bugs in programs, and Elixir doesn’t get rid of that. You can integrate error reporting and such to help in your journey of having a correct application, but there’ll always be bugs and exceptions. And Elixir does a good job at giving you a foundation for writing correct, well-tested programs.”
In your book, you talk about the philosophy of developing with Elixir: you build cities, not skyscrapers. Can you explain that further?
This phrase, “build cities, not skyscrapers,” stems from how Elixir has transformed my perspective on application development. The term “skyscrapers” isn’t the best choice because it might sound like I’m referring to the monolith versus microservices debate, but that’s not what I’m getting at. It’s about the way a single application is constructed. Traditional stack-based languages—and Ruby falls into this category, as do most web languages—use a different approach.
You have a web request that comes in, and, basically, you have a single stack throughout the application. You’re not interacting with stuff off that stack. The database operates on that stack, the caching operates on that stack. Everything is just one stack, up and down throughout your application. That’s the skyscraper, a big building.
It has a door at the bottom, you go to the top floor, come back down, leave out the door you came from, and Elixir gives you some options. You could build an application that way in Elixir if you wanted to, but it gives you the option to build a city. It’s like having micro applications that work together to form the larger application.
The database itself is a prime example of this concept. It can be seen as a mini application within the Elixir app. Being an application, it has its own data life cycle, error handling, stack allocation, and garbage collector. Essentially, it acts as a separate entity within the larger app. It’s important to note that all of this is happening on a single machine.
It’s all just one deployment. But that works together with the other parts of the app, which also works together with the web processing side. It works together with any type of custom code that you’ve written to maybe have performance optimizations around very specific caches that you’ve built.
You can build things in this model that I truly believe are impossible to build in other languages. That’s the thing that makes everything worth it for me. That’s why I use Elixir and why I love Elixir. I can build things and applications the way I want, rather than the way I’m told to build by the web framework.
“You can build things in this model that I truly believe are impossible to build in other languages. That’s the thing that makes everything worth it for me. That’s why I use Elixir and why I love Elixir. I can build things and applications the way I want, rather than the way I’m told to build by the web framework.”
What role does Phoenix play in development, and what is its equivalent in Ruby?
Phoenix is the most popular framework in the Elixir ecosystem. Most people would say it’s similar to Rails in the Ruby ecosystem, but there’s a distinction. The Project Phoenix has a motto: “Phoenix is not your application.”
Phoenix aims to effectively write web endpoints. In addition to Phoenix LiveView, there have been various other additions. However, setting those aside for a moment, Phoenix primarily focuses on serving as a web interface for your application.
This aspect is crucial because Phoenix is built with the ethos that the application belongs to you. You have the freedom to build it according to your preferences and expose endpoints through Phoenix accordingly. Phoenix offers patterns and convenient methods, but it constantly emphasizes that it is ultimately your application.
The reason I say that is different from the ethos of Rails is that Ruby on Rails seeks to be the entire toolkit you need. Everything is part of Ruby on Rails, so if you need something for your application, you can find it in Ruby on Rails.
It’s broken up into smaller libraries. When you pull in a Ruby on Rails app and build a new one, you’re pulling in libraries like ActiveRecord and ActiveSupport. These different things are part of Rails, but they come together to form Rails. Phoenix doesn’t have that same type of ecosystem.
Phoenix is a web framework that uses Ecto for its database. It’s not called Phoenix Ecto or Phoenix DB. Ecto is a separate library in the ecosystem. Phoenix focuses on being a great web framework. It’s lightweight, so using it doesn’t add a lot of overhead to your application. As a developer, it feels familiar and similar to writing Rails controllers, routers, etc.
It’s just a really simple, elegant web framework. There’s a reason it’s the most popular one in the Elixir ecosystem. It’s just very good.
“[Phoenix is] just a really simple, elegant web framework. There’s a reason it’s the most popular one in the Elixir ecosystem. It’s just very good.”
You mentioned Ecto. How does persistence and state work in your development in this Elixir environment, and what role does Ecto play? Are there other databases that you might prefer at other times? Or is Ecto the answer that everybody should be reaching for?
Data persistence in Elixir is very similar to other languages. You don’t really have special patterns or anything like that because it’s Elixir. It feels like you’re using a really good library for accessing the database. Elixir’s functional and immutable nature doesn’t play a big role in how you interact with the database.
It feels like a really good experience and Ecto is definitely the most popular database solution. I don’t know exactly what to call it because it’s not just a database driver; it’s not just a query language. It’s sort of everything put together, and it’s the most popular one in the electric ecosystem. I think 99.9 percent of people should just reach for that and use it, unless you have a very good reason not to.
The only other type of data store that immediately comes to mind is Elixir processes. Elixir processes work alongside Ecto and allow you to integrate them into your application. They can store state that you can interact with. So maybe you can perform tasks through them that you would typically do in a database. This means you can use both a database and in-memory persistence for better performance.
In Elixir, you have the choice to do that. However, Ecto is tightly integrated into the ecosystem, making it difficult to find a reason not to use it. Therefore, everyone should start with Ecto because it will likely work for you.
“Ecto is tightly integrated into the ecosystem, making it difficult to find a reason not to use it. Therefore, everyone should start with Ecto because it will likely work for you.”
What is Tesla other than a self-driving car?
Tesla is a library that allows you to write HTTP clients. I say it this way because there are Elixir HTTP clients that are very focused on providing a URL and making a request based on that. And that’s a simple concept for an HTTP client. Tesla takes a different approach where it allows you to write middleware that can modify the request or response based on your specific application logic.
This could include handling authorization for the API or any other custom logic you might have. Tesla actually uses other HTTP request libraries, so you have the flexibility to choose which library you want to use. It’s all about writing to the client using these request libraries. And I emphasize that because the client is not just about making a request. It’s also about handling authorization, input, output, and many other aspects. Tesla excels at addressing all of these requirements.
What about doing asynchronous jobs? What tools would you reach for for that?
There are three tools that I would consider when evaluating how to handle asynchronous jobs. Mainly this decision depends on a crucial question: Do I need to ensure that the job is completed? In most cases, the answer is yes, but sometimes it may be no. If you require the job to be guaranteed, then I would strongly recommend using a library called Oban. Oban is a database-backed job queue that allows for the insertion of jobs that are then processed and picked off by the job coordinators.
The reason I recommend this out of the box is that it has a good pattern of OTP usage. Good OTP usage in this case means it uses processes and supervisors appropriately to provide safety, fault tolerance, and optimization. You’re able to use your system to its full capacity with this right from the start.
The other solutions I mentioned that I might look at, depending on your needs, are
Task, which is built into Elixir, essentially a GenServer that runs asynchronously, or GenStage, a more complex library not covered in the book. GenStage is used for building a data pipeline that allows for more complex tasks compared to
Task or Oban. However, when it comes to job persistence, you’re on your own and you’ll have to build it from scratch.
I personally reach for Oban because it provides a complete solution to the problem. Oban just works, it works really well, and it’s the tool most people should use, unless they have a specific reason not to.
What is the story behind the book?
It’s because of my experience moving from Ruby to Elixir. I have a fondness for books that are created with a sense of urgency, so to speak. It’s actually a positive thing. It means that while you were building something, you considered ways to improve it for others and ways to share it with the world.
When I first started learning Elixir, I struggled with it. I was coming from Ruby and other languages, and although I could read and write Elixir, I didn’t fully grasp how it fit into applications and how to build applications with it. This book is my attempt to share my experience and help others learn it faster than I did, while also addressing some of the challenges I faced.
This is the second book I’ve written, and I really like this approach of structuring books in theory and practice sections. I find it helpful to have small examples in the theory section that are standalone, and then a single overarching project in the practice section.
In From Ruby to Elixir, I used this strategy to provide theory that helps readers learn how to read and write Elixir code. Additionally, I included a practical real-world application that teaches about Phoenix, Ecto, Tesla, and other libraries that are essential for building web applications today.
Who is the reader for your book?
The reader for this book should have some prior programming experience. It’s beneficial to have a background in Ruby because many of the examples in the book relate to concepts found in Ruby. The book aims to bridge the gap between Ruby and Elixir by building upon your existing knowledge and making Elixir feel familiar to you.
The examples apply to anyone coming from an Object-Oriented language in general. The ideas are about transitioning from object-oriented to functional and looking at different currency models. These concepts apply to other languages too. So if someone has prior programming experience, maybe at a beginner to intermediate level in Ruby, or even at an advanced level, and wants to learn Elixir, this is for them.
Maybe they’re learning it for fun, you know, because it’s something that can expand their horizons. Or maybe they’re on a team that’s adopted Elixir and they’re moving into a new role. Or maybe their company is considering Elixir and they’re currently working with Ruby and they want to know how to do things faster and ensure project success, you know? Those are the people who will really benefit from this book.
Where can people follow what you’re up to?
That is a good question. I have not been super active on social media. The places that I’m most active, for better or worse, are still Twitter and on the Elixir subreddit. I like to see people coming in with beginner-level questions and help point them in the right direction. So I’m pretty active there. Then, in the Elixir community on the forum and on the Elixir Slack.
Thank you so much.