00:00:11.840
Hello, everyone. Welcome to my talk. Today, I want to discuss the Phoenix framework.
00:00:17.609
My name is Christian Koch, and I'm from NCSA in Chicago. I have a few goals for today's talk.
00:00:26.119
First, I want to familiarize you with the Phoenix framework generally. Additionally, I hope to connect our discussion to Elixir, OTP, and Erlang.
00:00:32.730
I will explain some of these concepts shortly.
00:00:40.440
So, what this talk is not? Unfortunately, there will be no Phoenix puns.
00:00:46.170
I'm sorry about that, but I recognize that you are a sharp RailsConf crowd. I certainly don't need to pander to you with pictures of my cats, as that would be an insult.
00:00:51.539
Now, why not talk about Rails?
00:01:04.049
That's a reasonable question to ask at RailsConf. I didn't come here to tell you to abandon your Rails apps. I'm not an evangelist.
00:01:09.750
Rails is great, and I enjoy working with it. I know it very well. It's fast to deliver functionality and quick to develop.
00:01:16.799
However, I don’t particularly enjoy trying to scale my Rails apps.
00:01:23.040
Scaling usually requires more than just spinning up additional servers and often involves new technologies in the stack.
00:01:28.650
For example, Redis, Sidekiq, or perhaps Elasticsearch.
00:01:36.689
Let's consider one alternative: the Phoenix framework.
00:01:42.390
There are many similarities to Rails; they share many of the same motivations.
00:01:49.049
Chris McCord, who was a Rails programmer, created the Phoenix framework.
00:01:54.479
Both frameworks are designed to be productive.
00:01:59.610
They emphasize convention over configuration and both are server-side MVC frameworks.
00:02:04.619
However, there are important differences.
00:02:10.560
Phoenix is written in Elixir, a functional programming language.
00:02:15.900
A Phoenix app is compiled and it isn't just an app; it's an implementation of an OTP application written in Elixir.
00:02:21.630
Today, I may use Elixir and Phoenix interchangeably because the Phoenix framework is fundamentally constructed in Elixir.
00:02:27.300
By design, programming with Phoenix is programming with Elixir.
00:02:39.500
So, what exactly is the Phoenix framework?
00:02:45.870
It is a web framework written in Elixir, which is a functional language developed from Erlang.
00:02:51.720
Let’s look at what each of these components entails.
00:02:56.790
Functional programming provides data immutability.
00:03:01.950
This means actions taken on data structures always return a new data structure while leaving the original unchanged.
00:03:07.260
In functional programming, there are no objects or classes; rather, you pass data, like hashes and arrays.
00:03:15.090
Functions are first-class citizens in Elixir.
00:03:21.390
Erlang is a programming language used to build scalable, soft real-time systems.
00:03:26.790
It has requirements for high availability and was originally developed by Ericsson to support telecom infrastructure.
00:03:33.930
The fault tolerance required for seamless failover makes Erlang ideal for web applications.
00:03:39.390
With a syntax that bears some similarity to Prolog, Erlang is used by several production companies, including WhatsApp.
00:03:46.650
The OTP, or Open Telecom Platform, is not quite a full-fledged framework.
00:03:53.070
Instead, it is a collection of Erlang libraries and design choices that support the development of distributed applications.
00:04:00.390
These applications are highly available, supervised, and resistant to failure.
00:04:07.140
Elixir, designed by José Valim, is a dynamic functional language.
00:04:13.370
Its syntax is somewhat similar to Ruby.
00:04:19.019
Elixir offers the possibility of building distributed, scalable, maintainable applications with low overhead.
00:04:24.060
Let's talk about why Phoenix is important.
00:04:29.820
Phoenix is written in Elixir and designed to run on the Erlang virtual machine, making it functional and immutable.
00:04:36.450
It is asynchronous, scalable, lightweight, and fast. A Phoenix app is compiled for runtime stability.
00:04:42.360
Its design is well-suited to today's web environment, where multi-core processors run multiple processes.
00:04:53.610
Numerous companies are running Phoenix in production.
00:04:59.370
For example, Bleacher Report claims they handled eight times more traffic after transitioning from Rails to Phoenix.
00:05:05.580
They reduced their server count from 150 to just five. While this sounds a bit exaggerated, it illustrates a key point.
00:05:12.320
Now, let's look at a practical example.
00:05:16.170
In this Ruby example, we define a class and a method to modify a hash by adding a value.
00:05:22.320
When evaluated, both the original and new hashes share the same value since mutating directly can lead to shared references.
00:05:30.060
Let's now translate this example into Elixir.
00:05:35.580
Instead of a class, we define a module and create a function within it.
00:05:41.490
Since a module is just a collection of functions, there's no concept of instance or class methods.
00:05:47.669
When evaluated, the result appears similar: the new map is modified while the original remains unchanged.
00:05:55.620
Let's break down the workings of the transformation function.
00:06:03.480
We call the 'update!' method via the map module, as there are no objects to call methods on directly.
00:06:10.800
The 'update!' function requires three arguments: the map, the key, and an anonymous function.
00:06:15.810
The function processes the value of the map key as an argument.
00:06:21.330
In Elixir, the immutability of data structures allows us to avoid unintentional side-effects.
00:06:28.020
If we revisit the Ruby example, we could use 'dup' to create a copy, keeping the original hash unchanged.
00:06:33.210
However, this only results in shallow copies and doesn't work with nested objects.
00:06:39.750
Language-specific concepts will arise.
00:06:45.120
In Elixir, we use lists instead of arrays, and maps in place of hashes.
00:06:51.900
Instead of objects, Elixir has modules, which are groups of functions.
00:06:57.300
The BEAM is the Erlang virtual machine where all Phoenix and Elixir code executes.
00:07:04.590
Tuples are ordered collections of elements defined between curly braces.
00:07:11.180
In Elixir, there isn't a for loop; instead, it emphasizes recursion and higher-order functions.
00:07:16.500
Examining a Rails project alongside a Phoenix project, we can identify several similarities.
00:07:22.169
In Elixir, the 'mix' module combines the roles of bundler and rake.
00:07:29.610
In a Phoenix project, we can generate migrations and controllers, views, and more.
00:07:36.750
Unlike Rails, Phoenix requires explicit pluralization definitions.
00:07:43.920
The structure of a Phoenix project is reasonably similar to that of a Rails project.
00:07:49.680
The '_build' folder contains compiled project files, while the 'deps' folder contains necessary dependencies.
00:07:55.350
In a Phoenix project, the 'web' folder closely resembles the 'app' folder in Rails.
00:08:01.280
Channels in Phoenix serve as the equivalent of Action Cable or WebSockets.
00:08:07.510
With the upcoming Phoenix 1.3 release, several changes are set to be introduced.
00:08:14.750
Therefore, if you start a new Phoenix 1.3 project, it will differ from the 1.2 version.
00:08:20.350
Postgres is the default adapter for new Phoenix projects.
00:08:25.750
While there is support for other adapters, they may not always align with the latest release of Ecto.
00:08:31.300
Interestingly, there are not one but two Microsoft SQL adapters available.
00:08:37.070
Both the MSSQL Ecto and Amnesia adapters are relatively new.
00:08:43.200
Now, let’s discuss the MVC structure in Phoenix.
00:08:48.540
To begin, let's look at the controller.
00:08:55.500
For example, a Rails controller and a Phoenix controller demonstrate minimal differences.
00:09:00.880
In Phoenix, a controller action requires two arguments: the connection and the parameters.
00:09:06.220
In Rails, the connection is often implicit, derived from the application controller.
00:09:12.000
This aspect is part of the speed and ease of development that Rails provides.
00:09:18.950
In contrast, Phoenix requires a more explicit handling of the connection.
00:09:27.700
If you're wondering how the connection comes into play, we can examine the endpoint module.
00:09:35.480
In a Phoenix app, you declare each plug to represent a transformation.
00:09:41.570
Each transformation in your web request processes as it enters the application.
00:09:48.500
In many cases, you don’t need to worry about this like you do in Rails, but it's good to know it's laid out.
00:09:55.170
This location is also a great place to add custom functionality if necessary.
00:10:01.920
So, plugs and racks are similar; however, plugs can be anywhere.
00:10:06.570
Essentially, they are similar in how they affect web requests.
00:10:12.270
Now, the second argument in the controller action is a map.
00:10:19.470
It structures request parameters into a variable called 'data'.
00:10:25.050
Since we are working in an MVC framework, we likely expect there to be a database query.
00:10:31.110
Interestingly, when we perform a query, we don't invoke it on the model as in Rails.
00:10:37.080
Instead, we specify the Repo module, designating the model table for our query.
00:10:43.710
This format will change slightly in Phoenix 1.3.
00:10:49.310
Our controller must declare the view template to be used.
00:10:56.570
There's no implicit assumption on which view file gets rendered.
00:11:02.470
This clarity is not trivial in an application, especially larger ones.
00:11:09.080
We can easily switch out the desired view template because it is defined explicitly.
00:11:15.420
Phoenix as a framework itself acts as an interface.
00:11:22.110
It is essential to denote that Phoenix is an implementation of an OTP app.
00:11:29.350
With Rails, you tend to rely on implicit promises your app offers.
00:11:36.860
This can include assumptions about view rendering or using shared instance variables.
00:11:43.270
In contrast, Phoenix operates differently.
00:11:49.970
Interacting with your own code involves passing data structures to functions instead of sharing objects.
00:11:56.780
This conceptual shift can isolate your application code, reducing complexity.
00:12:03.520
Now, let's explore how we can structure this to be more functional.
00:12:10.020
We can use the pipe operator, which helps express the flow of values through functions.
00:12:16.670
This way presents data more clearly as it moves through a series of transformations.
00:12:23.200
Functionally, this fits well into the HTTP request-response cycle.
00:12:29.960
Any web request can be viewed as a function, capturing all necessary information for processing.
00:12:35.430
Statelessness is crucial for the Web, and both Rails and Phoenix share this characteristic.
00:12:41.450
There's no reason you can't structure your Rails app in a manner expressing a series of discrete transformations.
00:12:49.610
The design structure imposed by your language and framework influences how you write application code.
00:12:55.490
Looking now at the Phoenix model, it's often harder to search for information.
00:13:01.920
Typically, typing Phoenix model won't yield the relevant search results.
00:13:08.280
As we've seen, database queries don’t rely on model functions but on the Repo module.
00:13:15.460
This means models in Phoenix primarily manage schema and data validation.
00:13:21.530
Expanding the 'Web' model function imports some Ecto modules.
00:13:28.390
This structure defines the schema directly within the model instead of a separate schema file.
00:13:34.900
You set field names, data types, and any default or null values as needed.
00:13:41.320
Change sets are how Ecto transforms data structures like maps and lists into formal structures.
00:13:48.160
Ecto provides functions to manipulate change set data.
00:13:54.330
For example, the 'cast' function will attempt to coerce parameters non-destructively.
00:14:01.190
You can validate required fields to ensure they exist in the parameters.
00:14:07.400
Updating a change set applies more invasive coercion to the data.
00:14:13.050
While the manual boilerplate is lengthy, you explicitly declare validations.
00:14:20.660
While this might feel less DRY, validations in the model can help manage error responses.
00:14:27.160
Moreover, you can write custom validations with error messages attached.
00:14:33.030
Continuing with our basic Phoenix model, they tend to get skinnier as they revolve around data validity.
00:14:39.950
There's much more to explore regarding Ecto and the persistence layer.
00:14:46.840
Next, let’s return to the controller and see how it interacts with the model.
00:14:53.970
The change set function performs insert actions.
00:14:59.640
The 'create' function in the controller corresponds directly to this action.
00:15:06.010
Pattern matching is used on the result of the Repo insert function.
00:15:12.640
The return will typically be a tuple indicating success or failure.
00:15:18.240
The 'ok' atom confirms the expected result, allowing us to proceed down the happy path.
00:15:25.570
If the change set fails due to validation issues, we respond with error messages.
00:15:32.030
This includes setting HTTP status codes and error or warning messages.
00:15:39.880
Bringing everything back together, we render a view for the vanilla Phoenix app.
00:15:46.340
Rich Hickey, the author of Closure, discusses the complexity found in simplicity.
00:15:52.340
Rails embraces convention over configuration.
00:15:58.320
This makes it easier to work with, but it hides complexity.
00:16:04.060
In contrast, Phoenix is less straightforward, requiring more explicitness.
00:16:09.610
This encourages simplicity, showcasing how models in Phoenix perform data validation.
00:16:16.590
While separate modules are needed for database queries, this architecture fosters a clear separation.
00:16:23.040
Despite this could also be achievable within Rails, the core framework's use may dictate the design.
00:16:29.400
Transitioning back to the controller, we'll now examine Phoenix views.
00:16:37.620
They're simple and invoke functions via the render instruction from the controller.
00:16:44.220
You need to explicitly define the view module template and the corresponding variables.
00:16:50.470
The basic application template might not be intriguing on its own.
00:16:57.260
The crucial part is where the template integrates the render function.
00:17:03.610
This resembles a yield block within a Rails template.
00:17:09.930
To define our view module, we can add a decorator function, rendering our show template.
00:17:17.140
The template utilizes EEx code, which looks similar to ERB.
00:17:24.020
We can incorporate the previously defined title function back into our template.
00:17:30.000
After a lengthy examination of a basic web request, I wanted to highlight the similarities between Phoenix and Rails.
00:17:37.290
Getting started with Elixir code and Phoenix shouldn't be overly daunting.
00:17:43.700
It should feel familiar enough for you to comfortably explore.
00:17:50.640
However, Phoenix is not Rails.
00:17:55.590
While they're similar, they differ significantly.
00:18:02.740
It’s through these differences that we start to appreciate the strengths of Elixir.
00:18:09.260
We didn't delve into testing, but trust me: tests run quickly.
00:18:16.410
There’s minimal need for mocking or stubbing, and tests are generally easy to write.
00:18:23.080
Response times in Phoenix apps are microseconds, which is impressive.
00:18:30.160
While we've developed a simplistic app with one database record, which may not provide meaningful metrics,
00:18:38.520
You can effectively add queues and background workers simply by incorporating code.
00:18:47.040
Queues exist within the Erlang VM processes, beginning and managed by your application.
00:18:53.310
Built-in failure handling is a notable feature of the OTP framework, which provides a Supervisory tree.
00:19:00.000
This structure monitors running processes and your database connections.
00:19:06.830
Your application is designed to crash, being restarted, minimizing disruption.
00:19:13.250
Elixir and Phoenix may seem immature compared to more established technologies.
00:19:18.950
However, a Phoenix application is effectively an OTP application.
00:19:26.000
This is a well-defined operational paradigm, with Phoenix and Elixir powering the application.
00:19:33.000
This code has been battle-tested since the 1980s, making it older than Java.
00:19:40.020
The BEAM, similar to the JVM, is powerful within the Erlang ecosystem.
00:19:45.820
It is lightweight, fast, fault-tolerant, and highly scalable.
00:19:53.370
Due to its lightweight nature, growing your application requires relatively less infrastructure.
00:20:00.210
While some libraries might not be available yet, the elixir ecosystem is growing rapidly.
00:20:07.090
However, many similar libraries do already exist.
00:20:13.290
Elixir is fully interoperable with Erlang, simplifying library imports.
00:20:20.500
Should you use Phoenix? Yes! I encourage experimentation with it.
00:20:27.130
However, the answer depends on your specific needs.
00:20:34.490
If your query is about completing specific tasks, the answer is likely yes.
00:20:41.570
You might just need to create your own solutions or packages.
00:20:48.480
However, if it’s about whether Phoenix is right for your company, that relies heavily on your context.
00:20:54.630
Building core competency within your organization can support advocacy for Phoenix.
00:21:01.210
Encouraging your team to build an interest and skillset can help.
00:21:07.870
Interestingly, the learning curve isn't as steep as you might expect.
00:21:15.090
The similarities between Rails and Phoenix provide a distinct advantage.
00:21:24.040
Let me leave you with a quote from Jim Jarmusch's film 'Ghost Dog: The Way of the Samurai'.
00:21:33.430
"The second half is the same for anything called a way. If one understands things this way, it should be easier to be in accord with their own path."
00:21:39.680
I hope I've helped you understand the Phoenix framework better.
00:21:46.140
Consider using it in an upcoming project, but I'm not advocating abandoning Rails.
00:21:52.140
Phoenix is new and shiny, enticing in its own way, yet it remains a different tool in our toolbox.
00:22:01.500
It suits specific problems better than Rails does.
00:22:08.370
As Rails or Elixir programmers, exploring different technologies can provide great benefits.
00:22:15.340
These explorations not only convey different methods of doing things but may also challenge previous perspectives.
00:22:22.750
Thank you for your attention.