Talks

Why I choose Phoenix

A talk from RubyConfTH, held in Bangkok, Thailand on December 9-10, 2022.

Find out more and register for updates for our 2023 conference at https://rubyconfth.com/

RubyConfTH 2022 videos are presented by Cloud 66. https://cloud66.com

RubyConf TH 2022

00:00:15.139 Hello everyone! It's great to be here. I've always wanted to come to Thailand.
00:00:20.580 To Bangkok, to eat as much as humanly possible, and I've started doing that.
00:00:27.300 It's been really wonderful. I started with Ruby back in 2008, so it's been over a decade that I've been writing Rails apps and doing Ruby.
00:00:34.320 I came from a world that wasn't great, specifically working on Flash banner ads.
00:00:39.960 When you're building something that everyone loves on the internet, it gives you a warm feeling inside.
00:00:45.300 That's part of where I started with ActionScript 3, which is very similar to Java.
00:00:52.260 I got to a point where I thought, my life shouldn't be this painful. Why do I hate working?
00:00:58.680 I looked for other technologies, and what I found were these two options.
00:01:06.060 It was very hard to decide which of the two things that looked good I should pick.
00:01:11.520 So, I asked a woman named Amy Hoy, who does a lot of marketing stuff and had her own SaaS for time tracking.
00:01:17.040 At the time, I think it was called Freckle. I asked her what I should pick, and she said, 'Ruby! It's easy, just go with Ruby.'
00:01:22.380 I like to give important decisions in my life to other people, so I was like, 'Okay, I'll pick Ruby.'
00:01:28.380 I went with it, and it was really the first programming language, the first stack, that made me feel good.
00:01:36.299 I enjoyed doing side projects, and I even liked working on some of the boring stuff.
00:01:42.900 I didn't think it was possible, but it was, and I felt that feeling for about 11 years.
00:01:48.000 I've used a lot of tools in between; I did Swift for a year, Go partially, and Python for a year not too long ago.
00:01:54.960 All of it really just felt like tools to me. It's good not to get super emotionally attached to your tools.
00:02:05.700 However, Elixir and Phoenix are the first stack I've used that again gave me that joy from my work day-to-day.
00:02:12.300 With side projects, I've been able to create in a new way which feels refreshing.
00:02:18.660 The functional nature and how everything is put together forces you, with constraints, to think about your problems differently.
00:02:25.379 And the way I think about them differently is in a very positive way.
00:02:31.620 I don't know how long I've been doing Elixir development, probably off and on for about six years.
00:02:38.280 But definitely in the last two years, for any new projects I create, I start with 'mix phx.new' instead of 'rails new'.
00:02:44.640 So, thank you for the joy you brought me for 11, 12, or 10 years; I don't know how long it’s been.
00:02:51.480 I've spent enough time with Ruby that I'm comfortable enough to move on to a different stack.
00:02:57.420 I don't want you to think this is going to be any kind of Ruby-bashing talk at all.
00:03:04.099 I still appreciate Ruby, and I still use it sometimes.
00:03:09.900 I actually just wrote my first Elixir script the other day, which was one of the last holdouts I had from Ruby.
00:03:15.659 If I needed to do something quickly on the shell, I would use Ruby.
00:03:22.860 I'm almost completely done using Ruby, but I love the community and everything it has brought me over the years.
00:03:31.080 All I have to say is, there are other options out there that you might want to explore to solve different problems.
00:03:37.139 Here are ten reasons why I generally choose Phoenix before I would choose any other stack at this point.
00:03:42.600 Reason one is that everything is designed to be parallel.
00:03:47.699 There’s Moore’s law, and computers aren't really going to get faster anymore.
00:03:53.160 The megahertz aren't going to increase, but we're going to have 10 billion cores in our computers.
00:03:59.610 So everything needs to go parallel, and it's essential to think in a parallel way.
00:04:05.180 It's an exaggeration, but it's necessary to have technologies that prioritize parallelism.
00:04:10.320 For example, Go has channels, while Elixir has its processes.
00:04:17.460 Everything you use in Elixir is within a process. Your shell runs in a process, your repo runs in a process.
00:04:23.580 All of the components in Phoenix are running in processes.
00:04:31.139 When you start working in a parallel environment, it helps overcome the challenges of using threads or forking out processes.
00:04:39.360 You can create millions of processes if you want, and they take up very little memory to start.
00:04:48.000 They own their memory space, and errors are encapsulated within them.
00:04:53.600 If one crashes, it's just that process that crashes, not the whole system.
00:05:01.020 Unless, of course, you are using a supervision tree, which is a nice feature I'm not discussing today.
00:05:07.320 If you want to, feel free to come up to me later in the conference and ask me any Phoenix or Elixir questions.
00:05:13.080 You can start a simple process using spawn, which returns an address to that process.
00:05:18.660 The address is essentially where you send messages. All of these processors are started around you, and you get addresses to them.
00:05:25.000 You can also name them after a module to give it a permanent name.
00:05:31.680 Then you can send messages to it using its permanent name, or keep track of these PIDs.
00:05:38.460 Usually, in a process, you'll have a loop that continuously pulls messages off a mailbox.
00:05:44.480 Think of a PID like a mail address; when you send it a message, it goes into a mailbox, essentially a queue.
00:05:51.180 You can pull them off synchronously.
00:05:57.000 In a real production application, you spawn higher-level abstractions to manage processes.
00:06:02.940 You can start them in your application, using a supervisor tree, where one process looks after child processes.
00:06:09.380 If something breaks, the supervisor knows whether to restart it or alert you.
00:06:15.600 You can also use something called a task, which is another abstraction on top of processes.
00:06:22.920 Why am I discussing processes in the context of Phoenix?
00:06:28.740 One issue I've had with Rails, for example, is starting long-running processes or doing polling jobs.
00:06:37.320 I often end up starting polling jobs to retrieve information from a service several times a minute.
00:06:44.700 Pub/Sub works very well in the Elixir world.
00:06:52.680 So, if you need to fire and forget some message, you can send it to a process.
00:06:58.680 It can be processed outside of your normal synchronous application workflow.
00:07:06.120 For example, if you're sending off analytics that doesn't need to be perfect, you can fire them off to a process.
00:07:13.740 Sending emails and similar tasks are great for this.
00:07:20.520 You end up with an ecosystem of processes communicating with each other.
00:07:28.680 One runs here, another runs there, and the architecture in my mind makes more sense.
00:07:35.160 It feels like many little microservices that simplify communication.
00:07:41.820 Reason two is that Phoenix is incredibly fast right out of the box.
00:07:50.100 It's very quick, not quite Go speed, but close.
00:07:56.520 Many of my requests come in nanoseconds rather than milliseconds without any optimization.
00:08:03.000 I often run it on a Heroku dyno, so not a hefty box, and it feels very responsive.
00:08:09.480 For example, I've worked on a sports meditation app with a React Native frontend and a Phoenix backend.
00:08:15.120 It was featured multiple times on the App Store, and there was no blip in our CPU or memory usage.
00:08:22.140 The throughput was steady, even during huge traffic increases.
00:08:29.640 Reason three is that the testing story is excellent.
00:08:35.520 Out of the box, you get 'mix test,' which looks in your test directory and runs any files named appropriately.
00:08:42.120 There's tooling that allows you to use describe blocks like with RSpec.
00:08:49.200 Everything just works! Because it’s functional, it's often easier to reason about your testing workflow.
00:08:55.800 I have a productivity tip: if there's something you're procrastinating on, move it closer to you.
00:09:02.700 If you're learning an instrument or trying to write more, keep your guitar or writing tools close to eliminate friction.
00:09:09.840 There's a lot of friction with testing; I don't want to write tests because setting up the testing environment takes too long.
00:09:16.920 There is essentially one way to do it in Phoenix, and it works really well.
00:09:24.000 You can write tests incredibly quickly, including tests for web requests that are provided out of the box.
00:09:30.780 This makes testing efficient and fast, another reason people might neglect testing.
00:09:36.180 Running the entire test suite can take a long time, but the application I'm currently working on has a 30-40 minute test runtime.
00:09:44.040 This is a large Phoenix app, and it's manageable, so you reach a point where performance matters.
00:09:50.640 Now let's talk about creating some tests.
00:09:56.160 This is a simple example; if you create documentation, you can use it in structure.
00:10:02.520 With this example, if you have an IEx command in your documentation, you can write tests around it.
00:10:09.000 This structure allows you to verify that your documentation accurately represents the expected outcome.
00:10:15.300 Coverage tools come with the testing framework. You use 'mix,' the primary tool for generating and running tasks.
00:10:22.020 Running tests with a flag also gives you coverage results.
00:10:29.460 You receive an HTML report that helps you visualize where you're covered and where you're not.
00:10:35.880 So, reason four is that the Phoenix dashboard is added by default.
00:10:41.100 It provides useful metrics and real-time graphs. For example, you'll see RAM usage information.
00:10:49.380 There’s a thing called an atom in Elixir, which is similar to a symbol, and it tracks your memory usage.
00:10:56.100 Excessively created atoms can crash the Erlang VM if all memory is consumed.
00:11:03.240 You can add other metrics easily, and it’s backed by a library called Telemetry.
00:11:09.180 Telemetry is written in Erlang and is designed to work seamlessly with Elixir.
00:11:15.660 It’s usable similarly to the instrumentation used in Rails.
00:11:22.740 You can see your versioning, memory setup, and other metrics, including request logs.
00:11:29.640 You can push it onto production if you want, using your existing authentication.
00:11:36.600 This is all available for free and easily extendable.
00:11:42.120 Reason five is the conversation around Phoenix and being more Rails-like.
00:11:49.560 I've talked about this at Elixir conferences; some think it should be more Rails-like to attract more people.
00:11:57.720 Jay was saying it should be less so to facilitate a more flexible system.
00:12:05.520 With Phoenix, you separate concerns into different areas rather than merging everything into one.
00:12:11.640 You have a DWC web folder containing controllers, live views, channels, and templates.
00:12:19.080 Your domain logic goes into the app's flat namespace, where you can interact with databases, and much more.
00:12:25.680 It's a divergent approach from the Rails axiom: 'Rails is not your application,' advocating for clean architectural separation.
00:12:32.100 Reason six is that you get to keep your Rails-like generators.
00:12:39.480 HTML generation, JSON templates, model-like migrations, and channels for live views are all supported.
00:12:45.060 You can easily create your own generators using mix tasks.
00:12:50.100 Reason seven is that authentication is shipped with Phoenix.
00:12:56.820 There is a dependency called Phoenix Gen Auth.
00:13:02.520 Jose had experienced some dissatisfaction with Devise's inflexibility, which lacked adaptability.
00:13:07.620 He opted to work with generators instead of a library, making it easier to manage upgrades.
00:13:13.500 With its built-in authentication, you gain access to all relevant files allowing for easier implementation.
00:13:19.620 Reason eight discusses channels, which manage WebSockets in Phoenix effectively.
00:13:25.440 It's straightforward to set up and is based on core utilities in Elixir and Erlang.
00:13:31.020 You just create a socket and send tokens if necessary, which get pushed into the channel.
00:13:36.600 When you join, the channel requires you to implement a join function; events through the WebSocket go through handle functions.
00:13:44.040 You may see error messages when working with this interface, communicating through processes running continuously.
00:13:50.460 As you progress, you'll naturally dive deeper into how these Elixir patterns operate.
00:13:57.180 These channels have clients in various programming languages; I've used the Swift and JavaScript clients.
00:14:04.620 You can easily use Phoenix as your WebSocket API and integrate it with your existing applications.
00:14:11.460 Live view is groundbreaking, allowing you to render HTML and handle requests on the client side without much JavaScript.
00:14:19.440 You can increase interactivity, creating responsive interfaces without the overhead of a traditional framework.
00:14:26.760 The basic Javascript setup requires you to import a live socket, a very intuitive and developer-friendly process.
00:14:36.960 If you need JS interactivity, hooks allow seamless integration with your applications.
00:14:43.440 However, I find that most of the time, using React is unnecessary for simpler applications.
00:14:50.880 Typically, it's a single action, like clicking a button, which works seamlessly.
00:14:57.480 The most basic live view setup leverages sigils for creating data structures that validate HTML.
00:15:05.160 It swiftly updates whenever assigns are modified or the socket state changes.
00:15:11.460 You can connect actions through Phoenix clicks to handle dynamic updates from the client side.
00:15:18.840 To increase your thermostat's temperature, you create a button linked to the socket, enabling real-time adjustments.
00:15:25.260 The final reason, reason ten, is Livebook.
00:15:32.640 It's akin to Jupyter, with sections of markdown allowing for organized documentation.
00:15:38.760 You can run code cells, create graphs, and include API forms for interactive exploration.
00:15:46.560 You can run queries directly within Livebook, or create stand-alone Livebook components.
00:15:53.520 In relation to Phoenix, you can connect your Livebook to a running instance.
00:15:59.760 This enables live experimentation with your application and allows for broader use cases.
00:16:07.440 At my work, we utilize Livebooks for visualizing data and analytics.
00:16:14.280 They provide product teams insight into results without digging deeply into technicalities.
00:16:21.960 Upcoming improvements to documentation will link more relevant assets directly into Livebook.
00:16:28.920 It's an engaging way to present live documentation.
00:16:34.920 As seen in recent updates, interactive forms boost communication and engagement.
00:16:41.520 There’s a site that hosts Livebooks on the web, allowing immediate access for trials.
00:16:48.780 There are numerous aspects I wish to discuss, but time does not permit.
00:16:55.680 If you have more questions about Elixir or Phoenix, please feel free to approach me.
00:17:03.300 I am active on Twitter and looking to stream more on Twitch.
00:17:11.220 Thank you very much! Are there any questions? No questions?
00:17:17.600 Thank you, Aaron, for this overview of Phoenix and Elixir.