It deserved its own tome: Layered Design and the Extended Rails Way

Cover for It deserved its own tome: Layered Design and the Extended Rails Way

Topics

Share this post on


Translations

If you’re interested in translating or adapting this post, please contact us first.

In this interview with Vladimir Dementyev, we discuss his new book “Layered Design for Ruby on Rails Applications”. The Evil Martians’ Principal Backend Engineer goes deep on a number of topics: the contents of his book, the importance of maintainability, the Extended Rails Way, sharing his experience-driven methodology for building web apps with Rails, the future of Rails. Plus, comparing other frameworks and failed attempts to recruit his nephew into the world of Rails.

Travis: Can you tell me about the origins of this project?

Vladimir: The publisher (Packt) approached me and asked: hey, some of your blog posts have been on our radar, maybe you’d like to write a book with us. And I thought, why not? So that’s how it started. Okay, that’s the short version. It actually took about a month for me to make that decision, and then do the analysis and whatever boring things one must do before signing a contract.

T: So why did you decide to go with this topic, how did you get there? You were telling me earlier that you had some other ideas, too, right?

V: Yeah, I had some book ideas but never took them seriously, and none of them sounded like the one proposed by the publisher. The original topic was kind of broader. It was something like “Rails Design Patterns”, just some stuff about Rails. But when I started working on the outline, I kind of realized that I have something to say about Rails itself—how to use it to write applications the way I have done… for nearly the last 10 years, actually.

This book is my perception of how to build applications with Rails with a focus on maintainability—I’ve also already had some previous work about this topic—blog posts, materials for internal courses, and some conference talks. I would say I formed this book by reflecting on the past. So, it’s kind of a reflection on the experience I’ve had since I started using Rails and Ruby for real.

T: I immediately took the book as a kind of ideological text. I mean, when I read about your idea of the “Extended Rails Way”, it appeared we’re dealing with something that’s making a larger point, rather than just some guide book. It seemed like you were trying to put out some new ideas about taking the framework forward?

V: Yeah! Yes, that’s what I hope the readers will get, too. Because I didn’t want to write a book on “Rails Design Patterns”—what does it even mean? When I see the phrase, “Rails Design Patterns”, the picture in my mind is that, okay, this is gonna be a book where you’re gonna have a list of patterns, you know, software design patterns, and examples of using them with Rails with no additional value. Say, here is a chapter on the Adapter pattern, this one is about Form Object, oh, and one more about Value Objects and so on. That’s what I think of when I see “Rails Design Patterns”, like a handbook. That can be valuable, but actually, patterns are just tools—and they’re helpful—but they don’t solve the bigger problem of maintainable software or address the kind of thinking around this topic. Then, the question becomes—if not that book, then what do we need?

I found my answer within Ruby and Rails themselves. Ruby is about developer happiness—and Rails is also about developer happiness, plus productivity. To actually craft something good, something robust and easy to work with—something that’s even a pleasure to work with—we must embrace the ideas of Ruby and Rails. And that involves so much more than just using tools and abstract design patterns.

Luckily, I’ve worked at a consultancy for most of my professional career, so I see dozens of code bases every year. And Rails codebases differ from each other a lot. This actually highlights the fact that the Rails Way is not suitable for everyone. Whenever an application grows, developers tend to invent their own ways of dealing with things. And I rarely see good examples of that—admittedly, a bit of professional bias, for sure. Usually, what I see are monoliths with significant maintainability issues. My experience in solving issues like that formed the basis of the book.

Incidentally, I think really many tech books are actually just books of recipes. You have this scenario, and here’s an example of how to handle it. That’s helpful, but I wanted something different. I wanted to share the methodology, not the actual recipes, so you can just come up with the recipe yourself. This idea finally shaped the book and everything I put into it. This book is actually about finding the “Extended Rails Way”, not about what it is—because it’s not set in stone, you must feel and find it yourself.

T: So, I’m kind of curious where you got the inspiration for this Extended Rails Way idea?

V: If I had started writing something like this five years ago that book would probably say, okay, Rails is good, but there are a lot of controversial parts, so let’s not use it. Let’s just build an entirely new stack on top of Rails to not rely on Rails anymore! I thought, if we really want to grow, we need to go off Rails and use some ideas from other libraries, or whatever. But over the years, looking at many codebases, I realized that sometimes this works, but in most cases, it actually makes the codebase to be a less livable place.

I really like this analogy of describing a codebase as a place to live. I heard that from Sarah Mei. I once saw her give a talk live, and it was about the concept of livable code. And she compared it to a livable place for humans. And I realized, yeah, that’s a really good concept.

And to have a livable codebase, you just need to follow, I would say some house rules, or conventions, right? And then build on top of that. In the case of Rails, the fundamental house rules are defined by the framework itself. This is the Rails Way. So, I thought that we don’t need to contradict the Rails Way and try to build something different while relying on Rails’ foundation. We just need to “extend” the Rails Way to better match our use cases.

Rails gives the essentials, which are useful for most applications, but every application is still unique. And we need just to think about what we need to add on top of what Rails provides—but still stay in line with the Rails way. I realized that I was following this idea—unintentionally—for years, both with the applications I worked on, and with the libraries I wrote for Rails.

T: A little deeper on the origins of this, could you maybe trace back the Extended Rails idea to a particular library or project?

V: I think one of the first gems that I built following this idea was Action Policy. One of the reasons I did this is that I had to give a talk about authorization—that was my first RailsConf talk. And that’s why the title of the gem is actually “Action Policy”, because I tried to follow Rails naming conventions. My idea was to imagine that Rails had an authorization component built into the framework. And that would be Action Policy—not anything else. I’ve been using it in many projects, it really clicks with the rest of the Rails ecosystem. It looks like Rails. Well, it does to me, at least.

Later, I applied the same thinking to other abstractions. Many of them were eventually extracted from commercial projects into gems.

If you want to make something look like it was built by the Rails team—do that. This would make it look natural in the application and easier to work with for other developers. For the same reason I now argue in favor of following the Rails Way for as long as possible instead of backing the idea of mixing alternative ideas into Rails.

So, why did I change my mind?

I think a couple of times I’ve worked with pretty large codebases that tried to closely follow the Rails Way, you know, to be like Basecamp (although we don’t have a lot of information about the actual design of the Basecamp Rails application). So, when I worked on a large project that tried to follow the Rails Way, I realized why people are doing this: they want to stick to the framework defaults as much as possible to make it easy to onboard new engineers, to keep their productivity high, and to receive goodies as they upgrade. As the framework evolves, they want to evolve along with the framework, kind of “for free”, right? Because if you build custom components yourself, at some point, you may get stuck due to incompatibilities and lose the benefits of the framework evolving.

So, I’ve kind of seen it all: projects following the Rails Way, and projects embracing non-Rails ideas. And, you know, I’ve found it, more, let’s say, convenient to work with the former projects. And that’s another reason I decided, okay, it’s a good idea to stick to the framework, conventions and defaults or whatever, for as long as you can.

This meshes well with one of the fundamental principles of software design—the principle of least surprise: if you want to get something that’s easier to use for new developers, or for other developers, then make it look familiar to them. That is, reuse interfaces, ideas, concepts, whatever—reuse the things that can make the codebase more approachable. And that’s actually part of the Extended Rails Way. So, just reusing conventional Rails interfaces, even building blocks, to build something on top of it. This is the first ingredient of the “Extended Rails” recipe—yeah, now you see that the book is actually a book with a single recipe.

T: Speaking of the ingredients, let’s talk about the structure of the book a little bit. So you divided it into three sections. Could you walk through what those three sections are about, or how you divided them like that?

V: Yeah, so the first part is dedicated to Rails itself. So when I started writing a book, I was thinking about how to start the book. As I said, I didn’t want to have a book of pattern one, pattern two, and so on. I needed some introduction–why are we talking about this, right?

And I concluded that to come to the Extended Rails Way, we first need to learn about the actual Rails Way, right? Rails itself. I realized that one needs to understand that a web application—like in general, not only Rails applications—is a specific kind of software, and that affects the internal design and the architecture decisions we make. They should reflect the nature of the application. Because there are different kinds of software, right? There are graphical user interface (GUI) applications, desktop applications, games, and whatever, they’re very different from web applications as far as what Rails is built for. And we need to understand this difference. At least, this helps me see how the data flows in the application, and why it’s natural to have layers, like processing layers, or units of work, such as web requests.

So, we start the book with the basic stuff. We reveal the major components of Rails and how they’re built, and why they’re built this way, which patterns they use—what actually makes the Rails Way from the technical point of view. And that’s the first part—dedicated to the different parts of Rails—so, the HTTP layer, and then we talk about databases and the model layer, and then we talk about infrastructure stuff, like active storage, and so on.

One of my favorite chapters from this part is “Rails anti-patterns?”. There’s a question mark at the end of the chapter title, which is intentional, of course, because every anti-pattern actually can be seen as a huge productivity boost when you first start working with an application. Actually, that’s why I don’t like the term “anti-pattern”; it sounds very negative, but these are just patterns that are helpful in the beginning, but may hurt in the long term. So that’s what I tried to express with the question mark in the title.

But anyway, that’s an important chapter, because it kind of leads us to the problem of the Rails Way: if you continue focusing on building features around your productivity, but not on the software design, you’ll eventually end up with highly coupled, entangled, monolithic code, which is hard to scale, hard to work with, hard to actually introduce new features in the future—and that’s why we need to go beyond what Rails gives us, and keep up a good level of maintainability. And that’s what we start doing in the next parts of the book.

At the end of the first part, I introduce the layered architecture concept and how it can help us come up with better abstractions for our Rails applications. And this should all prepare the reader for the actual kind of, “refactoring” part of the book, the second and third parts.

That’s probably an important point: this book focuses on refactoring an existing application, not writing Rails applications from scratch.

T: So, that last bit kind of raises a question for me… how should the book be read?

V: That’s the other thing, the structure, the book assumes that the reader, at least for the first time, reads it as a sequence. I mean, you cannot just go straight to chapter 10 just because you’re interested in this particular problem. You won’t get the idea why we’re doing the code extraction or abstraction, introduction, direction, as it’s presented in the book. So, if you want to get the most from it, the book should be read starting from page one and then onward, page by page.

T: Yeah, I guess it’s because it’s not strictly a recipe book, as you said.

V: Yeah, yes, exactly. Or, as I mentioned earlier, you might consider it a single recipe. And you can’t really start cooking something in reverse order, right?

T: Well, if you do pivot to culinary texts, I’m definitely looking forward to that “reverse cookbook”. So, not directly related to your new book, but where do you think Rails will be in the next two to three years?

V: Hmm. Well, I think two or three years is not a lot of time for a framework with almost twenty years of history.

T: Feel free to go further into the timeline.

V: Well, there is an important thing going on right now; some are calling it a Rails Renaissance. I mean the modern way of building full-stack Rails applications, Hotwire, and the likes of that. I see many projects migrate—or try to migrate—their frontend stack partially or fully to what Rails offers. I think the trend will increase with the release of Rails 7.1—a bunch of minor but very useful things in there—and new Hotwire things, such as Strada for easier mobile development with Rails—yeah, it may sound strange, but that’s what it is.

So, I expect this trend to continue growing, and we’ll have more applications following these Rails ideas. That’s probably what I’d expect in the next couple of years, at least. Right now the portion of Rails apps running this new stack in the wild is small, maybe, 5–10%. And I can see it doubling in the next year or two, and, eventually, powering half of all Rails applications.

T: So, let’s say that some little kid comes to you and says “I wanna make web applications”. For some reason this happens—like hypothetically. Do you tell them, “hey buddy, oh yeah, Ruby and Rails, all the way!” Or, what’s the path? What would you say to someone getting into this field right now?

Actually, one of my nephews asked me a lot about software development over the last couple of years. He’s 16 now, and he’s starting his adult life going to college, and studying computer science at college this year. But even though I really advertised Ruby and Rails to him, he hasn’t really given it a chance, I mean, he didn’t take me seriously! So, I already tried and failed. I guess I’m probably a bad salesperson. But in my defense, he said he didn’t want to deal with the web at all, so, probably that’s why.

T: Let’s peek a little farther out for fun. What about JavaScript frameworks?

V: I haven’t tried the newest ones, like Remix, for example, but I think, some day they will be able to provide about the same level of happiness and productivity as Rails does today. But they’re all so young and immature, and I think it’s harder to start with something that’s new and changing fast. What’s good about Rails is that it’s a stable framework, and it just works, and you can trust it.

T: Python?

V: I tried Python and Django, and I wouldn’t recommend it, ha, sorry! It may be a good tool to achieve your goals, but as far as the developer experience… It’s just not fun, again—sorry.

T: Anything else?

I haven’t tried Laravel myself, but I’m thinking about it. Maybe I’ll just rewrite this book with Laravel! Not a bad idea. There are a lot of similarities and a lot of ideas about how we build Rails applications that could be applied to PHP and Laravel as well. I see that they’re doing a lot of stuff to make it easy to work with and build things faster. I would consider PHP as well, it was a nice language back in the day, I used it, and now it’s even better.

T: This is your first book, right?

V: Yeah.

T: So, if this publisher had never approached you, had you been thinking already about writing a book?

V: Yeah, that’s a good question. Well, I would never have done this on my own by self-publishing. I’ve been thinking of other ideas, and I’ll probably approach some publishers at some point.

T: Will you write another book, then?

V: Right now is a good time to write a book on Ruby. It’s starting to get more traction, to have more books in Ruby. And now we have Rails Foundation as well, focusing on education and marketing, and so on. I had some ideas on writing something about tests and tests profiling or maintainable tests based on my TestProf project. And also, have another idea of a book on Action Cable, AnyCable and real-time Rails in general.

T: Alright, so one more question: what is your overall hope for the book?

V: I want the reader to feel, to kind of get what drives my decision making. I’ve helped develop many applications and I can say they are still all alive. Well, most of them, okay, maybe not all. And that’s not a bad sign! So maybe that’s a reason to consider my advice! But yeah, I want readers to think about code not just as some structures and patterns combined together—it’s something bigger. The code we write is an expression of an idea that should be present. That’s why we need abstractions. If we don’t have abstractions, and just write code to “make something”, then we do no favors to anyone working with this code later or extending it or whatever.

So yeah, basically maintainability. I want the reader to make a shift from just making high-quality code, following metrics, clean code or whatever, and start thinking about higher level things related to the code, the abstract level of the system, to think in abstractions. Beautiful abstractions help you to stay alive and stay happy as a developer.

Thanks for reading! Be sure to check out the full book, Layered Design for Ruby on Rails Applications.

At Evil Martians, we transform growth-stage startups into unicorns, build developer tools, and create open source products. If you’re ready to engage warp drive, give us a shout!

Join our email newsletter

Get all the new posts delivered directly to your inbox. Unsubscribe anytime.

In the same orbit

How can we help you?

Martians at a glance
17
years in business

We transform growth-stage startups into unicorns, build developer tools, and create open source products.

If you prefer email, write to us at surrender@evilmartians.com