Dancer Advent Calendar 2014 Past and future perl Wed, 24 Dec 2014 00:00:00 -0000 <div class="pod-document"><h1><a name="past_and_future"></a>Past and future</h1> <p>This last article is meant to reflect on the past, in the present, and speculate about the future, perhaps even - with the cover of darkness - offer some future plans, in quiet murmur, of course. :)</p> <h2><a name="popularity"></a>Popularity</h2> <p>We all care about popularity. Popularity isn't just cool factor, it's also a measurement of success - doing well, going in the right direction.</p> <p>But how do you measure popularity? It's <a href="">hard</a>.</p> <p>We have different mechanisms made just to measure success. In our world that would Github stars, Github watchers, and even MetaCPAN votes. However, if you take a look at Moose, it only has 78 stars on Github, and only 15 watchers. Would you say Moose is less successful than Dancer? Not at all. This measurement simply is far from accurate.</p> <p>However, there is another way to measure popularity.</p> <p>One of my favorite and most respected authors provides the following comment in all of his projects:</p> <p><i>All complex software has bugs lurking in it, and this module is no exception. If you find a bug please either email me, or add the bug to cpan-RT.</i></p> <p>Complex software accumulates tickets. These are bugs, feature requests, failing tests, missing tests, questions, and so on. Hopefully authors will collect these in a ticket system like RT or Github.</p> <p>The amount of tickets you have indicates how many of these came up. While some authors will open a staggering amount of tickets for their projects (which is nothing short of being thorough and responsible) and projects may have a devoted user who opens tickets upon tickets, most tickets are opened by the audience of users. The number indicates how many have used your software to a degree of contacting you, providing input, and found you or your project approachable and tried to help improve it.</p> <p>You can count the number of tickets for a project, remove the core authors (and check for when they weren't core authors yet - it happens sometimes), normalize to amount of users opening the issues, and look at the numbers.</p> <p>Dancer has two main repositories: Dancer 1 and Dancer 2. Together they have accumulated around 1,900 tickets. Yes, that's close to <b>two thousand</b> tickets. About 1,000 of them are pull requests. Yes, that's right. Over <b>one thousand</b> pull requests. Actually, my numbers are off. I only took into account Github. Dancer has been running on RT earlier and there's a quite a few there as well. That would also be off, because we accept tickets through any medium. We get them in personal emails, on the mailing list, at conferences, on IRC, and so on.</p> <p>Beyond all measurements, I'd say we reached people. More importantly, I would say these people reached us. I cannot be more proud of this achievement.</p> <p>I can talk about <a href="">Booking</a> using Dancer. I can talk about <a href="">Shutterstock</a> using Dancer. I can talk about <a href="">MoonFruit</a>, <a href="">UK2</a>, <a href="">Tilt</a>, <a href="">FinanceJobs</a>, <a href="">PerlMaven</a>, <a href="">Geekuni</a>, the <a href="">Strehler CMS</a>, and even a <a href="">spiritual church</a> and an <a href="">anarchist library</a> using Dancer.</p> <p>I can talk about all of these, but that's not the great part. The great part is our contributors.</p> <h2><a name="contribution_is_key"></a>Contribution is key</h2> <p>Having someone contributing their time and skill is priceless. Contributors are the life-force of a project - not the core developers. Almost any core developer in Free and Open Source will undoubtedly tell you that development's gratitude is someone using it, thanking you for it, or better yet, improving it further by contributing something - a test, a documentation patch, or even opening tickets.</p> <p>Except for Dancer's founder, Alexis (<i>@sukria</i>) Sukrieh, all Dancer core developers started as contributors. This includes yours truly and everyone else in the team. This hasn't changed since. We always saw and see ourselves simply as contributors with more responsibility.</p> <p>Dancer has enjoyed the help of an astonishing amount of contributors. Overall, the Dancer project has received contributions from over 270 people. While this seems big it fails to account for many contributors and many forms of contribution. It's merely the number of recognized code committers.</p> <p>Sam Batschelet organized the Dancer conference, Gabor Szabo took the Dancer website under his care, Peter Martini provided a Dancer Docker image, David Dick packages the project for Fedora, Paul Cochrane is working on improving the documentation for beginners, and there are numerous other examples for tremendous work done by the community.</p> <p>Let me take a moment to thank you all for the work you've done and the work that you do, in the community and for the community.</p> <p>So now, where is all of this heading?</p> <h2><a name="what_the_future_holds___"></a>What the future holds...</h2> <p>It's hard to say what the future holds for Dancer, but we do have quite a few plans.</p> <p>The short list contains:</p> <ul> <li><a name="item_Thorough_documentation_overhaul"></a><b>Thorough documentation overhaul</b> </li> <li><a name="item_Improve_the_plugin_system_for_Dancer2"></a><b>Improve the plugin system for Dancer2</b> </li> <li><a name="item_Port_all_useful_plugins_to_Dancer2"></a><b>Port all useful plugins to Dancer2</b> </li> <li><a name="item_Rewrite_fair_portions_of_the_testing_suite"></a><b>Rewrite fair portions of the testing suite</b> </li> <li><a name="item_Many_core_cleanups"></a><b>Many core cleanups</b> </li> <li><a name="item_Additional_functionality"></a><b>Additional functionality</b> </li> <li><a name="item_Speed_optimizations"></a><b>Speed optimizations</b> </li> <li><a name="item_Compatibility_shims"></a><b>Compatibility shims</b> </li> <li><a name="item_Code_linting"></a><b>Code linting</b> </li> </ul> <p>We even have some idea regarding features we want to introduce:</p> <ul> <li><a name="item_Full_asynchronous_support"></a><b>Full asynchronous support</b> </li> <li><a name="item_Route_naming"></a><b>Route naming</b> </li> <li><a name="item_Chained_hooks"></a><b>Chained hooks</b> </li> <li><a name="item_Stronger_command_line_tooling"></a><b>Stronger command line tooling</b> </li> <li><a name="item_More_decoupling_of_components"></a><b>More decoupling of components</b> </li> </ul> <p>As you can see, there are plenty of ideas and the opportunities are abound.</p> <p>While we want to add some of these features as quickly as possible, we need to make sure we get them right, that we design them well, that we do not overlap with other features, and that we don't have to revert them.</p> <p>In fact, what we need is your help.</p> <p>I can promise some will be difficult to implement, some will take considerable time, and some will be like trudging through mud (especially any OS compatibility work), but above all, I can promise you will have a good time. :)</p> <p>I would like to thank everyone for an amazing year. I hope to see you and work with you this new year and provide you all with another set of articles at the next Advent Calendar.</p> <p>Have a merry Christmas, a wonderful Hanukkah, and a tremendous Festivus, for the rest of us!</p> <h2><a name="author"></a>Author</h2> <p>This article has been written by Sawyer X for the Perl Dancer Advent Calendar 2014.</p> <h2><a name="copyright"></a>Copyright</h2> <p>No copyright retained. Enjoy.</p> <p>2014 // Sawyer X <code>&lt;;</code></p> </div> Dynamic routing in Dancer is dynamic perl Tue, 23 Dec 2014 00:00:00 -0000 <div class="pod-document"><h1><a name="dynamic_routing_in_dancer_is_dynamic"></a>Dynamic routing in Dancer is dynamic</h1> <p>Dancer provides with a number of ways to do dynamic routing, A.K.A., chained actions. Let's take a look at situations that lead to such a requirement and how to achieve it.</p> <h2><a name="the_use_case"></a>The use-case</h2> <p>Let's say you were building a message board that supported any number of boards - each with a custom URL. For example, if this were something for a Beethoven fan site you might have a board for discussing each genre of work composed by him, with URLs like:</p> <ul> <li><a name="item_http___www_beethovenfans_com_string_quartets_"></a><b></b> </li> <li><a name="item_http___www_beethovenfans_com_symphonies_"></a><b></b> </li> <li><a name="item_http___www_beethovenfans_com_piano_sonatas_"></a><b></b> </li> </ul> <p>Visiting the top-level board url would show you a list of all posts under that board. You could start a discussion by simply using <i>/new-post</i> under the board name. So to start a discussion under string-quartets, you'd go to:</p> <pre class="prettyprint"></pre> <p>Similarly, you could view or permalink to a specific post as:</p> <pre class="prettyprint"></pre> <p>Where <i>opus-18-no-6</i> is the unique identifier of the post - possibly generated from the title of the post.</p> <p>Similarly, to upvote a post on the board:</p> <pre class="prettyprint"></pre> <p>Each time someone accesses one of these URLs, you first need to check if the discussion board exists. To put it in code:</p> <pre class="prettyprint">get '/:board' =&gt; sub { my $board = param('board'); # validation code for $board ... }; get '/:board/new-post' =&gt; sub { my $board = param('board'); # validation code for $board }; get '/:board/opus-18-no-6/upvote' =&gt; sub { my $board = param('board'); # validation code for $board };</pre> <p>Each of these handlers have to start by validating the existence of a discussion board before they do anything else. It makes sense to have the discussion board validation logic in one place.</p> <h2><a name="setup_method"></a>Setup method</h2> <p>One way to do this is by defining a special setup method which you call when the application starts up. This method can use the <b><code>prefix</code></b> keyword to set up routes for each board.</p> <pre class="prettyprint">sub get_boards { # in a real life application this would come from a # database. for the sake of simplicity, we simply return # a hard-coded list return qw(string-quartets symphonies piano-sonatas piano-trios); } sub setup_routes { my @boards = get_boards; foreach my $board (@boards) { prefix "/$board" =&gt; sub { # any variables here will be accessible to the handlers # defined below my $welcome_message = "Welcome to the group for discussing: $board"; get '/' =&gt; sub { # show a list of all the posts under the board $board # for demo's sake simply return the welcome message return $welcome_message; }; get '/:post_id' =&gt; sub { # do the work here or delegate to a specialised class my $post_id = param('post_id'); # check if the ID is valid and do something with it # for demo's sake show variables you have access to: return "I was called with board: $board, post id: $post_id" . " and have access to the welcome_message variable: $welcome_message"; }; }; } }</pre> <p>Then in your</p> <pre class="prettyprint">#!/usr/bin/env perl use FindBin; use lib "$FindBin::Bin/../lib"; use beethoven; beethoven-&gt;setup_routes; beethoven-&gt;to_app;</pre> <p>Calling setup_routes essentially materialises the routes beforehand based on what <code>get_boards</code> returns. If the user enters a board that doesn't exist, it will automatically get picked up by Dancer's default handling of missing routes and a 404 error will be returned to the user.</p> <p>This approach works well if the number of boards is small. Say in hundreds, or may be in thousands, but not in hundreds of thousands. After a certain point the Dancer process will grow too big in memory. That might or might not be a problem depending on your infrastructure.</p> <p>Also if boards are not fixed and are created all the time then this approach will not work very well as it would required an app restart to pick up all the new boards (or for that matter changes to the URL slugs for the existing boards, or deletions).</p> <h2><a name="the_hook"></a>The hook</h2> <p>There is another way that allows us to dynamically check for a board rather than materialising all our routes up front. The basic idea is to combine <b><code>prefix</code></b> with a <b><code>before</code></b> handler. Let's put together some code to illustrate this idea:</p> <pre class="prettyprint">hook before =&gt; sub { my $board = param('board'); if ($board &amp;&amp; board_is_valid($board)) { var board =&gt; $board; } }; prefix '/:board' =&gt; sub { get '/' =&gt; sub { # show a list of all the posts under the board $board # for demo's sake simply return the welcome message my $board = var('board') or pass; my $welcome_message = "Welcome to the group for discussing: $board"; return $welcome_message; }; get '/:post_id' =&gt; sub { my $board = var('board') or pass; # do the work here my $post_id = param('post_id'); # check if the ID is valid and do something with it # for demo's sake show variables you have access to: return "I was called with board: $board, post id: $post_id"; }; }; sub board_is_valid { my $board = shift; return if not defined $board; # in a real life application we would check this against a table in # a database or through a backend service. for the sake of # simplicity, let's just check against a hardcoded list my %valid_boards = map { $_ =&gt; 1 } qw(string-quartets symphonies piano-sonatas piano-trios); return defined $valid_boards{$board}; }</pre> <p>This time, our <code>before</code> handler will catch the request first. It sets up the <code>board</code> variable using <b><code>var</code></b> that is automatically passed around to each handler. The handler first checks if the <code>board</code> variable exists and if it doesn't, it simply defers the handling to the Dancer's default route handling. Since no other routes to handle the <code>:board</code> exist, this results in a 404.</p> <p>While it alleviates the need to build all possible routes up front, the one downside to this approach is having to check for the presence of <code>board</code> variable in each handler. On the positive side, you can dynamically add boards without restarting the application for them to be available.</p> <h2><a name="even_more_ways"></a>Even more ways</h2> <p>Additional approaches for the dynamic route handling problem exist. Most notably, another approach was recently documented by Yanick Champoux uses <a href="">megasplat</a> to produce <a href="">chained actions</a>.</p> <h2><a name="minimum_version"></a>Minimum version</h2> <p>This article requires <a href="">Dancer2</a> version 0.159000.</p> <p><i>(hopefully released soon enough.)</i></p> <h2><a name="conclusion"></a>Conclusion</h2> <p>Dancer has many methods of producing dynamic routes (or "chained actions") and each of them has its benefits and drawbacks.</p> <h2><a name="author"></a>Author</h2> <p>This article has been written by Deepak Gulati for the Perl Dancer Advent Calendar 2014.</p> <h2><a name="copyright"></a>Copyright</h2> <p>Creative Commons Deepak Gulati 2014.</p> </div> The Dancer community policy perl Mon, 22 Dec 2014 00:00:00 -0000 <div class="pod-document"><h1><a name="the_dancer_community_policy"></a>The Dancer community policy</h1> <p>In October 2014 we have introduced our Dancer core and community policy and our Standards of Conduct. You can find them at <a href="">Dancer::Policy</a> or <a href="">Dancer2::Policy</a> (identical documents).</p> <p>While the Dancer community has always pride itself of the warm feeling members have received, helpfulness and kindness were abundant, we still found it necessary to introduce a policy document.</p> <h2><a name="why_do_we_need_it"></a>Why do we need it?</h2> <p>While the policy is not an answer to a situation in the Dancer community, it is to behavior we've seen in other communities in and out of the tech industry.</p> <p>There are people who are not only discriminated against, but also marginalized daily. There are people who feel pushed out of the way, made small and insignificant, and dis-empowered by others who tend to have a more favorable starting point - what is usually referred to as "privileged".</p> <p>We felt it is absolutely crucial to provide a document that makes it absolutely clear, without a shadow of a doubt, that the Dancer community is maintained and owned by its members - all having a fair and equal stance in it. It is essential that everyone in the community feel and understand this space belongs to them just as much as it does to anyone else.</p> <h2><a name="introducing_a_problem_where_none_exists"></a>Introducing a problem where none exists?</h2> <p>So, are we really just fixing a situation that is not broken? If all is fine and well in the Dancer community, why provide such standards of conduct? That's a good question.</p> <p>Standards of conduct have multiple purposes:</p> <ul> <li><a name="item_Set_expectations_of_behavior"></a><b>Set expectations of behavior</b> <p>It is important that people in the community are aware of both what is expected from them (such as "you are expected to not be abusive towards anyone") and what they can expect from others (such as "you can expect not to be abused by anyone"). Setting these expectations allows people to let their guard down, enjoy their time, approach others, and be an active member without fearing abuse.</p> <p>The community, above all, should be a <b>safe space</b> for all of its members.</p> </li> <li><a name="item_Provide_a_stern_warning"></a><b>Provide a stern warning</b> <p>The document clearly explains that not only do we have expectations, but we will take measures against those who violate them. This helps defend the expectations we described above.</p> <p>If you will violate those standards, we will make sure you are held accountable. This makes sure these are not empty promises and that they won't be perceived as such.</p> </li> <li><a name="item_Enforcement_transparency"></a><b>Enforcement transparency</b> <p>While we provide these standards and a promise to enforce them, it is also important to provide transparency. You need to know <i>what</i> will be done and <i>how</i> decisions will be made.</p> </li> </ul> <h2><a name="can_i_still_be_me"></a>Can I still be me?</h2> <p>Many people worry that with a standards of conduct policy they will not be able to be themselves anymore. This is worth addressing.</p> <p>The standards of conduct clearly stipulate you may not, under any circumstance, be abusive to others. If violating that robs you of your being, it means you are an abusive person - a person we hope other community members will not have to experience or deal with.</p> <p>This, however, is not the same as "I will need to watch what I say". Having to make an effort to be kinder, more composed, or in general more respectful, is an understood effort. It is an effort we make every day. We make sure we're more respectful towards our friends, colleagues, peers, and we make sure we curse much less around our parents.</p> <p>While it is not always a simple task to work on our behavior, it is far different than violating your core principles.</p> <p>In short, if your core principles are to hurt others, and you feel like our standards of conduct negate that, we've done a good job.</p> <h2><a name="conclusion"></a>Conclusion</h2> <p>The community is maintained by the community members. Each and every single member should be regarded with respect, and we should all feel a sense of belonging to and in our community.</p> <p>The Dancer standards of conduct have been introduced to make sure new members understand this and know what we each expect from each other.</p> <p>We were thrilled with getting such positive results from a community