POST DIRECTORY
Category software development

After tweeting that his inbox couldn’t handle any more requests for preview access, Chris McCord recently made the initial release of Phoenix LiveView public. The repo soon appeared on Github’s Trending page indicating wide interest among developers.

Announced at ElixirConf 2018, Chris described the framework as offering a vastly simplified programming model compared to JavaScript alternatives. He further explained that

while modern JavaScript tooling enables sophisticated client applications, it often comes at an extreme cost in complexity and maintainability. There’s a common class of applications where rich experiences are needed, but full single-page applications are otherwise overkill to achieve the bits of required rich interaction.

Haught Codeworks is writing Elixir and Phoenix code and spent a little time taking this first release of LiveView for a test drive.

Initial Impressions

  • To state the obvious: Web applications run on the web. HTML is the original and standard language of the web so I welcome any opportunities to build real-time, interactive applications while writing and managing relatively standard HTML.

  • I also welcome opportunities to reduce the number of places that state, business logic and rendering are handled. Server-side html and state management keeps these concerns close to the server-handled business and domain logic. This proximity can reduce duplication and mental task switching while making code easier to reason about.

  • Depending on how it evolves, there could be a business-case for Elixir, Phoenix and LiveView. A reduced stack complexity could result in shorter development cycles and reduced costs to design, develop, maintain and extend applications.

I am excited about this. Read on to find out why!

Demos

live-view-clock.gif

Check this out. It’s a clock. A simple little clock. But it has generated a little excitement because in this demo created by @alephnaught2tog the clock updated a thousand times per second. On the server. With Elixir).

There are other demos including a couple small games here and developers are creating new demos daily on Twitter.

Here’s a colorful counter, a Kanban app, a server-side input box, and a calculator. Would you ever really want to have a server-side calculator? I know you will not want to use LiveView for animation. These demos are simply people experimenting with LiveView and small programs are the easiest way to do so.

live_view_animation.gif

Let’s break down this discussion into its parts: Elixir, Phoenix and LiveView.

Elixir: A functional language

Developers report that their Elixir code is: * concise * explicit * changeable * understandable

That’s great for software developers writing and changing software.

Yet as a basis for real-time web apps what really interests us about Elixir and other functional languages is that data is immutable and immutability is ideal for concurrency. Let’s take a closer look at Elixir to find out why.

The developers of Elixir describe the language as “a dynamic, functional language designed for building scalable and maintainable applications. Elixir leverages the Erlang VM, known for running low-latency, distributed and fault-tolerant systems.”

The Erlang VM has been around 30+ years and was created to run telephone networks presenting an ideal use case for managing connections, handling and restoring drops, restarting on failures, and scaling to millions of concurrent connections.

It is this concurrency that allows Elixir to be massively scalable. To understand why, take a step back to Moore’s law which observed that the number of transistors (and therefore the raw computing power) on a chip doubles every 18-24 months.

In effect, software got faster every year even if it were not changed at all! Bonus for software developers!!

Now the rate of CPU improvement has slowed and software developers can no longer depend on faster CPUs as an answer for faster software. Instead, Elixir and other languages lean on concurrency to provide scalability and performance improvements.

As mentioned above, Elixir is a functional language. It turns out that Elixir’s functional language underpinnings are ideal for concurrency. In a functional language, data is immutable. The immutability of data rids developers of a whole set of concurrency-related problems. Because data cannot change, concurrency management issues such as data-locking go away or are drastically simplified and concurrency can be deployed at massive scale.

It is inevitable that developers would want to leverage that scalability when building applications for the world’s ultimate scalable platform – the Internet. Phoenix is a framework built to do just that.

Phoenix

Phoenix is described as “a productive web framework that does not compromise speed or maintainability. Phoenix brings back the simplicity and joy in writing modern web applications by mixing tried and true technologies with a fresh breeze of functional ideas.”

While Elixir and the Erlang VM are used extensively in embedded devices, web applications and non-web-supporting server processes, Phoenix is squarely a web-based development framework supporting web browsers and api-consumers such as mobile applications.

Phoenix web applications create server-generated HTML, generally in response to a request from the browser and follow the typical http request-response cycle, including authorization, authentication, routing and rendering.

This request/response cycle is a well-understood and supported approach to web application development. Yet, for interactions that desire a real-time experience, this cycle is slow and does not feel interactive.

Solutions to slow request/response cycles

Existing solutions to add interactivity to web applications include AJAX to eliminate UX delays as well as client-side JavaScript frameworks such as React to manage state locally while providing efficient rendering of UX updates.

With AJAX and asynchronous requests the user does not see a spinning wheel or browser-loading indicator, there is still a request-response cycle in use. The web server receives AJAX requests similarly to normal synchronous html requestss, and after responding there is no further communication nor state nor connection until the next request. The connection and state need to be rebuilt with each request.

With LiveView, the connection between the application and the client remains open throughout the user’s session. This real-time connection is provided via Phoenix channels.

Channels

To revisit how Phoenix leverages the strengths of Elixir to support channels:

Functional languages simplify concurrency, which enables a massive number of light-weight processes (Elixir processes, not operating system processes). Tons of Elixir processes allow each user to have their own connection, aka channels.

Having the ability to run hundreds of thousands of concurrent processes means that each user can have their own persistent, real-time connection between the server and their client (in this case the web browser).

By using connected, bi-directional, real-time connections, channels allow for millisecond response times.

LiveView leverages this ability.

LiveView

Because LiveView keeps a socket open between the client session and the server, time is not spent on each state change to handle http tasks such as authentication, authorization, and re-building state.

Each user’s socket has Elixir processes that maintain and manage state. When an event is received from either the web browser or the application itself, LiveView handles the event by updating state on the process. Then the LiveView template’s render is performed using the new state and diff’d against the cached version of the template in order to deliver only the parts that changed to the browser.

This approach is familiar to React developers. JavaScript frameworks that move state and rendering to the client provide a real-time experience. Yet these solutions add complexity and cost which LiveView seeks to avoid.

“No JavaScript”

Based on initial responses on Twitter, many developers excited about LiveView are excited about the possibilities of avoiding JavaScript where it adds unnecessary complexity.

We are not against using JavaScript. We write JavaScript every day and expect to continue to do so as long as we’re developing web-based applications.

When developers exclaim “No JS” in their initial reactions to LiveView, it is not always the JavaScript itself that they are relieved to avoid. Instead it is the complexity that comes from managing the JavaScript implementation of the application domain in parallel to the server implementation of the application domain. By performing rendering updates on the server, LiveView reduces that coordination, possible duplication and mental switching between spaces and languages.

Reduced JavaScript can also result in fewer lines of code. While lines of code is not a good measurement in itself when selecting an approach, it can stand as a proxy for development costs and speed. When changes can be made in a smaller domain and debugging can happen in a more focused set of code, costs and time to market are reduced.

Avoid duplication

With LiveView, the same html that you write for initial render is used for re-renders and updates. The same changesets you use for initial render and for non-live-view events can be used for LiveView actions. Whether being called in response to a plain http request or a live view, the data layer (such as ecto changesets) and the html layers do not care.

This makes LiveView ideal for things like form validation. The same validation used at the data layer is available to the live view and need not be re-created or re-called in JavaScript, for example.

Limitations

There are scenarios where LiveView is not a candidate. These include mobile native, compute-heavy applications and applications requiring offline use.

  • Mobile native applications: Applications desiring mobile native support will not benefit from LiveView. Unlike React, HTML is the only implementation target of LiveView. Note, however, that Phoenix applications can easily deliver API support for native mobile apps. Also, some developers have created native applications which are essentially wrappers around a web-view native component. In this approach, Phoenix could serve html to “native” apps’ web-view components.

  • Compute-heavy applications: Elixir is not designed for computationally intensive applications. Elixir’s power comes from the ability to manage thousands or millions of Elixir processes. Yet Elixir itself is not the fastest of languages. Similar to how you would not write a jet-fighter flight-control system in Ruby, don’t try to do so in Elixir either.

  • Offline environments: Phoenix and LiveView are built for online web applications. Unlike JavaScript applications that could use local storage mechanisms, a server-side implementation like LiveView is only possible in a connected environment.

Uncharted Waters

Like any new tool, we are evaluating LiveView but are cautious about a few aspects.

  • For sample applications like we have seen so far, the number of events and handlers is small and easily manageable. When the number of interactions and events grow to those found in a real production application, it will become important and challenging to arrange them in a way that keeps code concise and maintainable.

  • This approach of complete reuse between initial render html and re-rendered html could make for some sloppy UX. When UX updates and transitions are not explicitly designed and coded but instead happen automatically, less attention could be paid to handling conditions such as failed server responses or some edge cases. Sometimes out-of-sight means out-of-mind. While LiveView could easily make UX updates in response to state changes out-of-sight, we must be careful not to forget about making the experience a positive one for users.

  • While proximity of domain-logic and presentation in the codebase can reduce costs and complexity, a monolithic approach can blur the lines between the two aspects of an application and introduce unnecessary coupling that reduces the ability for future change. Interestingly, the fact that state changes are required in order to trigger a LiveView re-render means that performing operations in html is discouraged. Data loading inside a LiveView template will not work. This has the side effect of enforcing the best practice of keeping data loading and state calculations in the domain-specialized Elixir code and out of your view code.

Resources

Try it out!

LiveView is so easy to implement that I recommend giving it a try to determine if there is a fit for your projects. To get started, take a look at these resources:

Getting started:

Elixir
Phoenix
Phoenix LiveView
Phoenix LiveView Examples
Phoenix LiveView Module Docs
Phoenix LiveView JavaScript Client

References:

Programming Elixir 1.6 by Dave Thomas
Programming Phoenix 1.4 Chris McCord, Bruce Tate and José Valim
Learn Functional Programming with Elixir by Ulisses Almeida

''