Talks
Impactful Refactors: Refactoring for Readability

http://www.rubyconf.org.au

We have no problems justifying a refactoring effort when it improves performance or eliminates a code smell. What if I told you there's a way your refactoring could be even more impactful? One of the most costly and time-consuming things we do is on boarding. It takes an incredible amount of effort to bring a developer up to speed on a new codebase. In this talk, we’ll see real-world readability refactors, discuss how you can apply these techniques for the benefit of your current (and future) team members, and how we can continue to program with empathy and diversity in mind.

RubyConf AU 2017

00:00:09.280 Hi, is everyone having a good time? Yeah? Awesome! I'm going to skip this slide because I just got an awesome introduction, which isn’t usual. Thank you! I work at a company in Denver called Go Spot Check, and I also mentor students how to code all around the world through a program called Block in my free time. That’s super fun when I'm not fly fishing or spending time outside.
00:00:15.440 Today, I'm going to talk about refactoring. It's a big part of what we do as developers. While technically it's not a refactor, performance optimizations are a common activity. We also refactor to implement design patterns or to improve our code in some way. But what if I told you that there is a type of refactoring that could be even more impactful and meaningful? I believe that refactoring to make code more readable is essential. Good design means more readable code. Yet, I acknowledge that there are times where readability may get overshadowed by other considerations. For example, we are currently dealing with scaling issues at Go Spot Check, and sometimes we need to do whatever it takes to keep our app running. Often, that means writing ugly, unreadable code. I argue that you should save that as a last resort. Readability should always trump performance unless absolutely necessary. Many times, performance optimizations can deteriorate readability.
00:01:01.760 This is a graph from Jeff Atwood's blog—I'm sure some of you know him. He argues that from his perspective, we spend significantly more time trying to understand code than doing anything else, so I think readability is crucial. Additionally, Nat Pryce and Steve Freeman state that developers spend far more time reading code than writing it, so that's what we should optimize for. A fantastic book to check out on this topic is 'Growing Object-Oriented Software Guided by Tests.' Michael Feathers also mentions that readability is the best default or the most important aspect of nearly all code. Today, we're going to discuss teachable versus readable code, go through some quick examples, talk about components, and then dive into the how and why of these concepts.
00:01:49.399 First, let’s start with teachable versus readable code. In previous versions of this talk, I approached this issue by almost 'dumbing down' the code or simplifying it to make it more readable for junior developers. However, my mentor and co-worker, Kim Barnes, taught me that what I was referring to was something called 'teachable code.' Teachable code should not be the norm for production. I want to clarify that making code more readable is not the same as dumbing it down. Readable code truly means better-designed code. In an article I really loved, Peter Jen explains that readable code clearly communicates its intention to the reader. On the other hand, teachable code makes the specific concept being taught as explicit as possible.
00:02:58.800 Concepts related to teachable code are important because they can significantly help junior developers in your organization level up. Kim helped me grow a lot quicker by focusing on this. However, it’s essential to ensure that you then revert to the production code after using teachable code. You don’t want teachable code in production, as it can do a disservice to your codebase and other developers on your team. I want to quickly go through two examples of readable versus teachable code. In the first example, we have readable code or code that you would have in production—it's a succinct and readable way to find our dogs. In contrast, teachable code could look more verbose, breaking it up into multiple lines and explicitly detailing how we are finding the dogs. Another example involves taking a single large class or method and breaking it down; readable production code consists of small methods that are well-named and each have their own responsibilities, while teachable code might combine all these methods into one for clarity.
00:04:30.800 It’s critical to slow down and take small steps when explaining these concepts using teachable code to juniors. I want to emphasize again that readable code is not the same as teachable code. Now we’ll look at more examples focused on readability. Firstly, let's talk about naming. There’s a popular blog discussing presenters in Rails, where it shows the creation of an instance variable called 'post.' However, post is referencing a new instance of post presenter. Why not name this instance variable 'post presenter' so that it’s immediately clear that you can call methods from the presenter class instead of the post class? Additionally, don’t fear long names. People often abbreviate or use single words when a longer name could provide much more clarity. A variable's name serves as a comment, and you should take advantage of that.
00:05:44.400 John, who’s taking pictures here, told me that writing good test descriptions is also very important. Describe what you’re testing; it makes everyone’s lives much easier. Stick to the standards—recently I came across some code in my codebase that lacked vertical spacing, which bothers me. Our team has a standard of using spaces, and our industry also follows that, so use it. I see neglecting this as laziness, which ultimately affects readability. So, my biggest piece of advice for making your code readable is to stop writing clever code. Justin Cal gave a great talk at RailsConf about this. Clever code doesn't impress; it can make others feel stupid. Reserve showing off clever code for side projects. Don’t sacrifice the readability of your code to showcase something new you learned.
00:06:28.000 Be courageous and write boring code. The goal should not be to minimize lines of code but to minimize the time needed to understand it. Next, let's discuss longer-term refactors that you can do to enhance code readability. Chad Fer states that if your services are so small that you can read them in one go, you probably don’t need a test. I may not fully agree with that because I write tests before code, but I appreciate the idea of readability. Break things into the smallest possible components to design better code, making it more readable. It will also enable you to keep context in your head rather than feeling overwhelmed by too much cognitive load. Importantly, name these objects clearly so that their responsibilities are transparent from the outset.
00:08:40.960 Though this is a Ruby conference, I want to illustrate that similar concepts apply to JavaScript. I had a recent refactor in a JavaScript service designed well from the get-go. Recently, I needed to fix a bug in a Backbone view that was over 300 lines long with very few tests; this is just the top half of the file. It took me a long time—about half a day—to understand what this view was doing. These large classes and views can be intimidating for any developer. My partner and I decided not only to fix the bug but also to refactor this class to improve its readability and design. We chose to follow a test-driven approach.
00:10:43.760 As we started pulling things out into smaller plain old JavaScript objects (POJOs), it became easier to comprehend the functionality. Initially, we thought it would be challenging to test this. Using Jasmine as our testing framework, the more we broke things apart, the simpler testing became. We began by creating a filter processor factory that returned a new instance of the type of processor needed. Subsequently, we separated each filter into its own processor class, making its processing clearer. Gradually, the 300-line Backbone view shrank, revealing its function more transparently. Not only did it become more readable, but we also discovered we could extract a base class for all processors, reducing the original Backbone view’s code significantly.
00:12:30.000 We even removed many comments since the code became self-explanatory. Remember that excessive comments often indicate that the code isn't readable, which can be a code smell. Once we understood the situation, the refactor took only a day. I initially feared it would take much longer, but I’m glad we took the time to refactor and test drive our code rather than just fixing the bug and leaving it. In this case, we ended up with fully test-driven code, a resolved bug, and a more readable and extendable codebase. We created tiny, flexible components that we could reuse later.
00:14:22.799 Examples of these refactors really reinforce that truly readable code results in good design. This concept isn't new; most of you have probably encountered it, but you rarely receive advice from someone who isn't a senior developer. Now, let's discuss how we can improve our code readability. Raising awareness about this within your team is essential. Always keep this in mind when writing code. Pair programming can be advantageous; having another set of eyes can help identify clever code that may be more complex than necessary. Additionally, taking breaks allows you to revisit your code with a fresh perspective. Code reviews should emphasize readability, whether during team reviews or pull request evaluations. Always strive to leave the code in a better state than you found it.
00:16:06.999 It's easy to fix a bug and move on, but I truly believe it’s worthwhile to invest the time for refactoring. Building code readability and good design should be foundational pillars in your engineering organization. Embrace the importance of readability—not only does it enhance productivity for everyone involved, but it also facilitates better onboarding for new developers. When the code is understandable, it drastically reduces their initial learning curve.
00:17:03.840 We are ultimately developing software for humans, benefiting human users. Ernie Miller introduced the term 'Humane Development,' emphasizing our work extends beyond just writing code for machines. We should focus on creating code that our teammates can easily comprehend and work with. The Ruby Community continues to grow in diversity, with many new developers transitioning from various backgrounds. This inclusivity necessitates crafting accessible code. Companies sometimes overlook their code quality when onboarding junior developers, leading to a toxic culture. I believe that the readability of your codebase can significantly impact how well you onboard and nurture junior developers. Writing readable code is vital not just for mentoring but for the overall quality of our work. As we wrap up, remember that readability should be the core principle guiding our development practices.
00:18:16.170 Thank you!