Migrating to Dancer2

A question we often get asked when we promote Dancer2 is "How do I migrate my code to Dancer2?"

There had been some changes between the versions - big enough to require an entirely new namespace. What were they? How do we migrate?

Changing the namespace

The reason we changed the namespace wasn't really due much to the change a user will necessarily see, but more due to the incredible difference in core architecture, and CPAN's inability to maintain two running versions in the same namespace, as mentioned in the previous article.

Dancer2 is actually a complete rewrite. It had small portions of the code moved and some of the documentation was copied over, but mainly it is completely restructured.

It no longer relies on reinventing the wheel as much. Users simply didn't care about installing another module or two or three or even more. At the same time, enough tools we written to still allow you to get away with not being able to install dependencies, so the entire problem became moot.

For example, Having local::lib allows you to install an entire module tree in a local user's directory (not requiring administrative privileges). Having fatpacker allows you to fatpack your entire Dancer2 application in a single file. Having Carton allows you to package it all nicely. Having Pinto allows you to set up an entire personal CPAN for your company. Things are much easier.

(Watch for additional articles that cover fatpacker and Carton in this advent calendar.)

Additionally, we wanted the ability to make core changes without breaking a lot of old applications. This doesn't mean a migration is difficult though. Having two different namespaces allows you to keep your current Dancer 1 applications running alongside your new Dancer2 applications and make it simple to migrate when you are ready.

Following are a few tips for migrating your applications to Dancer2, finishing with one great resource for it at the end.

It's all about the Plack

Dancer originally wasn't built for Plack. When Plack came out, Dancer has made the necessary changes to accommodate it. However, it wasn't the leading spec for Dancer, as it was simply a port of another framework from Ruby.

Dancer2 took a different approach: Plack leads the way. This led to quite a few changes in removing unnecessary code, producing much more correct behavior, and providing more deterministic results.

A few examples:

  • Each class is an entire app

    A Dancer App is now every class which consumes Dancer2. This means they can each have their own configuration, allowing different engines:

    package Admin {
        use Dancer2;
        ...
    }
    
    package Public {
        use Dancer2;
        ...
    }

    Now Admin and Public are fully independent applications. They will not share any resources and will be able to have different engines (template, session, serializer, logger) which will not be shared. No more worrying about globals.

  • Removing ':script' import key for plackup

    Dancer 1 had the :script import key which would read your command line arguments to change how the Dancer server would run.

    Since Plack has the plackup command line tool, it already reads your command line arguments. Why make a duplicate effort?

  • Fully object-oriented

    Dancer2 has changed its core substantially to be much more object oriented. Now the core is implemented in objects. The DSL layer simply provides an interface to those objects.

    This makes everything much easier to compose and test.

  • HTTP::Server::Simple replaced with HTTP::Server::PSGI

    Originally Dancer would use HTTP::Server::Simple which supported PSGI, but it was a pain to use, since it had issues we needed to patch and provided a dependency we weren't happy about.

    As it happens, Plack comes with a great development server called HTTP::Server::PSGI. Since we're building on Plack, we might as well make use of it. This is why Dancer2 uses it instead.

Migration in a nutshell

Okay, but putting all of that aside, how do I migrate?

Well, it really depends on what you do with your application, but here are our main migration tips:

  • Clean importing

    All of the importing keywords are unnecessary now, except for appname, explained below.

  • Separate serialized routes

    Routes that require serializers should be separated to their own Dancer2 app, since serializers will try to deserialize all input and serialize all output in every route in their app scope.

  • DSL keyword changes

    We tried to change very little of the DSL. load and param_array no longer exist, and session can also provide the session object, not just retrieve and set values for keys.

  • Applications are self-dispatching units

    As explained above, any module that uses Dancer2 becomes a Dancer Application, which creates a separated dispatcher only for the routes created under that module namespace.

    The application's engines will not be shared with others - an issue that pained experienced developers of Dancer 1.

    If you want to compose multiple Dancer Applications to create a single web application, you can use Plack::Builder and to_app. Stay tuned for an article explaining this exact situation.

  • Multiple packages for a single app

    Allowing multiple packages to create a single Dancer Application is also possible using the appname feature. This will also appear in an upcoming article.

You said something about a great resource?

Oh yes!

Writing down all the migration changes between Dancer 1 and Dancer2 would be too much. Plus, who would check this article after a while again to see if it was updated? No one, that's who!

Instead, we've compiled a list (with the kind help of Snigdha Dagar) of all of these changes under Dancer2::Manual::Migration.

If you're interested in migrating your applications to Dancer2, or would like to write a new application and care to know what the differences are, you should consult it.

Of course we welcome any changes and improvements to this document as it is a living breathing document (which we hope will not attack us during Halloween), so feel free to submit pull requests, send comments on the mailing list, or stop by the IRC channel.

Conclusion

Dancer2 has a few changes that promote much more consistent and deterministic web application development. It reduces the considerations we have to take into account while providing much more correct implementations for various pieces.

Our new Migration Document helps new-comers and seasoned developers keep up-to-date with the changes we've done and how it might affect their future code.

Author

This article has been written by Sawyer X and Mickey Nasriachi for the Perl Dancer Advent Calendar 2014.

Copyright

No copyright retained. Enjoy.

2014 // Sawyer X <xsawyerx@cpan.org>