Talks
Sometimes a Controller is Just a Controller

Sometimes a Controller is Just a Controller

by Justin Searls

The video titled "Sometimes a Controller is Just a Controller" by Justin Searls, presented at RailsConf 2015, explores the balance between functionality and readability in software engineering, particularly focusing on the concept of code quality.

Main Themes

  • Complexity vs. Simplicity: The talk argues that while engineers may tend to favor fancy, complex code, often simpler, more boring code is more effective and easier to maintain.
  • Influence and Communication: Searls expresses the importance of how code communicates its intent and logic to others, emphasizing that code should be accessible and understandable rather than overly clever.

Key Points

  • Good Code Principles:
    • Good code should have clear functionality and communicate intent effectively.
    • Code should be broken down into tiny units, emphasizing single responsibilities.
    • The speaker highlights the need to manage local variables and dependencies, prioritizing clarity over cleverness.
  • Team Dynamics:
    • Developers often struggle with differences in coding preferences, leading to conflicts about what constitutes 'good code.'
    • Empathy is vital to understanding teammates' perspectives, helping overcome biases.
  • Performance vs. Readability:
    • Searls discusses how many frameworks allow for beautiful syntax but may reduce performance, making a case for finding a balance.
  • Monocultures in Teams:
    • Monocultures can improve efficiency but may also lead to blind spots and diminished innovation.

Examples and Anecdotes

  • Searls shares personal experiences with his presentation style and the effort he puts into clarity and engagement, paralleling these principles to coding practices.
  • He humorously critiques the tendency of developers to overthink simple tasks and how this reflects in their coding outputs.

Conclusions and Takeaways

  • Ultimately, there isn’t a universal standard for good code; what's most effective is subjective and can only be evaluated contextually.
  • The importance of fostering a collaborative, open environment where differing coding philosophies can coexist is essential.
  • Vulnerability in admitting uncertainty in coding is vital for growth and improvement within teams.

Searls encourages developers to prioritize clarity over cleverness in their code and to embrace simplicity, which ultimately leads to better practices in software development.

00:00:13.120 Sometimes the controller is just a controller. It’s a deep dive into Action Pack. According to everyone who stopped me in the hallway this week, it’s actually not about that. Instead, it’s about fancy code versus boring code—the epic battle.
00:00:22.480 Here’s some boring code taken from one of my gems. It’s boring, don't read it. Let's make it fancy. Uh, this isn’t fancy, but it looks much more impressive. However, boring code is so much easier to read. I realized, when coming up with examples like this, that it would have made for a really boring talk to simply say, 'Look at this obvious code; it’s better than this cluttered code.' So, I refined the abstract with it.
00:00:39.200 My name is Justin. I do a lot of talks and usually invest a lot of time into my slides, trying to make them artful and effectively illustrate my points. However, I’m not an artist by any stretch of the imagination.
00:00:53.200 Yet, at the end of my talks, people often say, 'Oh, I love your slides,' which fills me with joy. Then they follow up by saying, 'You clearly put so much time into your slides.' I’m overwhelmed with emotion; those are the actual alt texts by the way of Apple's emoji.
00:01:11.200 Fundamentally, though, slides are about time. For anyone watching this recording in the future, this is what a wristwatch used to look like. I don't use a clock, and in fact, Apple already ruined that joke because they updated the emoji to match their products.
00:01:22.799 Speaking of the Apple Watch, if I get a package notification during this talk, I’m out of here, no offense. So, I did my own horological study, calculating that if you take all my free time and subtract the time I spend doing slides, it equals zero.
00:01:35.919 I sat down and pondered why I spend time on this. It’s because I want to win people over to a certain way of thinking or invoke interesting conversations on topics I find important. I realize that without time spent, I won’t win many over, but the more time I invest, the more people I can influence.
00:01:49.440 Even then, I understand that I will never win over 100% of people; it’s just not possible. I’d probably die before reaching that point. Luckily, as I manage a business, I know quite a few project management tricks like the 80/20 rule. I think the 80/20 rule suggests doing a job until it’s 80% done, and then stopping.
00:02:06.560 I figured that I might stop around 80%; I found that it takes about 60 to 80 hours per slide deck, which is a huge investment of time. I didn’t think I’d have quite that much time to prepare for this talk, so I hope you'll forgive me if my art isn’t up to spec.
00:02:13.040 Sometimes, a slide is just a slide. I care about this because I want to do a good job. I want to write talks that mean something to people, but I can’t know if it’s a good talk until I convey it to you and test whether you agree or disagree. It’s contextual—it depends on you. There’s really no such thing as universally good talks.
00:02:29.200 But anyway, this talk is about good code. I’m going to lay down my thoughts right now. First of all, this is going to be very hard to read. I’ll read it for you: good code should have tiny units, like hilariously tiny, as in one public method.
00:02:38.800 I tend to extract the private methods from complex code for their names, not for abstraction. I think these units should either hold and describe a value or perform some useful behavior, but never both. Those behavioral units can contain logic or depend on other units, but never both. I try to eliminate local variables to an absurd degree. I usually start with functional change; my favorite refactoring tool is composition. I refactor via functional composition. I use `tap` and `each` a lot, and there’s a screen side effect in this chain to remind me to go back and refactor that later.
00:02:56.440 I try to minimize third-party dependencies and write wrappers around them. I also try to pull side effects near the entry point, like various imperative spells. Furthermore, I disagree with whatever my peers do every ten minutes, and finally, I try to overwhelm people with information to get my way.
00:03:12.800 So, anyway, that’s my talk. My name is Justin, and I’d love it if you followed me on Twitter. Squirrel is my last name. If you have any long-form feedback, reach out to me at hello.com. Don’t worry; that’s not really the end of my talk. That’s just my favorite way to write code.
00:03:22.479 I’m sure you have your favorite way to write code, and when we get together as teams, we all collectively normalize and develop consensus about our collective favorite way to write code. We all have our frameworks and favorite conventions that delineate how we are supposed to write code. We negotiate these things all the time. The only ones in the room who are consistently right about this are our bosses because they know they want it on target, on time, and on budget.
00:03:36.640 When I attend an iteration planning meeting and we discuss how we'll approach the next feature, it often dissolves into an argument of us all wanting to implement our favorite way. Luis Dekay talked about this phenomenon in one of his stand-up routines. Most people don’t care what happens as long as they get to implement their favorite thing; they don’t even want to back off from following their preferred method.
00:03:51.920 In fact, I feel like I have been that person. Maybe, the case is that if you combine everybody’s favorite way to write code, then, maybe, that’s what good code is. But I suspect, and intuition suggests, that that’s not true. In fact, my thesis today is that there’s no such thing as good code.
00:04:00.560 I have some experiences in my life that made me think this way. First, stakeholder levels still sell out as fast as Hacker News can stock it. We’re all just clearly filling a void in our souls by consuming new frameworks. JavaScript projects rarely succeed or fail solely due to the quality of their code.
00:04:19.200 As a consultant, I’ve been on lots of projects, and code quality is rarely the reason they win or fail. The industry sure doesn’t seem to produce better code over time. If evolution, if natural selection, applies to software, then what it’s optimizing for certainly isn’t code quality.
00:04:35.440 It feels like we’re just oscillating back and forth between one meme and another—perhaps capability and suitability on either end of the spectrum. So, if I had to define good code, I’d say it performs a function and communicates intent. When we discuss performing a function, it’s rather straightforward.
00:04:49.680 We can look at the code, see what it does, measure it, benchmark it, and optimize it. We can always change what it does today; it’s going to be what it does tomorrow, and we can always alter it if we need to. So, functionality is very objective, and as engineers, we’re all comfortable with that.
00:05:02.079 But what about communication? This can feel like writing and even literary criticism. Our egos get drawn into our favorite ways of doing things, and it’s like staring into a crystal ball: we just have to guess how the person reading it will interpret it, what they will understand, and what they will be trying to accomplish. We’ll never know.
00:05:14.600 So that communication is completely subjectively evaluated, and this makes many of us engineers really uncomfortable. We often conflate those objective and subjective goals of code, making evaluation challenging. This is where you hear the phrase ‘code is art’ because it sounds impossible to evaluate.
00:05:30.240 On one end of the spectrum, you have nearly no ability to assess, while on the opposite side, we tend to emphasize function because measurement is easier—like burn-up charts. On the other side, we’re simply working from a flawed idea; we only truly evaluate half of what’s going on.
00:05:44.800 This misunderstanding is fundamental and causes discomfort for all of us. It rolls down from how we practice code as individuals and extends into our teams, communities, and industry. We’ll talk about all the side effects of that fundamental error we make.
00:06:02.080 When it comes to individuals, I really wish we could just have an app that could tell us whether our code is good. Well, I’ve written that app for you; it’s called ismycodegood.com, and it’s launching right now. It’s a real thing! Here’s a demo: you type in your GitHub username, it does some calculations, and gives you a report card on your code quality.
00:06:15.040 You can return and input your boss’s or friends’ usernames to see if you are better than them. Finally, we finally have some way to evaluate our code—just don’t view the source. In fact, in the last 30 seconds since it launched, it’s gone viral on Hacker News. You heard it here first.
00:06:32.080 I’m ready to announce version two’s headline feature: TEDx Developer Conversion, which will tell you what kind of x developer you are. That’ll be a paid upgrade because you’ll be able to argue for much higher salaries when you claim you’re an 8.6x developer.
00:06:47.440 There are a lot of sites like this, and they comfort us for some reason. Why do these scoring, ranking, and achievement sites go viral? It’s because any quantified measurement soothes our self-doubts as developers.
00:07:02.240 There’s this secret fear that I think most programmers share: What if my code sucks? I don’t really know. What if everyone else seems to have everything figured out? Maybe they know something I don’t.
00:07:15.160 You know, if I use enough big words, maybe I can fool them into thinking I belong here. We all cope with this in our own way. Some of us present larger fonts; some of us hide behind other people. Remember, the amount of fear, insecurity, and doubt varies from person to person.
00:07:29.919 There’s what we might define as a healthy amount of concern; some people struggle with anxiety about how they fit in, while others seem unfazed by what others think about their code. On one end, some folks are introspective, empathetic, and persuadable. On the other hand, people may exhibit a high level of self-assurance and confidence in their convictions.
00:07:45.040 How would you rate yourself on these scales? Let’s practice on me. Last week, I returned from France and filled out a customs declaration form upon entering the country. I hate this form. The first time I pulled it out, I was convinced I would get arrested because I didn’t know what I was doing.
00:08:00.000 Every time I fill it out, I find a new ambiguous wording in it; one of my favorites asks if I’m bringing fruits, vegetables, plants, food, or insects. I know what they’re asking for here; the intent is to prevent bio-contaminants from entering the country, but I’m a total technocrat.
00:08:13.840 I’m buddies with Aaron Patterson, who loves avant-garde junk food, and I bought a special milk bar with Oreo in it for him when I was in France. So, while filling out the form, I start by writing ‘No,’ then I feel guilty and change it to ‘Yes.’ But not really; it’s just candy chocolate.
00:08:31.200 I underlined 'candy,' thinking they might think I crossed out 'food.' But that’s what it is! So, my word library reflects that I’m anxious—clearly, I’m a high-anxiety individual.
00:08:45.760 If you think of those spectrums, when we hold people’s subjective evaluations in high regard, those who are very reflective might feel paralyzed by their self-doubt. They tend to struggle more for approval than those on the other side of the spectrum who value self-betterment.
00:09:00.400 This is crucial because all of this leads us to evaluate code poorly as an industry. The conscientious coders can doubt themselves disproportionately. The callous coders perform better as they are free from such concerns. Eventually, the conscientious coders feel marginalized and leave, perpetuating our flawed evaluations of code.
00:09:16.960 In teams, have you ever tried a new coding approach that you were excited about, only to have a team member quickly shoot you down or dismiss it? Or conversely, have you had a team member shoehorn a new approach they saw in a screencast into your project? It’s frustrating.
00:09:30.720 You know, in the exact same situations, there’s a phenomenon known as the fundamental attribution error. This refers to how we tend to justify our own actions as good while not extending the same leniency toward others.
00:09:44.560 To overcome this, we should exercise empathy. If I can understand why my teammate is doing things differently, I can justify and accept their approach. The problem is, however, we often end up expending so much energy masking our insecurities about the quality of our own code.
00:09:58.560 This leaves little room for compassion toward our teammates. Moreover, a core tension on teams involves balancing comfort with familiar coding approaches versus seeking out novel methodologies for solving problems.
00:10:13.440 On one side, those who prefer familiar solutions may view themselves as relying on proven methods, while those on the opposite end might see themselves as actively practicing modern development. We can bridge these divides, but personal insecurity and a lack of willingness to be vulnerable can prevent this.
00:10:30.240 Now, as a quick tangent, let’s talk about culture fit. I know we need to consider what culture fit means that can often come across as just a long-winded secret handshake to ensure you belong in the right club. It’s ritualistic alongside being evaluative.
00:10:46.720 Talking about monocultures and teams, the first dirty secret is that monocultures actually work faster. You might not want to admit it, but it’s true: if you stack your team with developers who all agree about the right approach, they run smoothly and efficiently.
00:11:01.040 However, a truth bomb is that those who claim they foster meritocracy often reinforce monocultures by just hiring individuals who align closely with their established preferences.
00:11:13.920 The issue with this is that if everyone on the team thinks the same, they are left with massive blind spots when environmental changes happen in the market or to types of users consuming their products.
00:11:28.800 A second secret is that faster doesn’t mean better. The world teaches us that slow equals stupid. Thus, teams that have to confront diverse perspectives and ideas deliberatively might be slower but create more robust solutions.
00:11:43.920 You could argue that a few people from both sides of a spectrum would argue about potential solutions to end up with fewer blind spots. Therefore, we need to stop framing concepts such as TDD, Agile, or Turbo Links as guarantees for speed; rather, they might yield better solutions.
00:11:59.040 In addition, most dichotomies are false. The two ends of a spectrum I showed earlier don’t capture the whole picture. Instead, we should treat these as parts of a wider array of possibilities.
00:12:16.800 The crux of the conversation lies in understanding the functionality of code on one end and communication on the other. If all the economies are false, then we must embrace everything as a spectrum.
00:12:32.560 For instance, I want to discuss how communication is directed at humans while functionality speaks to machines. A highly optimized function could be very dense and specifically designed for compiler or interpreter efficiency, but it may poorly communicate to humans—requiring extensive documentation to comprehend.
00:12:48.440 Conversely, much of Ruby’s popularity stems from its ability to communicate humanistically; its code is usually very readable but may struggle with speed due to all the dynamic nature that can be introduced.
00:13:03.680 This is yet another spectrum, and we must evaluate our code based on its ability to communicate effectively with both humans and computers. I propose a new concept: indirection analysis. In your system, every library, file, method, or name represents a form of indirection.
00:13:20.320 Every macro, reflection, or meta-program presents a significant level of indirection because changes can affect everything that preceded it. I would be curious to see someone invest the time to create a method for scoring indirection in a system.
00:13:34.560 For instance, for a given code path, we could assess how many names or concepts are encountered, how many separate files contribute code, how many tests redundantly cover that code, and what percentage is covered by third-party dependencies. All of this is helpful for both humans and computers to grasp the communication level of our code.
00:13:50.320 This drives us down the broader concept of dry versus wet—‘dry’ stands for 'Don't Repeat Yourself,' while ‘wet’ means to duplicate every element. Both extremes carry significant costs; on one end, where we couple nothing, it’s easy to change one small thing.
00:14:04.160 On the flip side, when we duplicate nothing, navigating change requires understanding the entire system. Thus, a healthy balance lies amid this spectrum.
00:14:17.920 Explicit versus implicit indirection is another interesting concept. With systems that leverage explicitly defined objects, you need a strong understanding of that unique framework for optimal success, tend to have heavier onboarding processes. Systems leveraging implicit indirection, like certain frameworks, establish commonality across the coding communities.
00:14:34.960 Practicing how we communicate about our codes is essential, leading us to more meta discussions.
00:14:51.440 Now let’s shift focus to community. Our community consists of individuals who are prolific; they speak at conferences, contribute to publications, and provide new ideas that inspire us. Think of them like a sixth person in our teams, helping to guide us with new thoughts and practices.
00:15:05.200 When it comes to code writing for our jobs, we must ask ourselves: Who is this code meant for? If I’m writing on a typical day, I can’t help but feel that I’m coding such that someone noteworthy, like Jerry, might be reading over my shoulder.
00:15:20.080 This thinking compels me to produce extravagant coding, stressing details, not just for me to monitor but for the reader as well. However, realistically it’s more likely going to be someone who is more like me or perhaps a novice, someone who will find comfort in clarity.
00:15:36.320 We suffer from a bit of hero-worship in this field—a common sentiment among developers. Gary tweeted about this; he highlighted how former speakers seem so mysterious. Now that I’ve given my first keynote speech, I’m just like everyone else—a total ding dong.
00:15:49.439 So, here I am, a certified speaker now. Your clever code does not impress me; in fact, your clever code makes me feel unintelligent. The more I reflect on this, I realize that clever code tends to signal poor understanding.
00:16:05.760 I’m far more impressed when developers focus on making complicated ideas accessible. This is much more challenging and, generally speaking, obvious code is more impressive than clever, convoluted code.
00:16:19.920 Speaking to the way thought leaders share knowledge, we’ve been inundated with numerous design approaches that become like memes—things like MVC, DDD, DSLs, and so forth are memes. Memes compete for our attention, feed off of it, and reproduce via our communications like evolution.
00:16:35.760 Ideas often start with individuals experimenting, then they transition to early adopters, spreading influence and eventually becoming mainstream. If successful, they become ubiquitous and eventually are recognized as a standard.
00:16:50.560 As for popularity—these ideas really shine once they’re widely known; any novel thought might incur much higher costs until its benefits are widely recognized. Understanding why design memes become so accepted helps us appreciate what they offer but requires caution.
00:17:06.400 The relationship between early adopters of ideas and their perception of benefits produces many passion projects—often overly optimistic about the changes they’ll bring. This leads to scenarios wherein the common population may benefit less than anticipated, so caution is warranted.
00:17:22.320 In the business aspect of this discussion, we need to acknowledge the complexities of communicating coding standards to non-technical individuals. For example, when clients want to assess how well they’re hiring developers, it can become quite abstract.
00:17:37.680 Requests for Proposals (RFPs) often pop up in the industry, which can lead to misunderstandings about quality work. If you’ve participated in responding to an RFP, you’ll understand the challenges tied to perception and risk.
00:17:53.680 When given an RFP, those viewed as conscientious tend to reveal a lot of risks while more self-assured developers rationalize potential pitfalls away. Thus, when presented with estimates for projects, the split between pessimistic estimators and overly confident optimists drives their bids.
00:18:08.240 Not only that, pessimistic estimators tend to provide above-average bids and rarely win work, while their self-assured peers often win projects at lower rates yet attribute failures to external factors instead of internal shortcomings.
00:18:22.560 This bias leads businesses to ultimately favor a specific type of agency that aligns with their current preferences—leaving no room to handle relatable projects effectively. This explains why flashy claims often distort the perception of coding quality.
00:18:39.920 I’d encourage us as developers to exhibit vulnerability in admitting the uncertainty inherent in our profession. The predominant metaphor for software development in the business realm is construction—building tangible products. Yet, it only serves to a certain point.
00:18:55.840 Another worthwhile metaphor is surgery, emphasizing how software exists to resolve issues. Decisions surrounding a project can lead to significant risk or opportunity involved—as well as determining treatment lengths.
00:19:12.560 You can either rush a project with lots of uncertainties, leaving a trail of destruction, or you can be more surgical, focusing on minimizing risk to lead to a healthy outcome.
00:19:28.640 This contrast provides valuable insights for developing code quality. Instead of merely determining how long it will take to build a feature, we should also focus on how much uncertainty lies ahead regarding risks in our code.
00:19:44.320 On the left, the cost of construction is a pressing line of inquiry, while on the right side, the emphasis is placed on risk tolerance—how can we effectively manage uncertainty to reach solid outcome goals? These two contrasting inquiries are not fundamentally wrong.
00:20:00.080 The challenge lies in their follow-up; when business types inquire about project timelines, they effectively seek assurance of quality. They invariably wonder how badly they can handle poor code when completing projects.
00:20:14.560 The rates they charge are often deterministic and do not accommodate real-world code’s vagaries or complexity and lead us to misunderstanding. It may lead direct pricing behaviors.
00:20:30.560 On the left, we could frame our inquiry in terms of coding up project specs; on the right, we could frame inquiries in terms of evaluating risks in managing uncertainty within projects. Both require deep understanding.
00:20:45.760 Therefore, you might want to adopt a strategy of selecting the most uncertain features first and addressing associated risks with careful assessments before deployment. That could enable your teams to engage more meaningfully.
00:21:01.840 This methodology could be articulated as the boring code discovery model. Ultimately, when exploring code, we can focus on identifying shared context without necessitating reinventing wheels, ensuring our applications function effectively.
00:21:16.960 Key considerations for developing code quality center on positively named domain concepts to create efficient silos while keeping empathy high for future maintainers and surroundings.
00:21:32.080 With these principles in practice, we might experiment among our team to gauge how projects flow and measure familiarity with concepts regarding developing unexpected scenarios.
00:21:45.280 At the end of the day, I suggest the following for productive coding: ignore arbitrary distinctions that claim universal good code and recognize that evaluating takes a subjective twist. Therefore, your fear of having less-than-stellar code is merely an illusion—don’t let it hinder you.
00:22:00.560 Instead, seek new opportunities for respectful deliberation regarding your work from your team while reflecting on how to honor differing perspectives toward coding. Exercise creativity when faced with views you might disagree with, and turn clever into—self-indulgent.
00:22:15.680 Finally, if someone doesn’t grasp your code, recognize that some responsibility lies with the creator. Just as Chip Thorne articulated, if parts of your work are challenging to comprehend, take a moment to reflect.
00:22:30.560 In conclusion, my main message is this: be courageous and embrace the simplicity of ultimately understanding your code better. That’s the end of my talk. My name is Justin, and I’d love it if you got in touch.
00:22:45.680 Follow me or provide feedback; I’m from Test Double, a software agency. If your team needs extra engineering support, reach out to us. We’re constantly hiring and looking for opportunities.
00:23:02.400 I have stickers if you’d like one! They represent our logo. Thank you all for your time, I really appreciate it.