Talks
Escape Your Framework
Summarized using AI

Escape Your Framework

by Julian Doherty

In this presentation, Julian Doherty, a lead developer at Envato with over 20 years of experience in software development, discusses the challenges of relying too heavily on frameworks like Ruby on Rails and proposes methods for escaping those constraints to improve code flexibility and maintainability.

Key points of the presentation include:

- Introduction: Julian begins by sharing his background, emphasizing his experience with Ruby and functional programming paradigms. He aims to explore how frameworks can be beneficial but also limiting.

- Case Study: He presents a scenario involving a famous Hollywood movie star who sought his advice on developing a website called 'ask overflow'. This website aimed to allow users to ask questions and earn points based on their interaction with the site's content.

- Initial Challenges: The star's initial implementation was quick and dirty, with hard-coded values and poor error handling, making testing and debugging difficult. Julian emphasizes the need to 'escape the framework' and promotes reusable components.

- Refactoring Process: To improve the code structure, he demonstrated how to pull unnecessary logic out of the controllers into dedicated classes. This included creating a CreditImporter class to handle data imports cleanly.

- Incorporating Functional Paradigms: Julian introduced a gem called 'values' for creating immutable objects that simplify error handling. He also developed an ImportSummary class to track the outcomes of import operations while maintaining overall process integrity.

- Effective Data Handling: He discussed the necessity of abstracting away logic for parsing data and managing network calls to prevent failures from impacting successful operations.

- Designing for Clarity: He highlighted the importance of structuring code to isolate pure functional logic from imperative operations to ensure easier testing and management.

- Conclusion and Takeaways: Julian concluded by summarizing how these improvements have created a flexible, maintainable codebase that embraces functional programming principles while remaining pragmatic for real-world applications. He encouraged developers to continue learning how to escape the constraints imposed by their frameworks, promoting a balance between functional purity and practical coding needs.

00:00:01.190 Our next speaker is Julian. He mentioned that he's not very exciting as a person and that he doesn't have many things to say. He has children, and I can totally empathize with that—it’s like, children go to bed, and I just watch TV. That’s pretty much my life. We are going to a party tonight, but I have to pick up the kids from school at 5:30. So, Julian isn't going to a party right now, but he is a lead developer.
00:00:14.040 He has been a developer for over 20 years and has been working with Ruby for the last 13 years. Originally from Wellington, New Zealand, he now calls Melbourne home. Currently, he works at Envato and has spent time at some of the biggest Rails shops in Australia. In addition to his work, he runs the Elixir Melbourne meetup group. He tries to spend as much time as possible inflicting functional programming paradigms on the codebases he works in.
00:00:32.279 Julian is going to give a talk about escaping your framework, which is a pain we all feel at one time or another. Please join me in welcoming Julian!
00:01:26.439 Okay, let's get started. As Mel said, I am Julian Doherty, and I am a lead developer at Envato. You can find me on Twitter as @madlip or at juliandohety.com. At Envato, we are hiring; we have a few roles going, so if you’re interested, go to careers.envato.com or ask Brenda over in the corner. By the way, if nothing else, do check out the cool swag we have.
00:01:46.580 Also, as Mel mentioned, I run the Elixir Melbourne meetup, where we discuss some of the topics I’ll touch on in this talk but not in as much detail. The topic I've chosen today came about when I received a request from a famous Hollywood movie star who was developing their own site for a cool startup idea. They contacted me for feedback regarding how they were doing with their code.
00:02:18.980 I can't say who it is, but I can talk about the project. They sent me a mockup of what the site would look like, something called 'ask overflow.' It’s a site where you can ask questions about a particular star and all the movies they've been in, and you can earn points for answering those questions.
00:02:30.769 To start this process, you'll need to get data from somewhere. You don't want to type everything in manually. There's a site called The Movie Database (TMDb) which is community-sourced and has most of the same data as IMDb. It also has a public API you can use. When querying the API, for example, querying the person ID 31 for the actor we're discussing, it will return information about them, such as 'Forrest Gump' being their most popular movie.
00:03:14.380 The star mentioned was quite eager; they had read some articles and completed a tutorial on setting up a Rails blog in 15 minutes. They were ready to dive into coding. The first task was to import this data, so they got to work. However, the code they put together was quick and dirty.
00:03:50.350 There's quite a bit going on in the code, and I won't read through every detail, but there were several issues present. For instance, they hard-coded an API key into a Rails controller without error handling, which made it difficult to test and debug. I pointed out those problems and emphasized that while it was a good start, we needed to escape the framework. The coupling to Rails made it hard to reuse components elsewhere, so my goal was to extract what could be reused.
00:06:04.310 First, we need to pull it out of the controller since all the logic was stuck there. This is straightforward; we can grab the API key and put it in a Rails configuration, ideally pulling that from the environment.
00:06:13.310 Then, we created a CreditImporter class to handle the import process. This class uses the person ID and URL we obtained and calls its import method. This method will inform how many records were inserted or updated and will also catch any errors that occur, providing feedback to the user. This approach resulted in a cleaner code structure.
00:06:37.910 Even after those changes, we noticed there was still a lot going on in the code. While it functioned properly, it was still hard to test, lacking error handling. We needed to escape further from the ways we were previously writing this code.
00:07:11.629 Next, I introduced a gem called 'values' that allows you to create immutable objects. For instance, if you create a Point class with X and Y coordinates, it makes it easier to reason about code without the complexity of mutable state. With this gem, we can handle errors more efficiently by looking at our core values, defining success and failure wrappers that streamline this process. This greatly simplifies our error handling logic.
00:08:25.210 Another improvement we made was to create an ImportSummary class to track information like how many records were inserted or updated, as well as handle validation errors without disrupting the overall process. We could then return a summary of what happened during the import.
00:09:03.430 As we iterate through the results, we can also abstract away some logic to handle data parsing and network calls. If an error occurs in fetching credits or in JSON parsing, we wrap that up so the failure does not directly affect the successful operations.
00:09:49.250 In this improved flow, every operation checks its success or failure status. By using functional paradigms such as currying, we can elegantly manage this data structure, ensuring our code remains clean without falling into callback hell.
00:10:29.310 We've arrived at a method where we effectively encapsulate our functional logic while ensuring smooth continuity between different stages in the flow of operations. Each method clearly outlines its function while maintaining an easy-to-read structure.
00:11:17.920 As we continued this refactor, the goal was to remove as many side effects as we could by creating a framework where data can be processed in a pure functional style. By introducing more functional techniques, we now have a core business logic that doesn't interfere with the imperative operations of our application. In practical terms, we are separating data mutation from the logic that dictates when and what should be mutated.
00:12:23.190 The idea is to introduce an imperative shell that performs these changes while leaving the functional core to handle pure operations without side effects. This allows for easier testing and isolation of concerns. By wrapping our database interactions in this patient, we're creating a coherent way to record operations while still managing to keep things efficient.
00:13:19.750 The concept involves creating a series of abstractions that can be executed sequentially. This will take the form of an abstract syntax tree—a structure that delineates how functions are chained without having the operational tails of their implementation interfere with one another.
00:14:01.645 This gives us the flexibility to express complex actions and chain their executions based on what result or effect we want to achieve while maintaining clear separation from how those effects manifest externally.
00:14:38.950 Finally, the structure will also allow us to implement a cleaner and more expressive API, almost resembling native Ruby syntax, which is user-friendly and encourages best coding practices. With all these adjustments, the idea was to make the code not just functional—that’s essential—but also maintainable and flexible in the framework of the application.
00:15:24.690 We've effectively built a mini programming language to reflect our design principles while keeping the core logic isolated from external actions. By implementing this approach, we gain clarity and depth without compromising usability. Everything retains its expected behaviors, allowing developers to manage resources appropriately.
00:16:07.300 Throughout this transformation, we have focused on ensuring that our design aligns with the underlying principles of functional programming while also maintaining a clear and manageable structure. It’s about bridging the gap between functional purity and real-world applicability, keeping our approach grounded in pragmatism and the realities of software development. This wraps up my presentation. Thank you for your time, and I hope we all advance in learning how to escape the constraints of our frameworks.
Explore all talks recorded at RubyConf AU 2020
+15