RailsConf 2017

Do Your Views Know Too Much?

Do Your Views Know Too Much?

by Jason Charnes

In the talk "Do Your Views Know Too Much?" at RailsConf 2017, Jason Charnes addresses the common issue of complex business logic being embedded within views in Ruby on Rails applications. By questioning the extent of logic in views, he suggests that many developers unknowingly let views become cluttered with operations best suited for controllers or models. Charnes emphasizes the importance of refactoring views to improve code maintainability and readability. Here are the key points discussed during the presentation:

  • Introduction to the Problem: Charnes kicks off by reflecting on his own experiences and anxiety about public speaking, which he overcame through involvement in the Rails community. He introduces the idea that views often become cluttered with code that should reside elsewhere.

  • Code Smells in Views: He categorizes certain coding patterns in views as code smells, indicating areas where better practices could be applied. For example, direct database calls within views, reliance on ActiveRecord, and multiple conditionals that complicate the view's purpose.

  • Refactoring Approaches: Charnes presents three primary ways to refactor views to clean them up:

    • Unit Level Refactoring: Simplifying view logic by shifting responsibility to models with methods that encapsulate complex logic, thus making the view more declarative.
    • Helper Methods: Utilizing helpers to centralize logic that may be needed in multiple places within views, promoting the DRY (Don't Repeat Yourself) principle.
    • Decorators: Introducing decorators to wrap model objects and provide additional presentation logic without polluting the original model, allowing for cleaner view templates.
  • Conditionals in Views: He highlights the need to minimize conditionals in views, advocating for placing such logic into helpers to keep views focused primarily on data presentation.

  • Key Takeaways: Charnes wraps up by reiterating four essential principles for better view design:

    • Views should not access the database directly.
    • Views should minimize repetition of code.
    • Views should avoid computing data.
    • Views should reduce conditional logic as much as possible.

Charnes encourages developers to prioritize the readability and maintainability of their views, suggesting that well-structured views contribute to overall code quality and easier collaboration within teams.
Overall, the talk provides a compelling case for view refactoring, coupled with practical strategies that developers can implement immediately to enhance their Rails applications.

00:00:13.230 I appreciate you coming out to listen to me talk about views. There is much reward in this topic, and once we are done, we have an Eric Patterson keynote to look forward to. So, there's much to look forward to; we just have to get through this. Today, we're going to talk about views.
00:00:23.130 When I originally put this talk together, I wanted to pose a question for myself: Do my views know too much? As I began to prepare, I realized that the question needed to be adjusted; I can confidently say that your views know too much. That's what we're going to explore today.
00:00:39.180 Before we get into that, let me introduce myself. My name is Jason. I've been writing Ruby since 2012, and this is my third RailsConf. I work for a company called Lens Rentals, where we rank as one of the top camera equipment rental companies nationwide. I'm also a new dad, and my wife was really excited when I told her I would be gone for a week while she stays home with our three-month-old baby.
00:01:02.010 It's amazing to be able to stand here and speak today. I used to be terrified of public speaking. About three years ago, I had a crippling anxiety disorder, which made speaking in front of people incredibly daunting. In college, I actually took my public speaking class online for that very reason.
00:01:31.340 Three years ago at RailsConf, we had some technical difficulties during the lightning talks, and they needed someone to fill in. I decided to talk about my anxiety for 90 seconds, and that experience changed my life in a way that made me excited to come to talk at events like this.
00:01:57.090 So, in a sense, while our views might not know much, I want to share my insights because if you ever consider getting into public speaking, you should do it! It's an amazing experience, and there's no better community than this one.
00:02:21.180 Now, back to our topic: How do we determine what 'knowing too much' means? As I said earlier, I started thinking about this, and I’ve seen it happen numerous times. Often, our views become a dumping ground for logic without us realizing it.
00:02:28.889 All of our principles of good code tend to get thrown away as we start writing into our views. We often say, 'Oh, they’re just views.' But perhaps that isn’t the best approach. Let’s take a look at an example of such a chunk of code.
00:02:48.660 For instance, we begin by retrieving all users from our database and looping through them. It seems simple enough, but then the requirements start piling up. If the current user sees themselves on the list, they should be able to click 'Edit.' Furthermore, admins should have the ability to delete users. While this seems manageable, the complexity increases over time. We don’t usually start off with a lot of conditionals in our views, but things escalate.
00:03:30.840 I love discussing clean code, and I believe in principles like skinny controllers and service objects. However, I've noticed that once I'm done refactoring and have implemented good patterns, I often overlook the views altogether. This talk is meant to refocus on views and show some love towards them.
00:03:51.180 Before we get into specifics, I want to clarify what this talk is not about. It won’t cover design aspects since I'm not a designer. It also won’t discuss front-end JavaScript frameworks as I'm not an expert in that area. Instead, I'll share insights based on what I’ve learned along the way.
00:04:00.300 I want to set the expectations that this isn't a definitive guide, but I hope what I share can help you in your own journey.
00:04:14.040 Let’s start by examining a chunk of code together, looking for what I'll call 'code smells.' These smells aren't official; they're experiences that I've deemed problematic over time. Let’s whip our views into shape.
00:04:40.150 One common code smell is that our views shouldn’t know about the database directly. Active Record makes it easy for us to access models anywhere, but with great power comes great responsibility. Our views should only receive data and not depend on the details of how it's gathered.
00:05:04.200 Here’s the good news for us as Rails developers: we have a simple fix. We can use instance variables in our controllers. For instance, if we have an admin controller, we can set an instance variable for our users right there. Instantly, this makes our views cleaner and more readable.
00:05:30.840 Another common issue is generating names in multiple places. It is inefficient to concatenate a first name and last name each time we need them. Instead, we could add a method to our user model that returns the full name. This marks the first point: our views shouldn’t need to compute data.
00:06:07.920 There are three ways we can keep our code DRY. The first is at a unit level in our user model, allowing us to access a user's name easily and clearly without redundant concatenation across our views. This method is also testable, which is a significant advantage.
00:06:36.720 The second way to achieve DRY code is by using helpers. Helpers are functions available to every view and controller in Rails, and they can simplify our code by performing common tasks, like formatting dates or creating links. If you ever need a function that isn’t part of the built-in helpers, you can create your own.
00:07:06.480 The third approach to consider is using decorators. A decorator acts as a wrapper around our model, allowing us to call methods on it while providing additional presentation logic. For example, if we have a user object, we can create a decorator that adds methods for formatting without changing the original user model. Draper is a gem that simplifies this process in Rails.
00:08:28.270 By using decorators, we can keep our views clean, ensuring they only handle data presentation. This is beneficial in keeping business logic and presentation logic separate. Furthermore, decorators still hold the methods from the original object for ease of use.
00:09:11.000 Next, we need to discuss conditionals directly in views. Typically, we want to avoid having views handle conditional rendering too often. Instead, we can push that logic into helpers where it belongs. For instance, we can create an edit link method in a helper that only renders the link when the current user is the user displayed.
00:10:42.180 By doing this, we clean up our views significantly. Now, we can handle all the conditional logic in one place and maintain clarity in our views.
00:11:06.790 Finally, while partials are a good tool for ensuring reusable views, they shouldn't be used as a band-aid for code smells. Instead, consider whether you can remove complicated conditionals altogether, reducing the need for partials in those cases.
00:12:34.350 To recap, our goal is to ensure that our views do not know about their implementation, avoid repeating data, delegate data computation, and limit the presence of conditionals. By focusing on these areas, we can make our views simpler and more manageable.
00:13:58.850 I ran through a lot of information today, but ultimately, I want you to remember that our views should focus primarily on displaying data. Now, I have plenty of time for your questions!
00:14:09.470 One question I was asked was if I prefer using local variables or instance variables when passing into partials. I don’t have a strict preference. At work, we've decided to use locals because it's generally easier for us to manage, allowing other developers to see variables at a glance.
00:14:52.940 Another question was about using view models in comparison to decorators. You can use view models, but I tend to stick with decorators because it allows me to easily access helper methods.
00:15:09.880 It’s important to remember that sometimes you will run into nil values, but the decorator pattern gives you a layer to handle that outside of your views.
00:15:56.790 So, someone asked about differences between presenters and decorators. I haven’t worked with presenters myself, so unfortunately, I can’t provide a definitive answer. However, I'm familiar with the Draper gem and its role in handling presentation logic.
00:16:21.920 Thank you for coming out today! It’s been great sharing this information, and I hope you found it helpful. Please feel free to reach out with any further questions.
00:17:15.980 Let’s continue these conversations afterwards. I’d love to hear more about your experiences with handling views in Ruby on Rails. Thank you again!