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.