Simple Functions

Phoenix is built on Elixir, which is a beautiful language, so we’re going to use Elixir to talk about the way the layers of Phoenix fit together. In Elixir, we might have a couple of functions like these:

 def​ inc(x), ​do​: x + 1
 def​ dec(x), ​do​: x - 1

We can chain together several different function calls like this:

 2 |> inc |> inc |> dec

The |>, or pipe operator, takes the value on the left and passes it as the first argument to the function on the right. We call these compositions pipes or pipelines, and we call each individual function a segment or pipe segment.

There’s a side benefit, though. Pipelines are also functions. That means you can make pipelines of pipelines. This idea will help you understand how the various layers fit together. Let’s take a look at what a Phoenix program might look like, using pipes:

 connection |> phoenix

Most of the time, you’d write phoenix(connection), but bear with us for a moment. We’re going to expand that phoenix function in a bit. We don’t care how the request gets to Phoenix. At some point, we know that a browser establishes a connection with an end user, and then there’s this big hairy function called phoenix. We pipe the connection into phoenix, it does its magic, and we’re done.

In Phoenix, that connection is the whole universe of things we need to know about a user’s request. It is a struct, which is a map with a known set of fields. The connection comes in with information about the request: whether it’s HTTP or HTTPS, what the URL is, what the parameters look like. Then, each layer of Phoenix makes a little change to that connection. When Phoenix is done, that connection will have the response in it.

Where Are All of the Diagrams?

In this book, we’re going to try something a little different. We’re going to use an experimental alternative to architectural diagrams.

For example, let’s say we’re showing you how to bake a cake. We could have a little diagram with boxes representing process steps that have beautiful bevels or drop shadows or other embellishments. Such a diagram would give you a quick mental picture of what’s happening. Then, you could mentally translate that diagram into code.

We can do better, though. Instead, we could choose to express the same idea with an Elixir pipe, like this:

  ingredients
  |> mix()
  |> bake()

That code isn’t as beautiful as a blinking diagram with fountain fills, but it’s tremendously exciting. That ugly text shows you exactly what the layers are, and also how the functions work together. It also helps you build a mental picture of what’s happening, because in Phoenix it is what’s happening. When you understand that diagram, you understand Phoenix. You’ll actually see code like that throughout the Phoenix framework, so we think it’s an excellent way to show how the parts fit together.

Now you know what the API of every layer of Phoenix looks like. Functions call other functions, and the first argument for each of those other functions is the connection.

The Layers of Phoenix

Let’s take our simplified version of Phoenix and break it down a bit. Let’s say that the request is a classic HTTP-style request. (The book will cover the more interactive channels API a little later, but the basic premise will be the same.) As we drill down to the next layer of detail, here’s what you see:

  connection
  |> endpoint()
  |> router()
  |> pipelines()
  |> controller()

Each request comes in through an endpoint, the first point of contact. It’s literally the end, or the beginning, of the Phoenix world. A request comes into an endpoint. From there, requests go into our router layer, which directs a request into the appropriate controller, after passing it through a series of pipelines. As you might expect, a pipeline groups functions together to handle common tasks. You might have a pipeline for browser requests, and another for JSON requests.

Inside Controllers

Web frameworks have been around for a long time. The main pattern we use has been around even longer. The Smalltalk language introduced a pattern called model-view-controller (MVC). Models access data, views present data, and controllers coordinate between the two. In a sense, the purpose of a web server is to get requests to functions that perform the right task. In most web frameworks, including Phoenix, that task is called an action, and we group like functions together in controllers.

To give you a little more perspective, the controller is also a pipeline of functions, one that looks like this:

  connection
  |> controller()
  |> common_services()
  |> action()

This view of the world may look much like what you’d expect from a typical web framework. The connection flows into the controller and calls common services. In Phoenix, those common services are implemented with Plug. You’ll get more details as we go. For now, think of Plug as a strategy for building web applications and a library with a few simple tools to enable that strategy.

In this book our actions will do many different things, from accessing other websites to authenticating a user. Most often, our actions will access a database and render a view. Here’s what an action to show a user might look like:

  connection
  |> find_user()
  |> view()
  |> template()

In Phoenix, we like to encapsulate all business logic in simple modules called contexts. If you’re using a database in Phoenix, you’ll probably use Ecto, the persistence layer. If you want to talk to another web application, there are many HTTP clients to choose from. Whether that code interacts with another web server or a database, you will want to keep the controllers clean and skinny.

There you have it. You don’t have to memorize all of these layers now, but you’ve seen the major pieces, and you know how they fit together. After a few pages of theory, you’re probably eager to roll up your sleeves and get started.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.219.34.62