

How to make your code imply responsibilities - saturnflyer
http://www.saturnflyer.com/blog/jim/2013/10/21/how-to-make-your-code-imply-responsibilities/

======
rads
> 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.

[1]
[http://worrydream.com/LadderOfAbstraction/](http://worrydream.com/LadderOfAbstraction/)

~~~
saturnflyer
Thanks for some fantastic feedback. I haven't read the worrydream link yet,
but will check it out.

------
ufo
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.

[https://en.wikipedia.org/wiki/Smalltalk#Control_structures](https://en.wikipedia.org/wiki/Smalltalk#Control_structures)

[http://c2.com/cgi/wiki?VisitorPattern](http://c2.com/cgi/wiki?VisitorPattern)

[https://en.wikipedia.org/wiki/Mogensen%E2%80%93Scott_encodin...](https://en.wikipedia.org/wiki/Mogensen%E2%80%93Scott_encoding)

One neat example of this correspondence is continuation-passing style. For
example, in Javascript:

    
    
        function foo(){ return value; }
        function fooCps(cb){ cb(value); }
    
        function bar(){
           if(x){
              return {tag:'OK', value:value};
           }else{
              return {tag:'ERROR', errmsg:"message"};
           }
        }
        function barCps(okCb, errCb){
           if(x){
              okCb(value);
           }else{
              errCb("message");
           }
        }

------
richkuo
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 %>

------
lmm
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.

------
adriancuadros
Great read and use of blocks.

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.

------
thecolorblue
This is a great article. I'm brainstorming how to do this in javascript.

~~~
jxf
Right now, you might have something like:

    
    
        ... = function() {
          // set up header
          // set up content
          // set up footer
        };
    

Segregating the responsibilities might look something like:

    
    
        var homepage = (function() {
            function renderHeader() {
                // ...
            };
    
            function renderContent() {
                // ...
            };
        
            function renderFooter() {
                // ...
            };
    
            return {
                renderHeader: renderHeader,
                renderContent: renderContent,
                renderFooter: renderFooter
            };  
        })();
    

Now you can just invoke "homepage.renderHeader()", instead of, say, 5
different methods that conditionally decide what should go in the header.

