> First, the name merely combines two values. What will happen when requirements change and we need to ensure that the provided experience includes at least 3 years of activity? The meaning of has_public_experience? will change along with its behavior and lead to surprises for developers unfamiliar with these particular details. It will no longer merely be existince of experience allowed for the public.
The problem is not the boolean, it's that we're using the wrong name for the method. Just choose a better name:
class ProfilePresenter < ::Presenter
def display_experience?
profile.has_experience? && profile.experience_public?
end
end
The advantage of this over a block is that you can use this in more than one spot on the page. What if you wanted to show a special badge for users with experience in a different place? You'll end up extracting out this logic anyways -- it will just be hidden by another layer.
> This leads us to the second problem: the intent of the method is to display features, not query for values. Were we to stick with a query method like has_public_experience? we would end up considering the content inside the view along with the meaning of the method every time we read this code.
When you move up and down the ladder of abstraction[1], make it clear. When you're talking about "has_experience? && experience_public?", the new name "with_experience" does not communicate that we're hiding details, nor does "block.call" when you look at the new method. The name "display_experience?" makes it clearer that we're now moving to a higher rung, the view.
This is a neat trick that pops up from time to time. Instead of representing an algebraic data type as a bunch of cases that you can test with if-statements at runtime, you represent it as a pattern-matching function that receives a code block to run for each possibility.
This is only necessary because the templates he's using are so crude and page-oriented. With a truly object-oriented framework like Wicket the problem goes away - you have a component hierarchy that parallels your model hierarchy, so e.g. your user panel just knows that a user has an address and hobbies etc., then the address panel just knows that it has a street name component and a zip component and so on. I wish I could find a framework that was properly object-oriented in any other language.
Personally the 'if' conditional statement acts as a visual trigger.
It allows me to quickly recognize that something may or may not show up on the view.
I would prefer something along these lines:
class ProfilePresenter < ::Presenter
def with_experience?
profile.has_experience? && profile.experience_public?
end
end
<% if user_profile.with_experience? %>
<p><strong>Experience:</strong> <%= user_profile.experience %></p>
<% end %>
I see how this code would be appropriate in larger apps but when things are just getting started. I would rather see an if else than having to go into three different structures to find out when a certain block of code is to be rendered.
The problem is not the boolean, it's that we're using the wrong name for the method. Just choose a better name:
The advantage of this over a block is that you can use this in more than one spot on the page. What if you wanted to show a special badge for users with experience in a different place? You'll end up extracting out this logic anyways -- it will just be hidden by another layer.> This leads us to the second problem: the intent of the method is to display features, not query for values. Were we to stick with a query method like has_public_experience? we would end up considering the content inside the view along with the meaning of the method every time we read this code.
When you move up and down the ladder of abstraction[1], make it clear. When you're talking about "has_experience? && experience_public?", the new name "with_experience" does not communicate that we're hiding details, nor does "block.call" when you look at the new method. The name "display_experience?" makes it clearer that we're now moving to a higher rung, the view.
[1] http://worrydream.com/LadderOfAbstraction/