Refactoring

Summarized using AI

Blow Up Your Views

Jeff Casimir • August 11, 2011 • Earth

In the talk titled "Blow Up Your Views," Jeff Casimir challenges Rails developers to rethink their approach to view layers in a Rails application. He begins by asserting that most developers' views are outdated and oversimplified, having undergone little innovation over the years. Casimir discusses the blending of multiple languages within the view layer, such as Ruby, HTML, CSS, and JavaScript, and criticizes reliance on instance variables that complicate the sharing of context between controllers and views. He advocates for a shift towards a more object-oriented design, suggesting that methods should be used from models rather than cluttering views with procedural helper methods.

Key points include:
- Instance Variables: These are often misused and lead to complex, coupled code that is hard to maintain. Casimir suggests eliminating them through cleaner interfaces.
- View Models: He proposes using view models or decorators to manage presentation logic, which allows methods to be attached to models and makes the responsibility clearer.
- API-centric Design: Views should be treated as API consumers. Casimir emphasizes that separating data gathering from presentation improves the ability to respond in multiple formats and reduces processing on the server side.
- Separation of Concerns: By encapsulating authorization and presentation logic within decorators, individual views can adapt based on user permissions, promoting better organization and reusability.
- Performance Improvements: Rethinking how templates interface with data can significantly enhance server performance, particularly when managing high volumes of requests.

Ultimately, Casimir encourages developers to throw out outdated practices and adopt a more structured, object-oriented approach, utilizing decorators and clear interfaces to improve their view layers. He concludes with a call for questions and emphasizes his teaching capabilities in Ruby and Rails, inviting further discussion.

Blow Up Your Views
Jeff Casimir • August 11, 2011 • Earth

Whether you're new to Rails or have been around few years, chances are that your views are primitive. Detonate what you know about how views are written and let's start over. In this session we'll discuss... - Why your views suck - Instance variables are stupid - Kill helpers and work with objects - Drawing the line between "C" and "V" - Treating views as API customers - Rethinking templating By the end you'll be dying to blow up your views.

Help us caption & translate this video!

http://amara.org/v/FGa0/

LoneStarRuby Conf 2011

00:00:19.720 So, I gave a talk in San Diego, and Matt gave me my favorite feedback on a talk ever. We walked out, went to happy hour, and afterwards he said, "You know, 30% of what you said I agreed with, and the other 60% your mother would be ashamed of." I wish I could do Matt's French accent to make it even more biting. But hey, French people and math—it’s not my strong suit.
00:00:47.440 I hope that some of you don't like this talk; I hope that you look at some of these ideas and say, "No, I completely disagree," but hopefully in an intellectual way. Your views suck? My views suck too. If you compared a Rails application from 2005 to today, how would you update the view template? Just shout it out.
00:01:14.320 Yeah, rename HTML to RHTML. And that’s it—that's all we’ve done in six years of innovation. We have spent absolutely no time on the view template. The idea I’ve been wrestling with is moving away from the term 'view template' and focusing more on 'the view layer.' As Rails programmers, we have models, which are Ruby classes, and controllers that are Ruby classes, and then there’s this view thing—it’s just a template in some directory. We can start to work on this.
00:01:39.079 Why do we avoid improving the view template? It's hard! It’s the only part of a typical Rails application that mixes four languages: Ruby, HTML, CSS, and JavaScript. Writing view templates is a tricky job. We’ve seen a few people try things like Marabe or other object-oriented view templates, but that’s not the way to go. I’m not a fan of the overwhelming nesting of object code. I think view templates are fine, but there’s room for improvement in this view layer. Just don’t leave the view layer to designers—don’t think that computer science is only found in the model!
00:02:27.360 Controllers tend to suck; we should barely have any code in the controller. But don’t just say, 'Let someone else deal with the view templates.' Instead, we should inject more code into the view layer and improve it. One of my first objections to our implementation of the view layer is the use of instance variables. Explaining how data gets from a controller to a view is complex, and I feel bad when I have to teach new rails classes. The controller and the view don't share context, meaning that a local variable from your 'new' action won’t appear in your new template unless you make it an instance variable.
00:03:26.480 It's still not a shared context, but it’s just there in the view. Well, what would you see if you did this with a view template? I hope you’re asking—what's the answer? It’s complicated. In a really trivial application I wrote with some people who had only been doing Rails for a day, the context size was 51,000 characters. It’s as if they created an anonymous class instance where the instance variables have been copied over from the controller. I'm not pointing fingers; I love Rails. I just think we could do more thinking here.
00:04:24.640 In theory, the Rails MVC model has requests going down to the router, to the controller, to the model, to the database, back to the model, up to the controller, and then to the view and out to the user. But in reality, the controller and view components have two responsibilities, which is against Uncle Bob's principle. The controller handles understanding requests and parameters and then provides a half-hearted data interface to the view layer. This part is lacking when we get to the view.
00:05:30.240 When managing the view layer, we have two main tasks: preparing data for output (like formatting a timestamp to suit the designer's preferred style) and combining that data with the template to generate the final HTML. The line between controller and view is blurred; we need to realize that the model doesn't just interact in a vacuum that could be labeled 'MVC.' The model, view, and controller are completely interconnected. If you’re looking at a view template representing the view layer, how do you know what data is available to you? The only way to know is by looking at the controller.
00:06:37.080 That's a very tight coupling! In an API, there’s usually an interface that clarifies how two objects interact, but currently, our views and controllers are intertwined, as helpers. Unfortunately, instance variables are copied over when 'render' is called from the controller, which can be a performance issue, creating and destroying thousands of objects. One approach I think is quite cool is something from Hashrocket in Florida called 'decent exposure.' It helps define a cleaner interface between your controller and view.
00:07:34.080 In a traditional controller and view scenario, you might define methods to expose resources. This allows you to reduce the amount of boilerplate code in your controllers, making them cleaner, and provides a better relationship between views and the data they receive. By using decent exposure, instance variables can be eliminated from your views, thus simplifying the data access problems.
00:08:42.960 Next, I'd like to talk about helpers. Personally, I have a strong aversion towards helpers. I don't dislike them because they exist, but it's frustrating how they’re often perplexing or misused. In Ruby, everything is an object. For example, when I teach people Ruby, I demonstrate how much simpler scenarios can be when we express processes in Ruby compared to C-like languages. But with Rails, we run into the frustration of relying on procedural helpers instead of using object-oriented techniques.
00:09:45.760 Preparing data for presentation is essential, and many people argue that helpers are necessary. For example, timestamps formatted to be human-readable often rely on helpers. But the reality is, most helpers become object-specific and lead to coupling with specific controllers or models. Why not write object-oriented methods instead, utilizing capabilities in the model rather than creating helpers meant for a single model?
00:10:40.760 What if we had methods like 'user.print_name' or 'user.created_at.format' instead of shifting that responsibility to a helper? We can develop a decorator pattern to attach presentation methods to our data models, leveraging Rails helpers directly while isolating formatting logic into a wrapper. This decorator should be placed within its own directory to apply view-specific operations without intermingle with the model.
00:11:49.200 I know critics might raise their eyebrows when they hear about 'view models' or 'model decorators.' But the idea is relatively simple: separate your view logic from your business logic. For example, if I need to provide different JSON requests based on user roles (admin, authenticated, public), it's often easier to do in a view-specific context. We shouldn’t approach it like a single, monolithic application but as distinct interactions with individual APIs.
00:12:54.480 This leads to a separation of concerns. You can create a dedicated decorator that adapts data models for specific displays depending on the user’s permissions, encapsulating authorization logic within the decorator classes. This means when you serve different users, you have adaptable responses. It’s akin to configuring the output format based on the user type, reducing the complexity in your controllers while promoting reusability.
00:13:59.040 Next point: the need for an interface. Ruby offers a lot of flexibility, allowing one to alter classes on-the-fly, which can be dangerous. However, functions like 'attr_accessible' serve to protect against mass assignment issues. With a properly routed decorator, we can establish a clear interface within the view, dictating which methods are permissible and disallowing access to potentially dangerous queries like those performed directly on the database.
00:15:04.200 The project I've been exploring is called Draper, which is an implementation of the decorator pattern in Rails. I’m excited solely because it presents a productive avenue where you can define what methods a view can call without compromising security. It’s been fun developing this project, and I’ve received interest from fellow developers wanting to implement it.
00:16:32.640 Now, let’s transition into the next section—'View Templates.' What about viewing templates as API customers? A year ago, there was a significant article discussing how downloading HTML is becoming less relevant compared to the increasing dependence on video and media APIs. Not having an API for your product today could mean trouble. Developers expect it—having an API alongside your web application is no longer a luxury but a necessity.
00:17:51.040 This presents a challenge in building both web interfaces for users and APIs for developers—a dual commitment that can feel unnecessary. But, should controllers be involved with output formats? If controllers operated to gather data, shouldn't they simply provide that data instead of formatting it? If the controllers defined proper interfaces, we wouldn’t need to account for generating HTML or JSON separately.
00:19:01.320 This approach would transform view templates into API consumers equally for HTML. Returns would simply be viewed as API responses, reducing repeated efforts between responses designed for people versus those made for computers. We want to simplify the entire approach to how we deliver responses.
00:20:10.079 In earlier architectures, response strategies were a challenge, and the client faced longer response times, wasting precious resources during data processing. However, if we shift the workload to the back end massively—we’ll see a significant reduction in server load. Instead, if we treat view templates just as API customers, we bridge the gap between the presentation layer and data API.
00:21:38.560 Moreover, as you design your API interactions, you and your JavaScript engines can share the same data without having to argue over different requirements from the backend or front end. The architectural shift here is moving templates from a view-centric flow and adjusting them for modern API usage.
00:22:52.720 Finally, I want to emphasize reducing processing on the server side to enhance the time to first response. This is of cardinal importance, especially in instances with high volumes of simultaneous users. The reality is that a majority of the response in average pages is ultimately ‘template,’ so effectively parsing large strings can transform load management on your server.
00:24:22.640 Embrace the variation on API customers—it swings back and forth on broader ideas of views as objects capable of fetching their presenting data while keeping operations clear. In conclusion, consider using decorators to enhance the understanding and flow between your models and views.
00:25:31.440 Throw out instance variables, boost utilization of your view layers using decorators, and unify your interface between API interactions and traditional HTML views. I show you how to wrap it up today.
00:27:19.560 Ask me questions—my name is Jeff Casimir, and I teach the best Ruby and Rails classes on Earth. If you or your company ever need that, let me know. Thanks for your time!.
Explore all talks recorded at LoneStarRuby Conf 2011
+15