Simplicity

The Fewer the Concepts, the Better the Code

The Fewer the Concepts, the Better the Code

by David Copeland

The video titled "The Fewer the Concepts, the Better the Code" by David Copeland, presented at RubyConf 2019, explores the importance of code simplicity and its impact on maintainability and understandability within development teams. Copeland emphasizes that better code is one that requires fewer concepts for comprehension, thereby making it accessible to a wider range of developers.

Key points discussed include:

- Understanding Complexity: The speaker reflects on his experience working with a seasoned engineer, Justin, highlighting moments where Justin struggled to comprehend Copeland's more complex code compared to his own simpler approaches. This interaction sparked a reevaluation of the simplicity of code and its accessibility for team members.

- Evaluating Code Quality: Metrics like method length, cyclomatic complexity, and other code metrics are important but inadequate. The context in which code exists plays a critical role in its quality assessment. Code should be understandable and maintainable by anyone on the team.

- Contextual Importance: The speaker discusses how one-off scripts can afford less design rigor compared to the critical application-level code, which must be accessible for frequent changes.

- Audience Consideration: Acknowledging that different team members may have varying expertise is crucial. For example, introducing Josh, a less experienced engineer, further illustrates that complexity can hinder learning and comprehension.

- Future Implications: The notion that simpler code allows for a larger pool of contributors is presented, fostering an environment of collaboration and team efficiency. Simplicity leads not only to better understanding but also to reduced onboarding time for new engineers.

- Balancing Complexity and Simplicity: The discussion emphasizes the need to balance using powerful programming features against the accessibility challenges these tools may impose on newer team members.

- Conclusion: The speaker concludes that by prioritizing simplicity and reducing the number of concepts required to understand code, teams can enhance collaboration, reduce frustration, and foster a healthy coding environment. Copeland encourages teams to evaluate their coding practices to ensure they serve everyone effectively.

Overall, the video promotes a paradigm shift in coding practices towards reducing conceptual overhead and prioritizing the collective understanding of code within teams.

00:00:12.049 All right, thanks everybody for coming. My name is David Copeland or dh1 5000 on Twitter and I'm pretty excited to talk about this topic.
00:00:18.119 It's something that I learned very late in my career, and it made me rethink a lot of assumptions. I hope to convince you of the same thing. I want to talk about Justin.
00:00:30.510 Justin is a guy that I worked with at Stitch Fix. He's a very experienced engineer. Although he specializes in networking infrastructure and system administration, he has written a lot of code in his career.
00:00:42.059 If I were to ask Justin if he's a Rails programmer, he would definitely say no. However, he is actually a pretty capable Rails programmer; he can get things done in Rails quite easily.
00:00:55.889 Justin and I were working on a project together that involved building the deployment pipeline at Stitch Fix. Ruby on Rails was a central part of this, alongside other technologies.
00:01:07.710 During a certain period, Justin and I were the only ones working on this application together. Naturally, we would review each other's code. Justin would make a change, and I would review it.
00:01:26.340 His changes would generally be straightforward. He would write sensible code, and it would all make sense. I'd have a few questions here and there about AWS or other topics, but the Rails code itself was pretty easy to follow.
00:01:39.270 However, when it came to my code changes, Justin's comments would often be along the lines of: 'Why did you do it that way?' or 'What is all this stuff?'
00:01:50.340 His confusion was not due to a lack of understanding; rather, he questioned why I didn’t simplify things. He would suggest doing things with less complexity, which made me think.
00:02:07.649 As I kept explaining my reasoning, I began to wonder: why am I explaining something that is supposed to be easy to understand? Shouldn’t it speak for itself if it's truly clear?
00:02:24.090 This led me to reflect on what aspects of my code made it difficult to grasp. Was it Justin's understanding that was lacking, or was it my responsibility to write code that he—along with 50% of the team—could easily comprehend?
00:02:54.840 Perhaps the issue wasn't with Justin but rather the complexity of my code. As I contemplated how we evaluate code, I realized that metrics alone can't capture the contextual factors surrounding the code.
00:03:07.919 Code doesn't exist in a vacuum. It doesn't just hang on a wall for us to discuss how good or bad it is. Instead, it exists within a context, which is critical to our assessment of its quality or performance.
00:03:39.569 What's the purpose of the code? How crucial is it for it to work flawlessly? We have all written one-off scripts that don't need to be meticulously designed. It’s important to consider whether it’s something that will change often or is largely static.
00:04:10.680 Moreover, whose job is it to maintain the code? Who needs to ensure that it works and to add features? Understanding the context of these questions is pretty important for evaluating code.
00:04:23.759 If I write the most outstanding code and nobody—including my own team—can understand or maintain it, is it truly remarkable? A great code metric alone can't capture this context—it only displays what the code looks like.
00:04:58.589 Let’s look at some code metrics for an example. Here’s a simple piece of code that sums the costs of items in a shop. Can everyone follow what this code does? It's quite idiomatic Ruby—we aren't using Rails or Active Support, just standard Ruby, which most programmers can grasp.
00:05:52.830 But let’s evaluate the code metrics for this Ruby code using RuboCop, which can calculate things like method length, ABC size, cyclomatic complexity, and perceived complexity. These metrics provide us a baseline to understand its complexity.
00:06:14.760 Now, let's compare it to a different piece of code performing the same function. This one seems to be far less elegant. It’s not idiomatic Ruby; it has more variables and a complicated for loop, which may confuse many.
00:06:39.330 RuboCop metrics indicate this is decidedly worse: a longer method, larger ABC size, higher cyclomatic complexity, and more perceived complexity. It's more complex and thus typically harder to understand.
00:07:05.050 But whose job is it to maintain this second block of code? If you’re a JavaScript developer, which one would you find easier to handle, the first or the second? If you're a Java developer who has just finished boot camp and hasn't explored Ruby, you've got to ask: which version would be easier for you?
00:07:49.070 How can we quantify this? Let’s count the concepts required to understand both code snippets. For the first piece, you would need to know about classes, methods, and Ruby-specific functions, which totals 13 concepts.
00:08:14.250 Now let's look at the second, more complex code. You still need to understand classes and methods, but the count here is only 9. Interestingly, this less idiomatic Ruby code, while seeming worse, actually requires less knowledge to grasp.
00:08:49.370 This revelation introduces a new way to evaluate code quality. Good code should not require in-depth knowledge of numerous concepts, and understanding the context of the code is valuable.
00:09:12.759 When we write and modify code, our primary aims are to ensure that the code is easily understandable and maintainable. Thus, if code requires fewer concepts to comprehend, it should be regarded as better.
00:09:46.829 However, it's essential to critique this idea. What if I understand all the code I've written, but you don't? It doesn't imply my code is better than yours. It’s about the intended audience for that code.
00:10:14.999 For instance, if someone is expected to be a Rubyist without knowing certain methods, then it suggests a gap. We should reconsider the workload and expectations of those who are new to Ruby or to programming.
00:10:49.079 Let me introduce Josh—a less experienced engineer who joined the team with Justin. While he has a background in networking and operations, he has not had as much programming experience.
00:11:04.569 When Josh examines the more functional code that Justin and I wrote, he wrestles with its complexity. In contrast, he finds it easier to understand the code that I consider bloated and less elegant.
00:11:48.929 This illustrates that despite the code's intended quality metrics, its readability and understandability are more important based on who is on the team. If Josh struggles with comprehension, perhaps the code could be improved.
00:12:19.450 Thus, the concepts required should be considered again. Josh, who isn’t a seasoned programmer, struggles with concepts that may be relatively standard for someone with more experience—for instance, List comprehensions.
00:12:57.579 This ultimately reiterates the importance of context and who could potentially work on the code and maintain it. Good code should be accessible to the entire team.
00:13:45.660 Code that is understood only by its author holds less value. If every programmer in an organization can understand a piece of code, it adds a lot of value to the project.
00:14:52.200 We must consider this further: if the code is understandable by every programmer, it serves as an asset to the organization. It broadens the pool of team members who can address issues and implement changes.
00:15:15.030 Think about the implications of code simplicity on a broader scale. The simpler the code is, the more likely it is that future programmers, regardless of their experience level, will understand and contribute to its development.
00:15:49.540 As we discuss more complex systems, it's crucial to understand how context plays a role in comprehensibility and maintainability. Simple code makes a system more approachable for many individuals.
00:16:08.030 The more our code embraces simplicity, the higher the likelihood of wider understanding and ownership among the team.
00:16:18.500 Most significantly, recognize that when developers encounter methods or structures that are convoluted, frustration and confusion may proliferate, leading to a lack of confidence.
00:16:32.060 At the same time, we must not dismiss the sophisticated capabilities that programming languages and frameworks provide us. These tools each come with a learning curve, which can make onboarding new team members more challenging.
00:17:01.890 For example, in our decision-making process, we must weigh the power of the features we integrate into our code versus the potential difficulties new team members may face.
00:17:25.520 The process of adding new features or introducing a more complex structure demands a commitment to bringing everyone on board. This can be both a daunting yet essential task for development teams.
00:17:55.470 By observing how our choices affect both the clarity of code and the onboarding experience for new team members, we can foster an environment that values simplicity and teamwork.
00:18:20.070 When difficult choices are presented—like whether to adopt a new language or library that requires extensive knowledge—consider creating pathways for onboarding rather than simply abandoning existing team members.
00:18:40.520 This approach was employed by Twitter when switching from Ruby on Rails to Scala, emphasizing training programs for their Rails developers to adapt smoothly to the new language.
00:19:05.200 Based on what we've discussed, take note of how your systems evolve as you understand the role of people on your team. Simplifying code structures can empower more individuals to contribute meaningfully.
00:19:29.100 Ultimately, strive to develop systems that prioritize the ease of comprehension for everyone involved. The balance between complexity and novice friendliness is key.
00:19:56.420 Whether through measurement tools or thoughtful driving principles, this mindset can represent a paradigmatic shift in how we create and maintain coding environments.
00:20:13.850 Engaging with these concepts can enhance not only the code we produce but also the shared understanding and growth of our teams. Let's open the floor for questions.
00:20:39.850 Are there any tools that count the number of concepts? Not that I'm aware of, but I bet Code Climate would be interested in such a feature.
00:20:48.000 A good question was raised: how do we balance our desire for expressive programming languages with the usefulness of simpler constructs, like for loops?
00:21:03.000 It's important to enhance our coding environment while keeping our teams motivated. Understanding their strengths allows us to make informed choices about code structure.
00:21:30.620 If a newcomer observes complexities in code, they should question them respectfully. However, when well-meaning dialogues come from seasoned engineers, it presents a valuable opportunity for reflection.
00:21:54.800 Evaluating the speed at which newcomers acclimate to the code can showcase whether the code remains accessible in the long run, influencing hiring and onboarding decisions.
00:22:27.100 So, is the complexity of the code leading to bugs? The correlation isn't straightforward, as more extended periods without edits may amplify risks.
00:22:36.960 Reading and understanding code can be greatly enhanced by simplifying structures and minimizing the number of concepts required. This balance can lead to reduced bugs over time.
00:23:02.760 In the end, each decision we make regarding code complexity comes with its costs—finding a prudent balance between efficiency and comprehensibility will cultivate better practices in our teams.
00:24:01.230 Remember that valuable code creates environments where clarity shines. The more we strive for understanding, the better we can grow our development practices.
00:24:25.060 If you want to continue exploring these ideas beyond standard wisdom, I’d like to invite you to sign up for my new project.