There is all sorts of talk lately in the Ruby on Rails community about decorators and presenters.
What is the essential difference between the two? If there is, what are the clues that tell me which one to use over the other? Or perhaps to use the two in conjunction?
A decorator is more of a "let's add some functionality to this entity". A presenter is more of a "let's build a bridge between the model/backend and view". The presenter pattern has several interpretations.
Decorators are generic/general purpose. Presenters have a narrower range of responsibilities/uses. Decorators are used across domains, presenters are almost always related to view-like functionality.
Draper site
RailsCasts Draper Episode
I suggest you to check this - Exhibit vs Presenter.
Decorator is a design pattern that is used to extend the functionality of a specific object by wrapping it, without effecting other instances of that object. In general, the decorator pattern is an example of the open/close principle (the class is closed for modifications, but available for extensions).
Both the exhibit and presenter patterns are a kind of the decorator pattern.
Related
What is the Rails Presenters folder for?
What goes in this folder?
Why is this folder needed?
presenters is a design pattern commonly reffered to as Model View Presenter(MVP)
This is a derivation of the Model View Controller pattern and is used for creating user interfaces.
It's useful for the Separation of Concerns for making code more DRY.
Here's how Wikipedia describes it
model - interface defining the data to be displayed or otherwise acted upon in the user interface.
presenter - acts upon the model and the view. It retrieves data from repositories (the model), and formats it for display in the view.
view - a passive interface that displays data (the model) and routes user commands (events) to the presenter to act upon that data.
https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93presenter
Presenters in Ruby on Rails
Presenters are simple classes that sit between the model and the view and provide a nice, DRY object oriented way of working with complex display logic.
In Rails, the convention is for them to be located in the app/presenters folder
Here is a userful article that explains the pattern and its use in Ruby on Rails.
https://kpumuk.info/ruby-on-rails/simplifying-your-ruby-on-rails-code/
The Presenters folder is where your Presenter code would go. I know, obvious, I'll explain.
The way I think of Presenters and Decorators is as an abstraction of a Model in order to massage the data attributes before they are given to view.
If you are familiar with helpers, well, Presenters are kind of like helpers in the sense that they are getting some data ready for the view, except helpers usually serve as utility methods for said views, while presenters are more about presenting the actual attributes.
This link explains the difference very well: https://awead.github.io/2016/03/08/presenters/
hope that helps.
Presenters de-clutter your views
When people mention presenters in a rails context (as opposed to discussions of Model-View-Presenter, MVC, MVVM discussions etc) they are referring to a situation where things look really complex in your views: there are plenty of if statements everywhere, and it's difficult to read through it all.
Or to adopt an everyday analogy: imagine you have a really messy house, with stuff piled up everywhere - so that it's difficult to walk through. You can think of a presenter as a large garage where you can neatly organise everything. This makes it much easier to walk through your house, and you still have all the utensils that you need.
Getting back to the rails context: Presenters allow you to remove all that complex logic somewhere else: into the Presenter's folder, so that when you read your views, it will be a lot easier to understand from a higher level. The clutter isn't there, the complexity isn't there: that has been transferred somewhere else. If you want more detail, you will have to go to the relevant folder. The logic need not be contained in a folder called "Presenters" but it can be put there by convention.
I have a lot of similar resources in my Rails application, and I have currently DRY'd up the code using controller inheritance. I see that there is a directory called concerns under the controller folder, where I could potentially write similar concerns (such as archiving, activate/deactivate etc.) I can probably write mixins too.
Is there a preferred approach to DRY up the controller code? Is there any downside in using inheritance, or are there any advantages using other techniques?
Is there a preferred approach to DRY up the controller code?
In my experience, it depends on what you want the code to do. I've only used concerns for simple controller-independent methods, such as before_action or something
I would use inheritance if your controller's methods are able to rely on a super class or something. My experience so far has lead me to use inherited_resources - a DRY way to create controller inheritance
Some facts/assumptions:
It is said that Ruby on Rails follows MVC architectural pattern.
The MVVM (Model View ViewModel), which derives from MVC, offers an abstraction layer, where all the buttons, labels and links (View) are separated from the way models expose data (ViewModel).
Some Javascript frameworks, that excel in building Single Page Apps, leverage MVVM pattern (for instance Knockout.js).
If we check Ruby toolbox, we will see a several presenter solutions like Draper and Apotomo that work just as a ViewModel thing.
Assuming there is no bs in my 'facts' section, there is one thing that bothers me:
Can we call Rails with Draper, Apotomo (or other presenter/decorator) a MVVM solution?
Can we say we are following MVVM pattern with Rails, if we encapsulate the data from the model in a form of decorator/presenter container with Draper?
Or is there something missing and we can't call it a MVVM, like Knockout.js?
Thank you for your insights.
Not in my opinion.... I think of MVVM as creating specific view objects that are disconnected from the underlying data/domain object.
With the Rails presenter pattern, these presenters will typically wrap around the active record object and add methods to it that pertain to the presentation.
I'm an ASP.NET MVC developer just starting with my first big project on rails however Im confused as where to put your business logic? on ASP.NET I create a library which contains services(Domain driven design) which handle business logic, I have heard that rails uses a concept of fat model skinny controller but I have some projects in ASP.NET which adding all the logic to the controller would create a big mess, is there any other way?
Go with the concept of FatModels and SkinnyControllers. Your models should know how they behave and what they should do.
When your models get too fat, extract them out into re-usuable modules and include them in your module.
Example of taking a fat controller (with logic) and moving to a model
Example of taking code from the views and moving into the model
You can easily test behavior of models using RSpec (or test/unit or shoulda). Then you can test that the application behaves correctly using Cucumber.
"Business Logic" or some might call it "Domain Logic" doesn't belong anywhere near Rails and/or your .NET MVC project. Rails and MVC should depend on your Domain not the other way around. I would recommend reading up on the Onion Architecture from Jeffery Palermo or watch "Architecture the Lost Years" by Robert Martin. (I think that's that talk anyway). There are probably more resources than that, but you'll thank yourself later for treating both Rails and .NET MVC like the 3rd party frameworks they are, and not the main house of your application.
I think this blog article provides a good overview of a strategy of incorporating domain driven design with in the rails framework: http://www.smashingboxes.com/domain-logic-in-rails/
TL;DR
Refactor your classic rails models into repositories, and use a facade layer in the controllers to interact with your domain model.
I'm struggling with this a little my self, and as much as the Fat Controller pattern seems to prevail, anything "fat" in software seems to be a smell, violating single responsibility.
You can put business logic anywhere you want (even in views! though that's a bad idea).
I'd say if the logic is tied to a real-world object, then put it on the model. Otherwise, use the controller. But it's up to you to determine how to do it for your app. Models are for modeling things, and Controllers are for controlling things.
My simplest ASP.NET MVC 2 controllers make calls to my service layer and map view models to entities using AutoMapper. Everything looks fantastic and there is no repeated code.
However, when I get into scenarios where I have similar behavior I have trouble balancing Single Responsibility Principle (SRP) with Don't Repeat Yourself (DRY). An example of this might be the need to add/edit vehicles where some properties/behaviors are shared while others are unique to a specific vehicle.
If I strive for really thin controllers (thus honoring Single Responsibility Principle), I end up having repeated code in both the views and controllers with minor variations (title, field labels, field visibility, dropdown values, selection criteria, etc.).
If I strive for non-repeated code I end up bundling too much logic into a single controller/view and it gets bloated.
What are some ways of addressing repeated code in controllers / views? I'm not talking about database code that can be factored out to a repository. Nor am I talking about business logic that can be factored out to a service layer. I'm looking for tools and/or rules of thumb that will help me produce the best solution in the scenario described above.
You get:
partials
RenderAction
action filters
service layer and helper classes (not HtmlHelper)
model binders
base controllers
dependency injection
So your views can invoke shared partials/actions for similar parts, common data can be prepared by action filters, database access code can be hidden in smart model binder, or you can have parent controller that child controllers override with specific tweaks. And, of course, good old service layeres, where you just extract common code into helper/static methods, or, better, inject specific implementations.
That's nothing new, same old tricks.
Or, maybe, your controllers do too much works? This is where stuff above also helps. ASP.NET MVC has very good tools to hide infrastructure-layer code and move it away from controllers. And if it's not infrastructure - it probably belongs to domain layer. There you can use inheritance, composition and other OOP tricks.
Specific example. Suppose your controllers should set few properties in a different way.
You can have your views to do this, if it's mostly formatting or choosing what properties to show
You can have your entities to have virtual methods - i.e. refactor code to move decisions to domain layer instead of controllers
You can have helper ViewDetails classes that will take your entities and get the data based on for what you need it; this is a bit of a dirty trick but sometimes useful; you delegate decision to another "strategy" class
You can use action filters to add this data to ViewData, or to tweak specific ViewData.Model types (look for some interface of it).
You can have abstract controller, where children pass implementation details to the base constructor like (): base(repository => repository.GetSpecificData())
And so on. I actually use all of them in appropriate places.
You are worrying too much about SRP and DRY. They are principles only and are not always right. SRP and DRY are good if they make your code more maintainable, but if they are in the way then ignore them. MVC is similar. It is useful in simple small desktop applications but is not appropriate for web applications. Web Forms is much better for the internet world while MVC is something from the 1980s.
I recommend you to use SRP over DRY in those cases. I wrote here a detailed answer.
In short both are rules which help to keep your code maintainable. DRY is a low abstraction level mechanism, while SRP is a high abstraction level. By maintain an application the high abstraction level structure is more important than the low abstraction level.
In your case I don't think it is necessary to give up DRY.
An example of this might be the need to add/edit vehicles where some
properties/behaviors are shared while others are unique to a specific
vehicle.
Many design patterns can help in this case. You can use decorator, composition, and so on... combined with builders for the different types of vehicles.
I found that ApiEndpoints is very good for this. You create a class for each controller method. A little more code, but I think it's very clean.