Domain Driven Design

Summarized using AI

Trailblazer

Nick Sutterer • March 11, 2015 • Wrocław, Poland

The video titled "Trailblazer," presented by Nick Sutterer at the wroc_love.rb 2015 conference, primarily discusses the challenges associated with using Rails for complex application development and introduces Trailblazer as a solution for managing complexity in Ruby on Rails applications.

Main Topic

  • Overview of benefits and architectural improvements offered by Trailblazer compared to traditional Rails MVC applications.

Key Points Discussed

  • Struggles with Rails: Sutterer explains the fundamental issue with Rails, where developers end up with a monolithic architecture that leads to massive and unwieldy classes containing business logic, environmental checks, and rendering code.
  • MVC Limitations:
    • Rails attempts to handle complex applications with its three layers—Model, View, and Controller—leading to cluttered code.
    • The simplicity of Rails is short-lived as complexity grows in real-world applications, making it difficult for developers to manage.
  • Proposal of Trailblazer:
    • Trailblazer introduces additional abstraction layers which allow for a more modular approach to coding, consequently minimizing the complexity found in Rails applications.
    • The core of Trailblazer’s architecture is the ‘operation’ class where developers can encapsulate business logic, validation, and authorization, separating it from the controller.
  • Cleaner Models:
    • In Trailblazer, models focus solely on data persistence, eliminating business logic and callbacks, which are instead handled in operations, allowing for clearer and more maintainable code.
  • Improved Views:
    • The views in Trailblazer can still include logic but offer flexibility and best practices with components through the cells gem for improved maintainability.
  • Operations as the Domain Layer:
    • Each operation acts as a class that defines contracts with embedded form objects, making the complexity of workflows manageable.
  • Callback Management:
    • Trailblazer allows explicit control over when callbacks execute, leading to more predictable and orderly code execution.

Important Examples and Anecdotes

  • Sutterer shares a relatable example of a project he worked on, highlighting how Trailblazer's structure allowed for better management of a community feature for a bikini company, showcasing the encapsulation of rendering logic.

Key Takeaways

  • Trailblazer is posited as an elegant alternative to Rails when scaling up applications, offering structured and maintainable code architecture.
  • The emphasis on separating responsibilities into operations encourages better coding practices.
  • The talk concludes with an encouragement for developers to foster passion and enjoyment in coding, suggesting that enthusiasm reflects in their work.

Trailblazer
Nick Sutterer • March 11, 2015 • Wrocław, Poland

wroclove.rb 2015

00:00:08.780 Please welcome a Pathan ik.
00:00:15.500 Check, check, check. Hello, good morning everyone! I was supposed to speak at 12:00, or was it 11:00? Oh, I don't know. Thanks for having me here, guys.
00:00:25.130 Last time I was here, it was a laugh. I tried to give a keynote, but that was different. I was standing over there, and I was drunk. This time, I'm here sober and only hungover, so it's going to be way better.
00:00:37.040 Actually, this talk is crowdfunded. While you guys were having lunch, these guys over here were working on my slides, so I have absolutely no idea what they put into my slides. Please give a round of applause to my slide boys!
00:00:54.110 So, I had this incredibly funny joke that I’m not Nick, but I’m Luca Luigi. It was kind of funny, but now it’s not funny anymore because I’m speaking it now instead of at 11. Apparently, Luke disappeared, so I have his slot. Yep, that's me. I'm from Italy, a wonderful country in Europe where we have pizza and a way of talking to each other.
00:01:11.710 If you have any questions about Italy or this country, feel free to hit me up later at the party, but hurry up because I might be drunk again. Speaking of drunk, yesterday was great! These are the photos I found on my camera in reverse order.
00:01:29.200 Apparently, I had to keep up before I went to bed, and that's why I didn't have lunch. We had lots of vodka after drinking which is me trying another drink. There are actually different kinds of vodka; this is Italian vodka I brought from Italy.
00:01:46.600 My camera got drunk as well, and we were having so much fun. There were so many beautiful moments yesterday, and at some point, I had this red scarf, and in every photo, I’m wearing that scarf. It's because I'm from Italy, and we're really fashionable. I should stop that now because it’s somewhat stereotypical.
00:02:11.360 I was having a good time; I don't know about you guys. Even though there were only three talks yesterday, we already partied like there were two days of conference behind us, always under the watchful eyes of NJ who told me not to get too drunk on Friday, and of course I didn’t listen…we just partied a little.
00:02:31.160 Let's get through these slides quickly because I'm respecting local traditions when we hang out at the pub. It's actually really cold here. I came from Brazil last week where I was speaking, and I didn’t bring any winter clothes. I mean, it’s not that I'm European and I know how it is in March in Europe. I just came like this, only brought my beanie.
00:02:53.150 Thanks to whoever gave me their beautiful coat. Apparently, I had another dinner because there are more photos of my camera.
00:03:09.340 So let's talk about Rails and Trailblazer. Are we discussing Lotus or Trailblazer first? Better yet, let’s talk about Rails.
00:03:19.270 In this audience, there are more people who do Rust than there were in Brazil. Wow! That's great! It's a cool programming language. I’ll start doing Rust after this talk, but Rails has a problem. I call it MV-Situs.
00:03:37.880 The problem is that Rails, still after ten years, tries to implement complex software, like the most complex software you can think of, with three abstraction layers: the view, the controller, and the model. Rails calls it MVC. What usually happens is that applications end up with a monolithic setup with huge classes—often massive models, massive controllers, and views full of code—and people don’t like this.
00:03:59.740 Yet, for some reason, people don’t take action, especially the Rails core team, who do not provide us with additional abstraction layers. When you start to introduce additional objects or abstraction layers in Rails, it’s often considered enterprise or over-engineering a simple solution.
00:04:09.190 The thing about Rails is that it’s simple, and every Rails developer will tell you that. I actually love that about Rails—it’s something I don’t want to miss out on. But Rails is only simple for a short period, like a three-minute block or a fifteen-minute block. I’ve never heard anyone say Rails is simple for structuring complex applications.
00:04:31.890 This is a result of the monolithic and extremely simplified architecture in Rails. Think of it as minimalistic; we have the Model-View-Controller setup, and quickly I’m going to walk you through the examples that lead to this architecture.
00:04:56.490 A controller in Rails usually contains a lot of different structural elements within one class. We always have filters in controllers for authentication or environment setups. All of this sits in a filter, and then we grab models. We find models and work on them, that’s partly business logic.
00:05:23.899 Then we have environmental checks to see if a user is signed in or locked in, and all of that helper logic is also dispatched from the controller. This often includes notifications like sending emails or logging activities, all stuffed in the same controller action.
00:05:35.819 And don’t forget the beautiful rendering code, which also sits in the same controller action. Excuse me, I have to drink something because one problem with alcohol is that the next day you can have a really dry mouth.
00:05:45.709 The model is my favorite part. In Rails, the model usually ends up with a lot of configuration code for forms, accessing parameters, and determining what is allowed to go into the model. So it ends up being the Rails way of configuring different aspects of your software.
00:06:02.580 My absolute favorite thing in Rails is the way callbacks are added to models. A callback is meant to extend your business logic so you can add or extend certain steps of your object lifecycle, like before validation or after saving. This is all added to the model in one central place.
00:06:33.090 But the problem arises when you add callbacks to a model and you don’t want to run a specific callback; you then have a problem. This situation results in the model getting stuffed with everything: it’s not just configuration and callbacks, but also all your business logic.
00:06:54.860 I don’t even want to discuss this further because I've seen extremely long classes in my life. As for the view, who puts logic into the view? No one here, right? Ah, one brave soul speaks up! But generally, we don’t put logic in views; it’s a no-go.
00:07:08.659 However, people do it all the time, and I don’t actually have a problem with logic in views; it’s the complexity that can ensue. Views are complex because Rails is designed to facilitate user interface-driven applications, which means a lot of logic goes into the view and should remain view-related.
00:07:23.900 What happens is that model code sits in the view. There’s so much environmental checks in the view. For example, it checks if the user is logged in or if they are an admin in order to determine what content to render.
00:07:38.550 They introduce what they call helpers to clean up our views. But a helper can often become a drastic mobile function in Ruby where people stuff even more code into completely object-oriented functions, which can also get messy.
00:07:56.660 There are configurations and decisions made in globally accessible functions in every view, and it’s a nice attempt to introduce those helpers, but it doesn’t really help to create a structured architecture in your Rails app.
00:08:06.480 So, when you think about the reason for this, to me, a classic Rails application boils down to a couple of steps that occur at every request. We start with dispatching in the controller.
00:08:15.869 We either choose to handle the HTML version of the page, the JSON version, or another format. Then we move on to authorization, where we figure out if we are authorized to run this business logic; are we allowed to render this page?
00:08:39.540 Next is validation of the incoming parameters. We must ensure that everything sent to the action is intact. Then we process the business logic, which is the code you all write.
00:08:57.040 We might access the persistence layer to save or query data, and finally, we render the result. This is the classic Rails stack for every request: the dispatch, authorization, validation, business logic, persistence, and rendering.
00:09:13.900 In Trailblazer, this setup differs slightly. If you know me well, you might find yourself in one of the illustrations in my book, which features various colorful illustrations and people I know. If you're nice to me, you might find yourself somewhere in Trailblazer.
00:09:35.310 So, in Trailblazer, we still have the same stack as Rails: we still have models, controllers, and views. However, Trailblazer brings additional abstraction layers, enhancing this diagram I’m presenting to you today.
00:09:56.170 In Trailblazer, what I call an 'operation' is the place where we put our business logic, validation, and authorization. Sometimes, rendering even gets included there. So, I’ll quickly show you some layers, but please don’t hit me about the simplicity of my examples. I’m just trying to make it as understandable as possible.
00:10:17.960 Controllers in Trailblazer serve as empty endpoints; there’s no business logic in the controller anymore. All the business logic is automatically dispatched to the operations. Instead of having decision-making and environment-coding residues in the controller, we just dispatch to an operation.
00:10:34.340 In terms of models, you can use Active Record, Data Mapper, or Lotus Model if you wish, as they give you all the freedom of the ORM we have in Rails and Ruby. But with one restriction: you don't use business code, callbacks, or validations in your models anymore.
00:10:44.640 By design, your models end up being empty, maintaining only associations and configurations like finders. You can still leverage all the great things Active Record offers, but without any additional complications from business code.
00:11:08.540 One of the beauties of Trailblazer is that by keeping models empty, they focus solely on persistence, which is a lovely feeling. The views, similar to models and controllers, allow for logic. You can use helpers or partials, and it's flexible, but it’s essential to define complexity in views.
00:11:37.230 When a view becomes overly complicated, we advise using a view component—which is what the `cells` gem brings to Trailblazer. The `cells` gem allows you to encapsulate tiny pieces of your UI into components.
00:12:00.590 For instance, in the project I’m currently working with, which is a bikini company, we have a community feature where people can comment on photos. Here, a comment can be well encapsulated within its own cell, as there are lots of variations of its logic.
00:12:16.270 An encapsulated cell allows me to manage the complexities surrounding each comment’s rendering logic, ensuring that every comment’s logic is tidy and encompassed within that cell. It’s so remarkable!
00:12:39.820 Each cell is simple; it derives what we call the `cell view model`. Each cell has a `show` method that renders the actual content. You still have views and templates, and you can mix in helpers, but the intention is to create maintainable view code.
00:12:56.670 The good news is that when you call a method in a view, like an avatar method, it isn’t called from some globally accessible helper stack but rather directly from the cell instance—allowing for better encapsulation.
00:13:38.030 In Trailblazer, the operation is what I call the domain layer. Each operation is a class responsible for maintaining a contract with an embedded form object, which has a single method you implement called `process`, where your business logic resides.
00:14:02.199 So the operation describes your forms and business logic inside of it. How it works is that everything in the operation is self-contained. When invoking an operation, you set necessary parameters, create a form object, run validations, and handle your data.
00:14:26.389 I want to make clear that separating code into operations helps manage the complexity in your Rails applications. Instead of flooding your controllers with business logic and responsibilities, this allows you to cleanly encapsulate all that in operations.
00:14:55.830 Each operation can delegate its work to other components in a way that fosters reusability. If you have repetitive workflows, you can utilize operations in tests by calling them directly or using them as factories without the need for traditional model code.
00:15:20.190 In Trailblazer, you also get better control over your callbacks. Instead of running them at unspecified times, you can explicitly set when a callback should happen. Thus, when adding or updating items, you know exactly how and when they’re running.
00:15:47.850 Another fascinating thing about Trailblazer is that it graciously allows you to manage formats other than hashes—like JSON or XML. Every operation can receive input in these formats, and since the contract knows how to deserialize the input, it handles that seamless.
00:16:08.160 To summarize, Trailblazer offers additional abstraction layers, enhances the structure of your application, and allows substantial support for object-oriented paradigms. It gets Rails developers thinking high-level rather than getting lost in the weeds of implementation details that often muddy workflows.
00:16:47.520 In a nutshell, while Rails has its strengths, Trailblazer provides a framework to manage complexity elegantly. It's about modularizing code where it makes sense—aiming for clean architecture instead of monolithic code-based structures.
00:17:10.430 That's my pitch for Trailblazer! Thanks so much for listening. I hope you all enjoyed it!
00:17:29.330 Feel free to ask me any questions! I'd love to hear your thoughts and answer your queries.
00:17:41.200 Remember, coding should be fun. If you’re passionate about what you do, it’ll always show in your work. So, let’s keep the spirit alive and thrive in the world of programming!
Explore all talks recorded at wroclove.rb 2015
+6