Sep 01

I’ve been thinking about what version 2.0 of Mason might look like. It’s been seven years since the last major version (1.10), and a lot has changed in the Perl world since then!

This is an initial brainstorm. Refinement and details to follow, and feedback is very much encouraged.

Name

  • HTML::Mason -> Mason. I believe we are finally entitled to a top-level name. :) This will help separate the new Mason from the old.
  • MasonX:: for extensions? This is more problematic, as the MasonX:: namespace already has a number of modules that are specific to the current Mason. Regardless, it needs to be a short and convenient prefix.

Implementation

  • Moose. We will use Moose for all classes. Moose represents a fundamentally different way of developing Perl, and it was the catalyst that started me thinking about a new Mason. Many of the remaining items in this list fall out of, or are enhanced by, Moosification.
  • Components will be classes. Components started out as subroutines, then became objects. The logical next step is for each component to be its own Moose subclass. This will allow components to benefit from true OO techniques (methods, attributes, roles), instead of Mason’s current painful pseudo-OO.
    • The entire component will be placed inside a MooseX::Declare class block, with a class name auto-generated from the component path.
    • The main component body – the content and the inline Perl sections – will be placed into a main method.
    • Calling a component (via <& &> or $m->comp) will mean creating a new instance of the component class, and calling its main method. Component call parameters will be passed to the constructor. Have to watch for performance impacts here.
    • A $self variable is automatically available, assigned to the component instance.
    • One of <%args> or <%attr> will be used to generate Moose attributes, rather than subroutine parameters. There will still be some syntactic sugar, but the section will have access to the full power of attributes. e.g.
      <%args>
         foo
         bar => (default => 5)
         baz => (default => 5, isa => 'Int')
         </%args>

      The advantage of attributes over parameters is that other methods in the component will have access to those values, something that is painful to deal with right now.

  • Subcomponents will become methods. <%def> and <%method> are currently implemented as their own component objects inside the main component. There was never a particularly good reason to do this other than that it seemed like a neat idea, and over the years it has proved more frustrating than helpful – e.g. $m->current_comp and $m->caller sometimes defy expectation. Now that components will be classes, it makes sense for a subcomponent to be just another method alongside main.
  • Autohandlers will be superclasses. Components will truly inherit from their autohandlers now. e.g. they’ll be able to call methods in the autohandler, a great way to share code within a hierarchy of components.
  • Smaller core, more extensions. As with other modern Perl frameworks, we should move as much as we can from the core to extensions, where we can do so without overly sacrificing ease of use, performance, etc.

Syntax

  • Same core syntax. The core syntax will be mostly the same – <% %> blocks, <%perl> and <%init> sections, %-lines. I do sometimes regret not going with the industry-standard <%= %> for expressions, so that <% %> could be used for non-expression Perl; but at this point <% $foo %> may be too deeply embedded in my brain to change it.
  • <%once> becomes <%class>. The <%class> section will contain code to be placed in the class definition outside the main method: ‘use’ statements, pure-Perl methods, utility subroutines, pragmas etc.
  • Automatic newline removal. Obvious newlines should be removed by default, so that components can be spaced neatly without adding gratuitous newlines to the output.
  • Consolidated filter syntax. Mason has several kinds of content filters: <%filter> section, components with content, and escapes (e.g. |h). All of these filtering methods should be consolidated under a single implementation, if not a single syntax. In addition, we need a way to create new content filters with Perl methods and use them on blocks. Standard filters could be installed on the main component class, and more specific filters on individual components. Example:
  • <%class>
       filter repeat ($times) {
           my ($self, $content) = @_;
           return $content x $times;
       }
       </%class>
    
       ...
    
       <% repeat (3) { %>
       blah blah
       <% } %>

New features

  • More powerful controller mechanisms. Mason has controller mechanisms – dhandler, autohandler, and the resolver – that were innovative once but are now underpowered. I don’t believe (as some do) that Mason should get out of the controller business – I actually like having my “C” and “V” in the same place. Mason just needs to provide easy access to the same powerful routing techniques that are used in modern web frameworks, e.g. via Path::Dispatcher or Path::Router. For example, an autohandler or dhandler or other special file could indicate how paths under that directory should be routed – still have to work out the syntactic details. Of course, nothing will prevent people from using an MVC framework’s routing and treating Mason like a controller-less template language.
  • Logging. Mason will log generously with different levels and categories via Log::Any. This was supposed to be put into Mason 1.x years ago but never made it…
  • Output placeholders. Support the insertion of placeholders whose values can be supplied by code further along in the request. This is motivated by HTML head elements, like title, that you want to output in the top template but determine in a more specific page component.

New extensions

  • MasonX::Tidy and MasonX::Critic. Tidying and criticizing specific to Mason components, analagous to what perltidy and perlcritic do for Perl.
  • MasonX::Safe. Use static code analysis (PPI) to restrict the set of Perl operations that could be executed in a set of Mason components. In the spirit of, but less draconian and broken than, Safe. Useful for environments when non-Perl-programmers are modifying components, or to give the “don’t do too much in components” philosophy some teeth. Intended for friendly policy enforcement, not airtight security.

What can be deprecated/eliminated

  • Web features. Mason has always ambiguously straddled the line between template language and web framework. This was out of necessity — when Mason was created, mod_perl was the only “web framework” in Perl. With the advent of web frameworks like Catalyst, Jifty and CGI::Application, and interfaces like PSGI/Plack, Mason no longer needs to occupy the web space. It should strive to simply be a great templating system that is easy to plug into various web frameworks. This means we can eliminate, among other things, the ApacheHandler and CGIHandler classes from the core.
  • Plugin API. In 1.3 we added a custom Mason plugin API, but Moose method modifiers and roles are a far better and more industry-standard way of supporting plugins.
  • <%cleanup> section. <%cleanup> has always been of dubious value because it is not guaranteed to run in case of an abnormal exit from the component. Now that components are classes, a DESTROY method in the <%class> section will be a more appropriate and functional way to perform cleanup.
  • <%shared> section. Since the various methods in a component are now part of the same class and share attributes, there is no reason to have <%shared>.
  • <%attr> or <%args> section. We only need to retain one of these to represent class attributes; the other can be eliminated.
  • <%method> or <%def> section. Perl methods will now be easy to define in the <%class> section. It will still be useful to define methods that produce output, but we only need one of these sections.
  • Non-CHI cache APIs. Eliminate the Cache::Cache and 1.0 APIs, and just support CHI.

What will be kept, begrudgingly

  • Components returning values. There are some cleanliness arguments for eliminating the ability of components to return values – one should use methods instead, etc. But I think this feature is too frequently used to discard. This is something to discourage in the docs and for MasonX::Critic to complain about. :)

What do you think?

Mason developers, let me hear your feedback and ideas.

28 Responses to “What Mason 2.0 would look like”

  1. Robert Says:

    I think you can use MasonX:: for plugins. You would just have something at the top of the POD like:

    =head1 NAME

    Mason — short description of the new Mason

    =head1 REQUIRES

    This plugin requires Mason2 (or greater) and will not work with ….

    If you don’t like that then nothing wrong with Mason::Plugin::*

    I look very forward to your future postings on this.

  2. Yanick Says:

    Okay, that list got me drooling…

    Big thumbs up for the Moosification. Ditto for the split from the web framework sphere. Nowadays I use Mason as the templating system of my Catalyst apps, so having Mason being more of a pure templating system fits perfectly with that.

  3. Jerome Eteve Says:

    All of this seems great. Does this new ‘true’ OO architecture also implies that components will inherit from other components even if they are not called within the main call chain? It would allow to call $m->comp(‘/foo.mas’ , o => $aPerlObject ); and let foo inherit from what’s needed. This way we could define ‘virtual’ components and specialize them in the same fashion as we do with the model classes.

    Also about this block. I’ve been using it till now to ensure some data is computed in the pnote hash before anything else is rendered on the page by refering to a shared variable in a method which I usually call ‘beforeall’ called in the autohandler before anything else.

    For instance I would have a ‘virtual’ method called ‘title’ in my autohandler containing just ‘generic title’ and I’d define the method ‘title’ with dynamic content in let say my page which display an particular object. So I would write

    /autohandler

    <meta title …

    ….

    /viewo.html:

    my $o = getMyObjectFromId($someId) ;

    $m->pnote(‘contextO’) = $o
    title() %>

    The order of component execution and sharing contextual data between scatered components on the page have always been a bit tricky with mason, although very powerful. For this reason, I’d be quite sad to loose the shared section, unless it’s replaced by something else more convenient than my technique to have the same effect.

    Thanks for sharing your thoughts.
    Let me know if I can help for mason 2.0!

    Jerome.

  4. john Says:

    I’m glad to see this discussion because I do think the Mason approach does meet a type of need (and a type of programmer mind) not met by more lightweight (efficiency wise, not power wise) frameworks like HTML::Template, but who don’t like the mini language approach of Template Toolkit.

    I’d love to see templates built around some of the more interesting Moose ideas, such as Roles, and a more clear inheritance model. Even something like the way Moose makes it easier to adapt and delegate via attributes would have value in my mind.

    Even though I use Catalyst primarily, I don’t think having a view with it’s own dispatch ability is a waste, given how most Catalyst programmers are used to a View that’s more of a View delegate or bridge than anything else (I’m talking about the commonly used and misused Catalyst::View::TT). The Template Declare stuff for Catalyst is a bit better in that regards, since you are actually creating Views. However the need for flexibility in the View warrants the inclusion of some sort of dispatch, although personally I’d love to see something integrated across the board with a tool like Bread::Board, and then you just have all these components spread around and loaded as needed.

    looking forward to seeing some next steps. I’d probably be an early adopter.

  5. Apu Says:

    I have been a fan of Mason since the beginning (partly because of the clarity of thoughts in design and sufficing the requirement at that time). However, I felt the following seems to slow me down time to time.

    1. With autohandler, mungling the outgoing headers becomes tricky when you have multiple javascript pages under header sections.
    2. Never had any issues, but is the Apache::DBI or even the Class::DBI thread safe under mod_perl/Mason environment ?
    3. Cookies and Sessions requires retrofitting from other modules, where I think this could be embedded as one of Mason’s sub classes.
    4. MasonX namespace itself scares me, and I ended up rolling my own extension classes. Perhaps a better suited name which *sounds a bit better?

    Apart from the MVC fad, mason stands out as an independent candidate which allows one to learn little and produce little and/or learn more and produce large. I hope you stay on the same principle.

  6. DarkoP Says:

    I would like to see more syntactic changes. After writing a lot of mason in the last two years, I’d like to see an easier way of mixing Perl with HTML. For example, it would be good if I could put any Perl code between . This little change would also remove the need for ‘% code’ at the begining of line. Personally, I think it would be great if the syntax could be easily extended via MasonX:: plugins opening ways to implement different templating schemes.

    Anyway, I’m looking forward to the new stuff, and to report some bugs (if any) :)

  7. Jonathan Swartz Says:

    Jerome: Yes, components will inherit from other components even if not in the main call chain. Obviously certain things, like template wrapping, only happen in the main call chain.

    As far as < %shared>, I don’t completely understand your example and will want to talk about it further, but I believe everything < %shared> does can be replaced with more traditional OO constructs.

  8. Jonathan Swartz Says:

    Apu: Starting with Mason 2.0 I would expect anyone doing Mason web development to use one of the many fine Perl web frameworks, which would take care cookies, sessions and the like. We’ll have to make sure that integration with the common frameworks requires minimal effort.

    The “X” for extensions is a CPAN standard, used with DBIx and MooseX, for example. It isn’t the prettiest, but its brevity can’t be beat. :)

  9. Jonathan Swartz Says:

    DarkoP: I agree, my main lament with core Mason syntax is not being able to do same-line Perl integration like

    < % if (...) { %> blah blah < % } %>

    One possibility is looking for the { or } at the end or beginning of the < % %> block, and treating that differently.

    Another possibility is finding a single character to follow < % that would mark it as a non-expression. e.g.

    <%: if (...) { %> blah blah < %: } %>

    Ideas welcome. As far as extending the syntax with plugins, hopefully that will come out of rewriting the parser in a modular way with Moose.

  10. Sebastian Willert Says:

    Most of these ideas sound great. I’d really like to spend some of the minimal free time at my hand to help out. Are there any plans for a formal place to dicuss and implement Mason2, e.g. IRC, github, a wiki?

    From the top of my head, here are a few things I’d also like to see in the next Mason:

    - Easy dynamic inheritance and component roots

    - Kill @_ for subcomponents, or at least create a way for a plugin to know if a subcomponent expects @_ or an args hash (I guess this is needed for the next idea)

    - Give Plugins better access to component args, e.g. to allow a plugin that makes the Catalyst stash available to each component

    - multi-line %flags, %args, %attrs sections

    - Better charset support

    Cheers,
    Sebastian

  11. Aran Deltac Says:

    Much like others here, it is great to hear that you’re wanting to push Mason 2.0. We use Mason here at $work as the main templating language under Catalyst. We tried other systems, such as TT, and the Mason code turned out to be the smallest and easiest to maintane. TT was the worse – the templates requires around twice the number of characters to do the same thing.

    Being able to do:

    <% if (…) { %> blah blah <% } %>

    Would be FABULOUS! I am totally willing to change the <% $blah %> syntax to <= $blah > to support the above ability.

    Also, on the thoughts of Mason having a more mature dispatching facility – I am of the mind that even when it comes to dispatching, there is a level of dispatching that belongs in the C, and a level of dispatching that belongs in the V. Having more robust View dispatching would rock!

  12. Aran Deltac Says:

    Hmm, looks like your blog stripped out my < > characters. Here’s what it was meant to say (hopefully this works):

    <% if (…) { %> blah blah <% } %>

    Would be FABULOUS! I am totally willing to change the <% $blah %> syntax to <= $blah > to support the above ability.

    Can you correct my post when you moderate it? Thanks.

  13. sharkey Says:

    jonswar: MasonX::Lexer::MSP changes the mason syntax to make your first example legal.

    It may not be a good idea to create a new instance every time a component is called. Once per request may be better, so you don’t have multiple instances if it is called more than once, and you don’t have to wonder which instance gets the request when you call a method.

    Concerning components returning values, the real disconnect is that sometimes you want the component output to go out, and sometimes you want to capture or filter the output, which creates several ways of calling components (comp, scomp, filtered, etc) and many fiddly rules for dealing with the output correctly, flushing or not, etc. One way to dramatically simplify the situation is to make the rule that:
    Every component returns its output.
    Then there is no need to have comp vs scomp, and filters are simple. The caller determines what happens to the output. would automatically append to this component’s buffer, or you wrap your $m->comp in an $m->print. You could still have a flush method to output and clear current buffers immediately.

    I would also suggest a MaxonX class to manage the html head section. It would have methods to change the title, and to allow any component to put stuff (meta, script, style tags) in the head section, then output it all when the first flush occurs.

  14. Jonathan Swartz Says:

    Sebastian: Haven’t figured out where or how Mason 2 will be planned. Suggestions welcome. Clearly need something that will support many simultaneous discussions, one for each major feature and implementation aspect. What have other projects of similar size used recently?

    Catalyst::View::Mason already makes $c available to all components as a global. Can’t you access the stash via $c->stash?

  15. Jonathan Swartz Says:

    sharkey: The point of creating one instance per component call is so that the component’s own methods can access the attributes for that particular call. I’m more concerned about the performance than the semantics – we’ll have to see.

    I understand your argument about eliminating the output / return-value duality – it would certainly simplify things, especially for newcomers. There are a few reasons I hesitate to do this. First, to maintain some semblance of backward compatibility we have to support components that return values – removing this feature would make Mason 2 a non-starter for some major sites I’ve worked on. Second, having a separate output pipe adds the potential of streaming output as soon as it is printed. But it’s definitely worth thinking about.

  16. Jonathan Swartz Says:

    sharkey: I’ve added “Output placeholder” under New features which I think is what you want for the html head section.

  17. raiph Says:

    Sometimes a great way to explore a field is to start way off to the left of it…

    What about playing with P6 possibilities, then coming back towards Mason?

  18. John Says:

    Has anyone looked at Apache2::ASP? Just curious?

  19. Davidslv Says:

    Hum, i’m worried about this new! Cos i’m starting to learn Mason, and the book is from October 2002. Well, when the changes will come ?

    Thank you

  20. Tudor Marghidanu Says:

    Very glad to hear about all these changes especially about the OO terminology which applies very good on Mason making thing clearer. I’m very enthusiastic about the fact that Mason will no longer use CHI for caching (had some big problems there) and about the controller mechanism.
    Are we going t o see this anytime soon, hope so because it sounds very good!

  21. Jonathan Swartz Says:

    Tudor: You had problems with CHI for caching? Or do you mean Cache::Cache?

  22. Jonathan Swartz Says:

    Davidslv: Not to worry, the changes won’t come for a while, and the previous version of Mason will continue to exist and be supported.

  23. DarkoP Says:

    Regarding syntax changes disscussed above: I implemented simple preprocessing (I’ll probably reimeplent this in Lexer later) so I now have simple keywords like and (I use them alot). I’m not sure it’s the right thing to do, but it works nicely, and the templates (complex HTML form generation) are cleaner now. Here’s the code: http://pastie.org/693463

  24. DarkoP Says:

    Ugh, the keywords are: <%if> and <%for> Hopefully it works now.

  25. Bruce Says:

    Hum, i’m worried about this new! Cos i’m starting to learn Mason, and the book is from October 2002. Well, when the changes will come ?

    Thank you

  26. Andreas Says:

    If I may add the the wishlist:

    I would be cool if Mason 2 was “secure by default”, i.e.

    - Mandatory, easy-to-use input validation (e.g. Params::Validate)
    - Default encoding/escaping (e.g. default_escape_flags).
    - Don’t serve pages/components outside a defined whitelist.
    - Secure out-of-the box authentication and session management.
    - Do not disclose stack trace or source code by default.
    - Promote secure coding standards.

    http://www.owasp.org/index.php/Top_10_2010-Main

  27. Emily Says:

    Davidslv: Not to worry, the changes won’t come for a while, and the previous version of Mason will continue to exist and be supported.

  28. Announcing Mason 2 Says:

    [...] talked about plans for Mason 2 here before, but as things have changed in the past year and a half, here’s an updated [...]

Leave a Reply

preload preload preload