Refactoring
Prepare to Tack: Steering Rails Apps Out of Technical Debt

Summarized using AI

Prepare to Tack: Steering Rails Apps Out of Technical Debt

Robby Russell • September 26, 2024 • Toronto, Canada

In his talk at Rails World 2024, Robby Russell addresses the complexities of maintaining Ruby on Rails applications that are bogged down by technical debt. Using a sailing metaphor, Russell compares the challenging task of navigating tough waters to the difficulties developers face in keeping Rails apps up-to-date and efficient. He challenges traditional notions of 'technical debt' and advocates for a mindset shift, proposing that technical debt should be viewed as an opportunity for improvement rather than merely a burden. Key points of his discussion include:

  • Common Issues: Developers often find themselves struggling with technical challenges due to time constraints and legacy practices, which lead to short-term solutions overshadowing necessary long-term improvements.
  • Reframing Technical Debt: Russell suggests treating technical debt not as a cost but as a strategic move that can drive growth and efficiency.
  • Community Insights: He highlights survey findings from over 2,700 Ruby on Rails community members, pinpointing a lack of time and priority as the main reasons for not updating applications.
  • Identity Matters: Russell emphasizes the importance of team identity in maintaining a healthy codebase. Teams should aspire to be proactive in their approach to issues, integrating continuous improvement into their identity.
  • Actionable Steps: Russell urges teams to address unreliable tests, simplify dependencies, regularly conduct code reviews, and keep a lean codebase while embracing the monolithic architecture.
  • Avoiding Solo Missions: Collaboration is key to overcoming hurdles; Russell advises against sole developers tackling large tasks without team support.
  • Long-term Improvement: Instead of bankrolling rewrites or complex solutions, he advocates for incremental improvements, regularly assessing which features are essential, and discarding those that don't add value.

In conclusion, Russell reminds attendees to visualize their goals as a team and to build habits that prioritize clarity, collaboration, and continuous integration of important practices. His call-to-action revolves around fostering a culture of ownership where steady, manageable steps lead to improved outcomes, ensuring their Rails applications are not just maintained but thrive.

Prepare to Tack: Steering Rails Apps Out of Technical Debt
Robby Russell • September 26, 2024 • Toronto, Canada

If your Rails app is drowning in a sea of compromises and quick fixes, making it difficult to update and slowing you down, it's high time to redefine "technical debt" - perhaps even time to ditch the term altogether. In his #RailsWorld talk, Planet Argon foundr and CEO Robby Russell explores the common issues facing our Rails apps, uncovering roadblocks, blind spots, and comfort zones that lead us to rationalize away the need for necessary changes. It's time to confront these issues head on and work towards a more maintainable, efficient codebase.

Find the slides for this talk here: https://maintainablerails.com/railsworld-2024-talk-resources

#technicaldebt #Rails

Thank you Shopify for sponsoring the editing and post-production of these videos. Check out insights from the Engineering team at: https://shopify.engineering/

Stay tuned: all 2024 Rails World videos will be subtitled in Japanese and Brazilian Portuguese soon thanks to our sponsor Happy Scribe, a transcription service built on Rails. https://www.happyscribe.com/

Rails World 2024

00:00:16 It was drizzling rain, just enough to start fogging my glasses when I heard the instructor shout, "Robby, it's your turn!" My turn to what? She pointed at the helm. I grabbed the wheel and tried to navigate this thing through the choppy waters with really big boats moving around us. I had just met a bunch of these classmates a couple of hours earlier in the sailing class and already, I had to be the first person to go. The wind started to pick up, and I got a little nervous. I tried to stay calm; I really did. But I could feel that nervous energy starting to build up inside me, not unlike right now. I realized that this wasn't going to be as easy as I thought.
00:01:04 I think about this a lot because it’s very similar to maintaining our Rails apps. Rails 8 sounds great, but how many people are so far behind that it's not even likely to happen anytime soon for them? So when you think about working on your existing applications, there's this sense of being thrown into the deep end and having to make choices while still learning the ropes. There's no manual, no safety nets, and you definitely don't have a sailing instructor nearby.
00:01:43 Now, I always thought learning to sail would be this relaxing experience, just drifting calmly across the serene seas. Actually, if you can do a little experiment with me, I want to ask all of you to close your eyes. Can you do that? This will only work if everyone actually closes their eyes. Imagine yourself sailing on a gentle sea, the water is like glass, and the sun is warm on your skin. There's no worries, no product backlogs, just peace, quiet, and a steady breeze.
00:02:01 And now, imagine yourself running the following command: 'bundle update --all.' You can open your eyes. Who here thinks this resonates a little too closely to home? Let me see your hands. Yes, Rails is wonderful to work with; its elegance and simplicity shine through. However, maintaining our apps can sometimes feel like we're navigating through really rough seas. Sometimes we're on our own. On my podcast, I regularly ask guests whether they use the metaphor 'technical debt' in their day-to-day work, and the responses vary wildly.
00:02:31 Some people argue that we use it far too often, while others believe we should not use it at all anymore. We often find ourselves in pedantic arguments about what Ward Cunningham actually meant when he coined the term. Personally, I worry that it's an overused term and has become a bit of a catchall bucket. It serves as a proxy we use for a variety of issues. But how do we prioritize everything when it all gets lumped under the same umbrella? What really needs to happen? What's just nice to have? Do we only tackle the essentials? What’s essential? Or can we make room for things that might boost morale or enhance our work experience?
00:03:15 And how do we decide when to let something go? If everything is technical debt, how do we know what’s truly important to address? We talk about paying down technical debt, but it sounds like a burden; it's just another cost. What if we could see it differently? Not as an expense, but as a strategic move—a way to drive growth and improve efficiency? By shifting our mindset, we can turn technical debt into a tool for opportunity, not just something we try to pay down.
00:03:55 To gain buy-in, we need to be clearer. And if we're being honest, technical debt isn't very clear. Instead, we need to frame it as an investment—something that will reduce risk, increase our capacity, and speed up our delivery. Businesses invest in growth, not just in paying off debt. My company, Planet Argon, recently surveyed the Rails community. How many people here participated? Thank you so much! We had a little over 2,700 people respond to understand what the state of the community is.
00:04:38 One of the things we're always curious about is why teams struggle to keep their apps up to date. Can you guess what the number one reason is? Do you have any guesses? Exactly: number one— not enough time. Number two— not seen as a priority. These two factors are actually tied, and third-party dependencies came in third place. Teams feel stuck in a cycle where maintenance piles up, priorities blur, and a fear of breaking things starts to take hold.
00:05:11 But I doubt that any of these teams ever decided one day, 'Hey, we want to be the kind of team that can't keep our apps up to date.' No one sets out with that plan, but it happens. Little compromises add up, shortcuts become habits, and we avoid tough choices. This is why our team's identity matters. In James Clear's book, 'Atomic Habits,' he discusses the power of identity, particularly how it drives long-term growth.
00:05:50 Quick show of hands: who has read this book? I recommend it for everyone else. The author explains that it's not just about setting goals or taking actions; it’s about becoming the kind of person or team that naturally does these things. For example, instead of just trying to fix issues as they arise, a team that identifies as one that values maintainability and efficiency will proactively seek out ways to improve their situation. It's not just something they do; it’s who they are.
00:06:44 So today, I want us to think about what kind of developers we aspire to be and what team we want to be part of. Are we a team that just reacts to issues as they pop up, or are we a team that takes pride in continuously improving things for ourselves and our code? Because our current outcomes—everything from our code quality to our test coverage and deployment speeds—are direct results of all of our habits up until this point. If we want different results, we need different habits. Habits aren't big, one-time efforts; they're small actions repeated until they become second nature.
00:07:15 As James Clear states, "Your outcomes are a lagging measure of your habits." So let's think about the habits that are driving our current outcomes. In sailing, tacking is a significant maneuver when the wind is against you. You have to turn the boat through the wind to change direction. This isn't something you do all the time, but it takes planning, timing, and everyone in the crew working together. It's a maneuver you need to practice regularly.
00:08:03 Everyone on board needs to understand their role and be ready to execute when the time comes. Habits help with small, continuous improvements, but when the wind isn’t working in our favor, we must be prepared for bigger moves. In Rails apps, tacking could look like deciding to refactor a major piece of code or switching our test suite to a different version. Maybe we're going to remove Active Record and tackle some of that tech head-on.
00:08:44 These are not small tweaks; they are deliberate, strategic moves. We don’t tack every day; we tack when the small adjustments just can't keep us on course anymore. So let's examine some common technical challenges that teams are facing with their Rails apps, along with a few that you might not expect. I'm pulling these from surveys we've conducted, teams we've interviewed, and client engagements we’re a part of.
00:09:08 Some of these might require bold action, while others might need new or better habits. If you don’t agree with everything, that’s fine; that’s what developers do best. You know your team and your codebase best. Unreliable tests: we've all faced them. They slow us down, frustrate us, and chip away at our confidence. But sometimes, we keep them around, telling ourselves we’ll fix them one day.
00:10:00 Let’s be honest, flaky tests do more harm than good; they are not just an annoyance, they become an anchor. Tests should be the wind in our sails, propelling us forward—not holding us back. If your team lacks the skills to deal with the situation right now, that’s okay; admit it. Stop faking it. You can bring in an external consultant to help, or buy books on the subject.
00:10:39 But, admittedly, a lot of books discuss theory without addressing the tangled mess many teams already face. How do you start adding improvements for that? It's complicated— not everybody is born with that skill set. So either make your tests reliable, or get rid of them. You're already deploying, and you must have some confidence in it. Now, we’ve all been there. You find a new Ruby gem that promises a quick fix. It’s tempting to add it immediately.
00:11:18 However, many gems come with their own dependencies and functionality that you're never going to use. They can slow down your app and make it harder to maintain in the long run. So ask yourself: is this gem adding more weight than value? Could we write that small piece of functionality ourselves? Be careful with gems; they may seem like gifts from above, but they can also hold us back at times.
00:11:58 Choose what truly helps you move fast while keeping a lean code base. I'm going to highlight a couple of types of gems that many teams struggle with: Active Admin and Refinery. They’re great for getting started, and I don’t fault you for using them, but they seem to get deprecated every few major Rails versions, and teams get stuck because they aren't sure what to migrate to next.
00:12:37 Here’s my bold tack: rip them out! Stop waiting! Embrace some boring Rails code. You can do it! Rails is really great at handling CRUD, and you don't need to depend on anything. For extra credit, look into using and writing your own generators. Check out a great book by Garrett Dimond called 'Frictionless Generators'. I also want you to consider all of the unused data being stored in your database, like older data that you're no longer using.
00:13:21 Old database columns that you're no longer touching, assets residing in your S3 buckets that you don’t use anymore. Holding onto unnecessary data not only slows down your app's performance over time; it also increases the complexity of making bold moves like migrating between libraries or tools. Not to mention that it could expose you to security risks and privacy concerns with client data that you promised to delete, but it’s still there.
00:14:01 So, what can we do to delete? What can we eliminate in our systems? Naming things in programming can be hard because it means challenging old decisions and clearing up confusion that has built up over time. A good habit is to regularly ask if the names in your code still make sense. Are they clear to everyone? Are they helping, or hindering? A team that gets comfortable renaming values prioritizes clarity over convenience.
00:14:40 When we embrace clarity, we create a codebase that’s easier to understand, maintain, and onboard new people. If you're curious about this, here’s another book recommendation by Eric Evans. Too often, teams see a new feature stack as the perfect opportunity to try out that new JavaScript framework they’ve been wanting to play with. Instead of replacing old code, they just add the new framework in, piling on top and creating a tangled mess.
00:15:18 Fast forward a few years, and a lot of teams now have three, four frameworks mixed up in their systems. The front end becomes an absolute nightmare to maintain, and there’s no clear path out of that situation. Here’s my advice: I challenge you to experiment with those new frameworks on your existing stable features first. Try doing so because you have good test coverage; see what really works there first.
00:16:00 If it succeeds, great! You're already on your way to migrating to the new tool that excites you. If not, no harm done; you can revert back to what you're comfortable with. Remember, if you're too afraid to make those changes today, do you honestly think it’s going to be easier tomorrow or a year from now? Probably not.
00:16:49 Small teams love how fast Rails allows them to build an API, but a number of years ago, there was this whole wave where a lot of teams opted to build out the front end in a different tool stack and repository. Here’s the problem: many small teams did this, and every change required coordination in multiple repositories to get things pushed out. This slowed everything down.
00:17:38 In fact, over the last six years, the Rails community has been increasingly re-embracing the power of the monolith. We discussed this in the keynote earlier, and more developers are realizing that keeping everything under one roof makes things simpler, with less overhead and fewer headaches for smaller teams. A particular focus on one cohesive system helps even large companies simplify their processes as much as possible.
00:18:30 Every team has its fair share of quick fixes, one-off rig tasks, and temporary patches that solve some immediate problem, but they often linger in your codebase, cluttering things up and becoming dead weight. Instead of just cleaning up later sometime in the future, let’s build a better habit whenever we're writing code that we know shouldn’t be there after it’s run. Clearly label it as temporary, mark it for removal, and set a reminder.
00:19:15 Make it clear it has an expiration date. This way, we can stay truly aware of what's important to keep around in our codebase. Let's take a quick moment to recap, as I know I'm covering a lot quickly here. Get your tests in order, reduce dependencies, rename things more often, experiment on existing features first, embrace your monolith, and remove temporary code.
00:20:04 I want you to think a little bit about which of these types of actions you might be able to start implementing when you get back to your office, wherever that might be. And don’t worry; these slides will be available later, so if you don't get a photo, that’s okay.
00:20:46 Switching gears, let's talk about the challenges that teams face, because how we communicate, collaborate, and approach our work can either make or break our efforts to steer things into smoother waters. One challenge many teams face is retaining legacy practices simply because that's how it’s always been done.
00:21:10 However, as our teams and our apps evolve, so too must the way we work as teams and how our organizations process things. These outdated methods can become roadblocks rather than assets, unintentionally slowing our progress. Don’t be afraid to question them. When we've been told 'not right now' too many times while asking for time to deal with tech debt, it’s easy to stop asking.
00:21:45 Here's my bold tack: stop asking for time altogether. Instead, bake the work into what needs to happen by framing it around the organizational goals. How does improving the code lead to faster releases, better customer experiences, and fewer bugs? Make that connection clear. Propose the work as essential, not optional. This is your job; these are the things you need to take care of.
00:22:33 We often come into client engagements and hear the same story over and over: one person goes off on a solo mission to tackle a big problem. This could be a significant upgrade, refactor, or migration, but it often leads to false starts. We’ve all seen those GitHub branches lingering for months, leaving no one sure of where things left off or how to pick them back up. Worse yet, that person may get burnt out or find a new job, and that lost knowledge is gone.
00:23:22 This doesn’t help your team, app, or organization. Therefore, the bold tack I suggest is to avoid heroic solo missions. One framework or not, make collaboration a habit. Pair up on the big tasks, share knowledge openly, and don’t let progress depend on just one person. Are we the kind of team that tackles problems together, or do we rely on lone heroes? Let’s build a culture where no one sails alone.
00:24:01 Many teams fantasize about a clean slate—a complete rewrite of their app, Rails new, or some other tech stack—but it feels like the easy way out. Rarely is it actually easy. Here's my bold tack: commit to never rewriting your app. Treat it like it's the last application you're ever going to work on for the rest of your life. Instead of starting over, focus on making it better every day. Refactor what you have and improve it piece by piece.
00:24:51 Rewrites often fail because we underestimate complexity and overestimate benefits. So make the decision now: no resets—just continuous improvements. Teams often make decisions with the assumption that a bigger team will develop in the future, which leads to unnecessary complexity. We tend to assume growth is inevitable because businesses are supposed to grow, but what happens when our development team remains the same size or even shrinks?
00:25:39 Instead of overengineering, focus on what your current team needs. Simplify things wherever possible; do this again and again because a lean, efficient codebase is going to be easier for you to maintain, no matter the team size. As developers, we can get frustrated with legacy code and changing priorities, conflicting priorities, and endless backlogs. It often feels like nobody is listening, but blaming the business creates a divide.
00:26:32 It halts progress. What if we changed the narrative? We need to realize that we're on the same team. How can we align our work with their goals and see them as our goals, moving forward together? While it might seem obvious—and I'm guilty of this myself—we need to shine more light on our small victories. Many teams feel stagnant, not because they aren't making progress, but because they're not celebrating it.
00:27:06 Recognizing these small wins keeps momentum going and reminds us of the progress we're making every day. Additionally, many projects get bogged down with low-value features. Teams are often hesitant to remove things or even propose them; they don’t feel they have time for that. Yet, little value features slow our apps and our overall progress down.
00:27:44 So, what can you do? Start by adding feature monitoring around features that you suspect aren't pulling their weight. See what's actually being used and how frequently. Then, be bold! Help your product owners cut the clutter. Ask whether we really need something or if we can simplify or eliminate it. Remember, the easiest feature to maintain is one that no longer exists.
00:28:29 Many teams wait too long for consensus or permission; they drift into deadlock where progress stalls, momentum fades, and nothing moves forward. Instead, build good habits, test small experiments without needing everyone’s approval, see what happens, and react accordingly. This keeps you agile and allows for continuous movement—and these habits prepare you for those big, bold tactics.
00:29:13 When the stakes are high, you’ll be ready because you’ve built trust in a strong, collaborative culture. So ask yourselves: Are we stuck in deadlock, or are we building habits to steer through any challenge? And I know we’ve covered a lot, so let’s bring it all together with some key actions for your team.
00:29:54 Here are a few bold moves and better habits to consider: I want you to question old practices, stop waiting for permission, avoid solo missions, commit to never rewriting your app—treat it as the last one you’ll ever work on—optimize for your current team, celebrate the small wins, and regularly ask, "Can this be removed? Do we still need this?" These are tangible actions you can start right now.
00:30:33 I’m giving you permission to start implementing them. See, Robby said so! I know we could spend all afternoon discussing many challenges and the excuses we encounter, but I’m curious how many of you are experiencing at least two of these issues right now? Can I see a show of hands? Raise them up and take a look around—make eye contact with the stranger next to you and smile.
00:31:18 Say, 'I’m on board! We’re in this together.' Let me see those hands again. Look at these people with problems. If you see someone who didn’t raise their hand, go ask them what their secret sauce is. All right, as we wrap up, I’m going to leave you with a bit of homework. I want you to take these questions back to your team. This isn’t just a thought exercise; this is a call to action.
00:31:57 Can we do it? I want you to start a conversation with your team about who you are and who you seek to become. Confront the obstacles, challenge the excuses, and set a course towards smoother waters. Step one: Think about the team you aspire to be, not just in name, but in action. What daily habits would they practice? Try thinking about it from a third-party perspective—this helps tremendously.
00:32:35 Would they make time for more consistent code reviews? Would they actively try to reduce dependencies? Would they pair up on major refactorings? Would they prioritize better documentation that you're currently producing? Would they delete things that should have been removed years ago? Define your ideal, and start building towards becoming that team.
00:33:13 Two: Stop seeing challenges as burdens and reframe them as opportunities. If managing microservices is overwhelming, see it as a chance to reduce overhead and unify your approach. If your test suite is unreliable, view it as an opportunity to redefine quality and stability for your team. Ask yourselves how that ideal team would approach these issues, and how they would turn pain points into progress.
00:33:53 Great teams know when to make bold moves. Look at where your Rails app is slowing you down. Do you need to refactor your service objects? Do you need to migrate to that new modern JavaScript that promises everything? Do you need to rethink your deployment pipeline? Reflect on what bold moves align with your vision and which changes will have the most impact, and consider how that ideal team would approach these bold tasks.
00:34:28 Think about it from a third-party perspective—this has proven to help significantly. Come back to the 'Atomic Habits' mindset: once you've identified your challenges, bold moves, and committed to them, don't just talk about it; make it part of your culture. This is who we are, not just something we do. Set clear goals.
00:35:00 Hold each other accountable—hold yourself accountable—and build momentum with every step. Change happens when everyone believes in the course of action and acts on it daily. Steering our Rails apps into a more maintainable future isn’t a one-time move; it’s going to be a lifelong journey.
00:35:49 Remember, this is the last app you’ll ever work on! It requires making smart choices, embracing change, and focusing on what truly matters. I believe that if you adopt the right habits, discard the bad ones, make bold moves, and develop the right mindset, you can navigate even the stormiest of waters.
00:36:27 So let's set a course for progress and make this journey one we can look back on with pride. And let’s start sailing! Thank you for joining me today.
Explore all talks recorded at Rails World 2024
+13