On Jul 12, 2016, at 1:41 PM, John J. McDermott, CPLP <[email protected]> wrote:
> 
> Let's say I have an app that can generate two kinds of output.  It is a 
> front-end to a database It can be used with a JSON interface or it can 
> present HTML as a traditional web page.

Perfectly fine so far.

> I *could* add a /html element to the path to say "output as html" but it 
> would seldom -- if ever -- be used. I *could* add a checkbox to the web form 
> so it would return JSON but it is unlikely a normal person would want that.

Do you know a strong functional programming language?  I don’t mean FP in the 
way that JavaScript is a Scheme dialect and therefore FP, or even in the way 
that Perl is FP as laid out in Dominus’ “Higher-Order Perl.”  I mean FP as in 
Haskell, the ML family, Erlang, etc.

These languages teach you the value of thinking of functions in the 
mathematical sense, which is that any function called with a given set of 
arguments should always return the same result.  Another way of saying the same 
thing is that functions should not have side effects.

It is impossible to avoid all side effects in any practical program not doing 
pure mathematics, but we can minimize and restrict the scope of these side 
effects by thinking hard about where the boundaries should be.  Strong FP 
languages sensitize you to this way of thinking.

In the context of this debate, the principles of tightly-scoped side effects 
and referential transparency tell us that if you should not have a a Dancer 
route that returns HTML in one context and JSON in another.  Either the route 
must differ somehow or the parameters must differ.

My preference is to put all JSON-returning Dancer routes under /api, then make 
all other routes return HTML.  (That’s a simplification.  My current app also 
has /pdf for the routes that return dynamically-generated PDFs, for example.)

Where the HTML-returning routes need data returned by the JSON API, either:

1. Call the internal JSON-returning route handler from the HTML route handler 
and use its data to construct the HTML; or

2. Call back into the API from the client side via JS and construct HTML from 
the returned JSON data there.

An example of alternative 1 is:

    sub getSomeData {   … used below …    }

    get '/foo' => {  # because not under /api, returns HTML
         # Do stuff here
         # ...

         # Okay, we’re ready to return our page
         return template '/foo' => {
              oneElement     => getSomeData(param 'bar'),
              anotherElement => $variableComputedAbove,
         }
    };

    prefix '/api' => {
        prefix '/some' => {
            get '/data' => \&getSomeData
        };
    };

Here we have two routes, one returning HTML and one returning JSON, the first 
of which is implemented in terms of the second.  Because of Dancer's automatic 
serializers, getSomeData() can return a normal Perl data structure that can 
either be consumed directly by the template used in the HTML case or be 
serialized to JSON for consumption on the client side via JS code.

Note the use of code references here to allow the HTML route handler to call 
the JSON route handler.

You can read more about this style of development in a series of articles I 
wrote for the fizzled Dancer 2015 Advent Calendar:

   https://goo.gl/u900Ii

A lesser design principle is that, to the greatest extent practical, you should 
push most of the code into the JSON side to reduce code duplication.  The 
HTML/JS client-side code can also consume JSON, but the JSON API has little use 
for HTML.

To drag this back onto the topic of this particular thread, it is immaterial in 
my view whether the values passed to the Dancer route come from the URL’s query 
parameters, are defined as part of the route, or are passed in via a POST call 
in the request body.  Parameters are parameters, and a properly-written Dancer 
route handler should return the same data regardless of the exact mechanism 
used to pass those parameters.
_______________________________________________
dancer-users mailing list
[email protected]
http://lists.preshweb.co.uk/mailman/listinfo/dancer-users

Reply via email to