Thursday, December 23, 2010

Images inheritance in Plack based apps

My plan for Nblog is to let users customize it by subclassing and overloading, in the screencast I showed how to do that with controllers and templates, in the latest revision of Nblog I added the possibility of overloading images. There are Plack components for all parts of this task - but I had a bit of struggle with getting the settings right. Maybe the following code snippet will spare similar time waste for someone?



Some explanations: psgi_callback is the method in WebNano that constructs the anonymous subroutine required by the PSGI standard and here I use the around Moose method modifier for it to add some additional processing there. static_roots returns a list of directories where to search for the static files - this is our search path - the first file found in these directories is served. In the base class this list contains only 'static' - if you want to overload the static files in a subclass you need to add your directories before this one, in my example subclass config I have:

static_root => [ 'static', '../Nblog/static' ]

(these are relative paths). See also Plack::App::Cascade. All of this would be a bit easier to assemble if the Plack components logged some debug info to STDOUT, like what you can find in the standard Apache logs about files not found, when run in development environment. I am volunteering to write a patch if there is a green light from the core devs.

Monday, December 20, 2010

Unit Testing

With one functional/system test you can test lot's of low level parts that in Unit Testing would require a separate test each. It is also easier to write - because you only need to test how the module/library is used and using it should be easy (and not require mocking etc) - otherwise the library would not be a good library to start with. And what are the reasons to do unit testing? Personally I was never convinced by the arguments until I started reading Misko Hevery - here is for example is the single best explanation of why to do unit testing I've ever seen:

Lets say you would like to test a car, which you are in the process of designing, would you test is by driving it around and making modifications to it, or would you prove your design by testing each component separately? I think that testing all of the corner cases by driving the car around is very difficult, yes if the car drives you know that a lot of things must work (engine, transmission, electronics, etc), but if it does not work you have no idea where to look. However, there are some things which you will have very hard time reproducing in this end-to-end test. For example, it will be very hard for you to see if the car will be able to start in the extreme cold of the north pole, or if the engine will not overheat going full throttle up a sand dune in Sahara. I propose we take the engine out and simulate the load on it in a laboratory.

from It is not about writing tests, its about writing stories

In the rest of his writings you'll also find how to structure your code in a way that makes unit testing easy and does not require crazy mockings. I am also convinced that code structured in that way is well decoupled and easy to understand, modify and talk about.

Friday, December 17, 2010

Experiments in Inheritance - a screencast

This is a short screencast I made to replace the video made at my London Perl Workshop presentation. It did not make the list eventually - but I still think it might be interesting: http://warszawa.pm.org/WebNanoInheritance.mpeg. It is my first screencast ever made - please comment.

The main idea presented there is about solving the "give mi an application like this one but ..." problem, illustrated by making a blog engine that inherits from Nblog, but extends it and overrides some of it's elements.

Monday, December 13, 2010

Namespace Matching

The other day I was reading the Dancer Advent Calendar and I finally found the two words description of what WebNano does. WebNano is the minimal addition to PSGI that provides Namespace Matching. Beside easy deployment, which is currently covered by Plack, Namespace Matching is probably the main feature of Catalyst and now with WebNano you can have that without the heavy baggage of the whole of the Catalyst framework. I think it is important because it seems to produce just the right granularity of the controller classes and provides a path for the application growth (without overloading one file with too much stuff).

Sunday, December 05, 2010

WebNano - some incompatible API changes ahead

I tried carefully not to document some things that are likely to change in the closest WebNano releases, but the example code I put in the docs needs to be exact and that means it contains some details I have not yet decided are stable. One of these examples is about overriding the local_dispatch. It used to take the path as a string parameter - now it takes an array - i.e. the path split on the '/' character. The past way was more universal as it let the user programmer to specify how to parse the path - but I think splitting on '/' is such a common usage that it justifies the change. And it is not destructive - so if someone really want's to parse the path in a different way then he can join it back.

This change will be in the next WebNano release.

In the longer perspective I am thinking about being more compliant with the Law of Demeter and building the controllers with the needed model parts in their own attributes, instead of accessing them through app. So for example some code in Nblog would change from

$self->app->schema->resultset( 'Article' )->search
to
$self->article_rs->search

Now this can be done by overriding the handle class method - but maybe it needs something more elegant.

Wednesday, December 01, 2010

WebNano as Catalyst::Tiny

If you have read The Philosophy of WebNano you might think that WebNano is radically different from Catalyst, the more so if you'd compare the size of these projects (sloccount reports over 5000 lines in lib for Catalyst, versus less then 250 for WebNano). But if you compare the code structure between Nblog and the original RavLog project you'll find it very similar. The DBIC schema and form classes were just copied around, you'll see mostly the same controllers with mostly the same methods.

Look for example at Nblog::Controller::Ajax and RavLog::Controller::Ajax - the changes are minimal, mostly just changing sub check_articles : Local to sub check_articles_action and accessing the model from $c->model('DB::Tag')->search to $self->app->schema->resultset( 'Tag')->search - a bit longer perhaps. Sure there are other controllers like: RavLog::Controller::View that I renamed to Nblog::Controller::Article. This renaming is not important - I just did not like a controller called View but there is also some difference in their methods. The RavLog controller uses the Chained Catalyst dispatcher - while in the Nblog one I overrode local_dispatch, and it uses stash to communicate with the template while in Nblog I passe the data directly as a parameter. Still some similarity remains.

WebNano uses some dependencies - so it does not fit into the original Adam's definition of tiny modules (by the way I cannot fin this definition now - maybe this should go to some semi-official place like the p5p wiki?). But the prerequisites are really minimal - and mostly tiny themselves. Maybe in the subject space of web frameworks this should be allowed?

Monday, November 15, 2010

Old code and survivor bias

If code is well designed, decoupled and has good test coverage there are chances that it will be regularly updated to new technologies and new programming techniques. The other code will probably scare programmers and have much chance to stay in it's sad state until decommission.

Saturday, November 06, 2010

Templates

I've heard that Perl is ugly because of all those pesky '$'. Purely esthetically this might be true, depending on the font used, but I have the impression that people use the word 'ugly' in a more metaphorical way, like 'ugly subroutine'. Somehow they believe that using an otherwise unused character for marking variables is inelegant - but I think they are confused, I think their opposition arises from the kneejerk reaction to an unfamiliar character. For me the '$' signs make parsing and understanding Perl code easier.

I've heard that TT2 code is ugly because it uses '[%' instead of the more familiar '<', and that it 'FOR' is a heavy burden for the eyes of the programmer because it is "shouting" at him, but I think that the features that make TT2 code standout in the text being templated make it easier to parse and understand and they help my eyes in their work.

Beside that purely ergonomical argument I don't see any purpose of the mini language and I think I am not that thrilled by the future direction of TT.

Wednesday, October 20, 2010

WebNano

In the weekend I published WebNano to CPAN. There is some documentation there - so it is ready for experimenting. I am thinking about a "Why WebNano" article. For now let me just say this: WebNano has just 232 lines of code in 'lib' (as reported by sloccount) and beside Plack it uses only minimal dependencies, but when porting a non-trivial blog engine from Catalyst to WebNano I did not miss any Catalyst features. To be honest in that conversion I did use two WebNano extensions (both also already published), Template Toolkit renderer with dynamic paths and a CRUD controller, but even including them the line count would not excede 500.

Monday, October 18, 2010

Extending the 'Template Method' design pattern

There is this notion that you should not put semantics into names, or maybe that what your program do should not change in alpha-conversion. But of course everyone is breaking that rule if she is using the Template Method design pattern (if we agree that the library they use is somehow outside of the program and is not alpha-converted together with it). There the names of methods have a lot of semantics.

In Advanced Search in web DBIx::Class based applications I proposed an extension to DBIx::Class that would treat all methods with names search_for_* as predicate builders. This way programmers could easily extend the query language used by DBIx::Class with new predicates by adding methods to the ResultSet class. Now in WebNano all *_action controller methods also have a special meaning - these are the methods that can be called from outside via automatic dispatching from an url. Taken literally sub my_method_action is not that different from sub my_method : Action which is the way to specify that in Catalyst. The difference is only ' : A' versus '_a' (and I could use *_Action if I wanted to golf it even more) - but yeah - I am cramming the semantics into the name while Catalyst reserves it for the code attributes. Catalyst way is cleaner - but my goal was a 'minimal' framework. The 'Extended Template Method' design works in a few lines while MooseX-MethodAttributes is 13 packages with who knows how many lines of very subtle code.

What surprises me is that I have never seen a description of this 'Extended Template Method' design pattern. It looks rather obvious, maybe it is called by some other name in the literature.

Tuesday, October 12, 2010

Inviting non-Perlers to speak at Perl conferences

There is an organized effort, by the Perl volunteer marketers, to attend non-Perl events and communicate about the all new things happening in the otherwise insulated Perl word. I wish this effort all the best, and I hope that The Perl Foundation will find a way to support it. To enforce the effect I would like to see also the symmetric and complementary action of inviting non-Perlers to our conferences. I am sure that is already happening to some extent - but personally I have not yet seen it - so I conclude that this extent is not enough.

Whom, from non-Perl speakers, would you like to hear at your next Perl conference?

Thursday, September 30, 2010

Value Objects - some notes

There is a controversy - or maybe a fuzzy consensus about what you should be able to do in templates. Some template engines, like Template Tookit, let you call subroutines and methods on stuff passed to the template. This is very useful - you don't need to care about turning the data into a specially formed hash that can be iterated by the template, you just pass the data there and can be sure that it can display it. But it can also be abused. I think everyone would agree that template should not for example change the data in the database, but where is exactly the limit is not clear. Value Objects seem to be a good answer, templates should work only with Value Objects.

The question is how sharply you can divide your objects into Value Objects and Service Objects. In ActiveRecord is hard to test Hevery proposes a design where the record in Active Record is a Value Object (newable in his terminology is a synonym) with no link to the repository object which would do all the database manipulation. This would work for normal attributes - you'd assign the value there on object creation - but what about relations? $user->books is very convenient, especially in templates, and it can be pure - if you know that you need the books on the user you could put them there when creating the user object. But then you'd have two kinds of objects - those with books, needed in some places - and those without, when you want to spare the additional database calls. Maybe we need subclasses of User? But then we'd need subclasses for all possible combinations of relations (users with books, users with friends, users with books and friends, ...), not to mention the mess with relations on the related objects.

Sunday, September 26, 2010

Another argument for immutable objects

Class is like a little program, it has data, it has code, it can be instantiated - like a program can be run. From the perspective of the object it's attributes are global. There can also be other variables - like parameters passed to the methods or other block scoped variables - those are local, but attributes are global. If they are immutable - they are like programs constants, but when they are changeable - they are like global variables. And we know that global variables are bad.

Saturday, September 25, 2010

Managing Object Lifetime

This is the title of a blog post by Misko Hevery. There are also lot's of other materials authored by him freely available on the net. I have just started exploring them, and there is a lot of repetition if you just google around like me - but I already want to recommend it to anyone working on improving the design of their programs.

WebNano does not (yet?) meet all the design criteria he is talking about - but he is putting into words many of the foggy intuitions that made me not satisfied with all of the existing Perl web framework and write yet another one.

Thursday, September 23, 2010

Inheritance and rapid prototyping

There is much talk about the dangers of too much inheritance and how composition is better then inheritance - and probably they are right if we are talking about the final product. What they don't account for are the dynamics of the development - where you grab the first thing that does something similar to what you need and you start testing it, changing it, evaluating your ideas. Inheritance allows you to do exactly that - making changes to something that was already finished and working somewhere else. With procedural code this is not possible, the most similar thing you can get there are examples.

In other words Inheritance might lead to tightly coupled code, with intricate execution paths, but at least it is an easy way to get something working quickly. You can refactor it later.

Thursday, September 16, 2010

Installing Dist::Zilla plugins

Dear lazyweb - when I try out a distribution converted to DistZilla I often discover that I don't have all the plugins used there. Starting the work then consists of a string of 'dzil build' commands, searching the monstrous error stacks for the name of the missing plugin and then running cpan with it. Sure that should be automated!

And, by the way, it could also install the distribution's prerequisites.

Update: Repeating one of the comments - apparently the latest Dist::Zilla supports following solution dzil authordeps | cpanm.

Saturday, August 14, 2010

Object::Tiny:RW and MooseX::NonMoose

There are conflicting requirements for WebNano. On one hand I would like to build big heavy web applications based on it, and of course I would like to use Moose as the object framework for them. On the other hand I would like to give it a chance to work in the restricted environments of most shared web hosting serving CGI scripts - so heavy dependencies and XS and big startup times are out. And I would also like to make it suitable for serving huge amounts of simple Ajax requests - so it needs to be fast.

First I tried using Any::Moose and let people decide if they used Moose or Mouse. By using Mouse people could solve the startup problem and also there is some way to use Mouse without XS.

But Mouse was still huge dependency - so next I asked myself it it would be possible to subclass in Moose a non Moose base classes. That proved to be rather simple with the aptly named MooseX::NonMoose. Using it in WebNano I can build my objects in what ever way I choose and as long as I stick to the standard hash based objects I can extend the WebNano classes in my Moose based applications with no problems. Or at least it seems to be with no problems for me now - if someone knows more about disadvantages of this solution - please leave a comment.

After discovering MooseX::NonMoose I switched to use Class::XSAccessor. It small and very fast, but unfortunately it was XS based. I was thinking about the possibilities of bundling the software as a PAR package or so and using it in the restricted shared hosting environments and relying on a C compiler seemed to complicate things a lot.

Next I tried Object::Tiny, it was tiny, fast and did not use XS, there was just one but - it did not produce the attribute setters. I could live with that and it did not take much time for me to port WebNano to use Object::Tiny, but still it seemed like an extreme choice. Fortunately just browsing CPAN I discovered a fork of O::T - Object::Tiny::RW - this one is small, fast, does not use XS and does produce attribute setters. I am still a bit worry about why Adam would not add that feature to his module - given that it is such a trivial change (compare the sources of Object::Tiny::RW and Object::Tiny - its just one line changed), he must have had a good reason for that?

Saturday, August 07, 2010

RavLog - a perl blog engine

For testing HTML::FormHandler Gerda Shank wrote RavLog. Recently I've made a fork of it, switched to SQLite as the main db engine and made it easy to install. It still does not pass all formatting tests (HTML::Tidy seems to be uninstallable) - but it is usable. My goal is to make another fork out of it and port at least part of it to WebNano, but I think that what is now there can also be interesting for someone looking for a Catalyst based weblog engine.

Friday, July 09, 2010

Technically right, socially not so

Imagine that you let anyone use your hard work by publishing your code as Open Source and then instead of thank you notes you receive angry emails about purported bugs in it.

Imagine that you noticed a problem about some Open Source code and as a good citizen you analyze it and report your findings and instead of a thank you note you receive a reply explaining how much confused you are for thinking that that could be a bug.

Imagine that this happens in a public space like an mailing list, open bug tracker, etc. This is like the setting of a Greek tragedy - both sides have their own rights and values, both sides can be technically right - and yet the conflict spreads and escalates. People copy the emotions of each other, even perceived emotions and especially anger, when displayed publicly leads to more anger. This is a vicious circle of positive feedback loop. When it starts everyone gets irritated and everyone wants to know who started it, who is responsible for that.

But go back to the start - it's not anyone's fault - you cannot point the finger on one person and say 'he is responsible'. Looking for the main culprit is really looking for a scapegoat - a surrogate victim that would heal everyone's consciousness. This is not especially geek thing overall - it is a universal trait - but sadly inventing fodder for the scapegoat search is a prominent part of geek culture.

One of the many things that I admire about Larry Wall is how he can neutralize the poisons of angry reactions. People scorn Perl for being a 'scripting' language - he talks about Ada Lovelace:

Suppose you went back to Ada Lovelace and asked her the difference between a script and a program. She'd probably look at you funny, then say something like: Well, a script is what you give the actors, but a program is what you give the audience. That Ada was one sharp lady...

Wednesday, July 07, 2010

Installing dependencies - continued

I don't know what I am doing wrong - but after installing Perl 5.12.1 under perlbrew "cpan -m ." stopped to install the dependencies. It seems that for making and testing it adds the libs in '.cpan/build' to the PERL5LIB search path so both can go on without really installing the dependencies:

Running make for /home/zby/progs/ravlog/.
Prepending blib/arch and blib/lib of 108 build dirs to PERL5LIB; for 'get'

"cpan -t . " works in the same way and if the tests fail then "cpan ." stops there - so I cannot tell if it would install the dependencies in the case when the tests pass.

I don't really know how to investigate it further - but I am noting that as it is very frustrating. Eventually I had to resort to cpanminus ("cpanm --installdeps ." is really handy as it addresses the problem directly).

Thursday, June 24, 2010

Implementing file upload progress bar

At work I was assigned the task of replacing the previous hodgepodge of tools that provide the progress bar functionality for forms with file uploads. At first glance this seems like a trivial thing to do - you periodically observe how much of the file you've got and update the progress bar, but there are details that make it hard to do with the current tools. I report here how I solved that problem - not because I think this is the optimal way - but rather to open the discussion and because I could not find any description of solving it when I googled for it.

First of all the common programming tools (like CGI.pm or Mason that we use here) assume that the page handler receives the whole request as input - and that whole request is not available until after the file is uploaded. So for example 'my $q = CGI.pm->new' will not finish until it is too late to measure the upload progress. The solution to that is to use another page to report the upload progress and call that page via Ajax from Javascript code updating the progress bar. This would work great - but the file is normally uploaded to a temporary file with a random name and the other script would not have any chance to guess it. We need to generate a new random file name in the form page and then pass that name to the form handler script so that it would save the data to that file, and in parallel to the Ajax scripts that would check the size of that file.


To save the data into a specified filename I used the CGI.pm callback feature:

my $q = CGI->new( \&hook, $fh, undef );
...
sub hook {
my ($filename, $buffer, $bytes_read, $fh) = @_;
print $fh substr($buffer, 0, $bytes_read);
$fh->flush();
}

It is described in the subsection called "Progress bars for file uploads and avoiding temp files" of the CGI.pm documentaion, but actually it is a great leap of thought to say that it supports progress bar implementation, you still cannot use it directly to get the progress bar from the CGI object on the form landing page, you still need the separate scripts measuring the progress. For my solution all I needed was to pass the target file name to the code saving the data, this could be easier than writing this callback above. And the callback is still not everything - I yet need a way to pass the generated filename from the form page to that script - and not via form parameters, remember they are not available at that stage. So how can that be done? Simple - as PATH_INFO - which is available in the %ENV hash even before the params are parsed by CGI.pm.

This is the skeleton of the solution - there are a few more details in the actual implementation - but the code will be published soon as Open Source - so I hope everyone will be able to look them up there.

Saturday, June 19, 2010

When those micro-seconds matter

Catalyst is the only web framework that has a mailing list I subscribe to - but I am sure that it happens at others too. In a recurring pattern someone someone posts a benchmark showing that Catalyst for some trivial operation is many times (or many hundred times) slower than some other web framework or for that matter PHP. That does not fail to generate a heated debate - but eventually the seasoned framework developers gain the upper hand with the argument that for all the, often big, web sites they worked on, those few micro-seconds lost in the Catalyst dispatcher never mattered much because the application spent hundred times more in other code fragments and mostly in business logic parts, so shaving off some part of the few micro-seconds would not improve the overall speed more than 1%. This is a great argument, perfectly reasonable and rational but it is biased towards the status quo. It might be true that everywhere where Catalyst is currently used it works great but it is also not hard to imagine an application with very simple business logic that needs to serve millions of users, Twitter anyone? Or an app that does many simple Ajax callbacks. Sure you can always code the speed requiring, simple parts in PHP and keep Catalyst only for the other more heavy-weight tasks but having a universal solution would be so much more convenient.

Sunday, June 13, 2010

Installing dependencies for your packaged for CPAN library

Update: See the comments, apparently the warning against auto_install is outdated information. I don't have any opinion of myself here.

It always puzzled me what is the 'canonical' way to install dependencies for an unpacked distribution, be it downloaded from CPAN or your own in-house product packaged the CPAN way for convenience. Module::Install provides an 'auto_install' option that you add to your Makefile.PL and then perl Makefile.PL; make (or perl Makefile.PL; sudo make) should do that trick. This seemed like a good solution that could be a standard, but now I see that the FAQ of that module says:


Do I really have to avoid auto_install()?

auto_install() has a long history of breaking CPAN toolchains. Lots of people had a bad feeling on it, and have said it should be strongly avoided. In fact it was deprecated and removed once.

Although most of the known problems have been fixed and you can use it more safely than ever, the use of auto_install() is still discouraged, especially if what you are writing is a module to be uploaded on the CPAN. auto_install() does lots of things itself, thus does not always do the same things as other toolchains do (including extra attribute handling, etc; which can be fixed somehow but that's not too DRY). It only supports CPAN and CPANPLUS as its backends. If you use other tools to install, it may still cause a trouble.

Besides, now you can do what auto_install() does with other means. If your CPAN module is new enough, you can pass a dot to the cpan command it provides, and it will install all the required distributions from the CPAN:

$ cpan .

So apparently this is the way to go - using the cpan shell. There is a minor problem with this when used for testing - it would automatically install the package from the directory you are in. Sure you can suppress that you need by adding another command switch (-m), but it would be better if the default action was the safe one.

Saturday, May 22, 2010

Templates and inheritance

In every web site project I have been working on there inevitably came that moment that someone wanted to have a copy of the site with some small changes, or that someone wanted to use a piece the website in something else. In both cases it was all about (initially) some small changes, what they call as skin or a branded site. With programming part we know what to do then - we design base classes for the core undifferentiated functionality and inherit from them in the targeted classes. Most templating engines do have some notion of search path - so this should be doable with templates - but it always proves to be much more messy than it initially seems to be. I'll try to catalogue here all the use cases and how they compare to the standard inheritance in object oriented programming languages and describe them in terms of operations on the search path.


Initial setup


In 'normal' programming languages the atomic piece that can be inherited and overloaded and that is searched on the inheritance path is a method - in case of templates the atomic part is a whole template. The granularity is defined differently, but we can do analogues things with both. Here I will concentrate on the dispatching model familiar for users of most of the MVC frameworks with controllers and their methods as the endpoints (called actions). In this setting all the methods could have a matching template file and inheriting and overriding a template could work on the same level as inheriting and overriding an action.

Basic case


Lets say I have a controller 'MyApp::Controller::Book' with a few actions like 'view', 'list', 'edit' (a CRUD controller) and matching templates in 'templates/Book'. I would like that when calling the render from that controller I did not need to specify the full path of the templates - but just call them by name 'view'. Also when they have a common subcomponents in the same directory they should be able to [% INCLUDE date_formatting %] them by name. This is just like calling methods in a class and it can be accomplished by adding the 'templates/Book' directory at the start of the search path.

Library component


Sometimes we would like to use ready made components from some published library, maybe a CRUD controller for our Books. We inherit from the library class in our 'MyApp::Controller::Book' and we would like its templates to be inherited in a similar way. That means adding '/usr/lib/something/something/CRUD/templates' to our search path somewhere after 'templates/Book'.

Subclassing our own controllers


If our 'MyApp::Controller::Book' is a subclass of our own ''MyApp::Controller::Item' class - this is a very similar case to the above. Here as well we want to insert the search path of the parent class somewhere after 'templates/Book. But in this case what we insert is 'template/Item' - a path relative to our application root.

Application wide components


This is solved simply by adding an application wide element in the search path. It would be analogues to adding stuff to a common base class in standard programming - much more rare there.

Subclassing a whole site


This is the case of 'branded' sites where we would like to subclass everything at once. It is maybe the most common case - but also the most difficult because there are no good analogies/solutions in standard object oriented programming. If 'MyNewApp' inherits from 'MyApp' that does not automatically mean that 'MyNewApp::Controller::Book' springs to existence and can serve book information in the new app (but I've heard there are existing Object Oriented languages that work like that and some people are thinking about implementing this in Perl). So I think we need to first think over how this is handled in the main framework and then we can deduce something about how to treat templates from that. For the limited case of application wide components this can be solved by adding the new template root to the beginning of the search path - but it gets more complicated for all the other cases described above.

Conclusions


I mostly wrote that to have it all in one place - but I think it does show the need to make the template search path dependent on the controller used.

Wednesday, May 19, 2010

A subject for mst's talk

I did not really intended to vote in that silly poll - but I think I have found a subject for the talk that could be highly beneficial for the Perl community: How using the insights from cognitive science (and what else is needed) I am going to make HTML::Zoom actually usable for mere mortals.

Tuesday, May 18, 2010

PSGI and Object Oriented Programming

There is one thing that seems pretty simple - but it took me a bit of mulling over to fully understand


It is a reference to a sub that expects a hash ref representing the HTTP request passed to it as the one and only parameter and which returns an array ref representing a HTTP response. Hmm - yeah that's what web apps do - take the request and return the response.

But then you think - OK, but I like Object Oriented code and I want my application to be an object with attributes and stuff - so what can I do? Well - that is simple. Have your app as object as you like, and to the PSGI layer pass a closure referring to that object. For example if you application object normally handles the requests with a ->handle method then


would return a suitable callback. Which you can then use in your app.psgi file:


And this is exactly what I do in WebNano.

Wednesday, May 12, 2010

Web Applications and Dispatching

Historically the operation of finding the code to handle the web request was trivial - the server just matched the path part of the web request into the filesystem to find the CGI program producing the requested page. But then it got more complicated when we moved from the CGI 'one program equals one page' way into the realm of web applications that serve many pages.

The tree (or DAG) data structure is the underlying concept of both the path part of URL and many programming language library (or class) structures - so there is a natural way of mapping between them. To have code handling requests to related pages in the same file we can extend it so that the last part of the path is interpreted as a subroutine name.

That idea gets a bit more complicated when we realize that we don't want to expose all of our often internal methods (and libraries/classes) to be callable from outside - we need a way to mark them as 'external' and expose only these.

Of course sometimes there are reasons that we don't want to use such a literal mapping, it can be some security (by obscurity) need to hide internal code structures, need for more elegant URLs or other requirements. So sometimes we need to extend it or completely replace it with something else.

The Perl web frameworks (that I know the best) in respect to usage of that mapping can be roughly divided into following styles (many use more than one style so the boundaries are fuzzy):


  1. The 'old' CGI (or PHP) paradigm of one address one program

  2. Using the mapping of paths to libraries, selecting 'externally callable' methods by placing them on a list ( run_modes in CGI::Aplication ).

  3. Using the mapping of paths to libraries, but dispatching to methods configured via a hash (also run_modes in CGI::Application).

  4. Using the mapping of paths to libraries (but not to methods) and calling the 'get' or 'post' method in the landing library (like in Tatsumaki).

  5. Configuring the dispatching by code attributes of the methods (like in Catalyst).

  6. Not using methods but anonymous subroutines. This way it is easy to assign the dispatching configuration to the code by using DSLs (like in Dancer).

  7. Dispatching configuration external to the classes that are dispatched to.


Having the dispatching configuration close to the subroutine code let's you avoid switching between two places in the source code when adding a new action or changing an existing one. I think one of the greatest conveniences of Catalyst was that that configuration was not only in the same file but directly in the subroutine definition.

Saturday, April 17, 2010

WebNano - what I did not say at the London.pm tech meeting

About a month ago I had a presentation at the London.pm tech meeting about the design ideas I plan to experiment in WebNano. There are a few things that I did not have time to tell - and I plan to blog about them. First of all I think I should have admitted that I stole the both the name and the idea from Simon Cozen's MicroMaypole (I hope he will treat that in the terms of the well known quote about imitation and not intellectual property trespassing:).

At the presentation I mentioned that there is not much code in WebNano currently - but maybe this was not the best way to put it. I actually don't plan to ever have much code in it and the example of MicroMaypole shows that perhaps such a minimal web framework can be a practical thing, but I do plan to build some more examples using that minimal code so that I can be sure that even if minimal it does have all the desired features. What are those features will be the subject of other blog posts soon.

Monday, February 01, 2010

Frameworks are framing, libraries are liberating

It seems that the season is open and everyone is writing his new web framework again (all authors of the dozens of other recently created Perl web framework - please accept my apologies - I could not possibly link to all of your babies). If you ask me why is that? My answer is: it is easy now. We have libraries that do nearly everything that the traditional web frameworks provide. You don't need to write much - you just saw together the available patches and voila: your own web framework. You can be proud.

For some time I was thinking: OK, so now we have that cambrian explosion of new frameworks, that's OK, it will all settle down, people will select the best of them and the rest will die off. All we need to do is waiting. We could also speed it up a bit and make it a bit more smooth and rational by learning how to evaluate the frameworks. To do that we need to talk about them, study their functions and compare designs, project goals, project management styles and all of that. This will not be easy, but once we get past the awsome depth of common analyses of the 'this sucks' style and start to think about 'this is good for that and that other thing is better if you need something else', the rest will be incremental.

And I still believe that we need to talk more about design solutions and expand our vocabulary and use less of 'this is stupid' authoritative evaluations. This is something beneficial in any circumstances. But now I also think that since we have the libraries that do the all the work that previously was done by frameworks - then why should we build any more frameworks? Frameworks are coupling, they tie together the libraries that do the actual work and send that loose, uncohesive package to the programmer, who he has no choice, but has to use all of it and in the way prescribed by the framework. But every educated programmer knows that coupling is bad and cohesion is good. So why don't we just use the available nicely decoupled and internally cohesive libraries instead? Yeah, the libraries don't yet do all the 100% of stuff traditionally provided by frameworks, they can do 80% or even 90% of it but not yet the whole 100%, it is still ahead of us to extract the other 10% of functionality from the existing frameworks and turn it into a nicely decoupled and internally cohesive libraries.

Historically the trend is clear - the first frameworks did everything, the MVC frameworks included all Model, View and Controller components, then came Catalyst which is mostly just the Controller part. But that was not the end of decoupling - the Controller part still can be broken down further. And it was, with libraries like HTML::Engine budding off it, splitting and heading for an independent CPAN life. Now it is time to have a look at Catalyst and other frameworks and think what are the exclusive features that it provides that are not yet available as independent CPAN libraries. We have Plack, that provides all the abstraction needed for easy deployment and testing, we have packages like Bread::Board that provide a generic way of initialising application components, and I am sure there are also other interesting libraries at CPAN that provide other parts of the framework functionality. So what is left?

Maybe I am missing something, but the only important functionality of Catalyst that I cannot find any generic libs for is dispatching - selecting the subroutine (or method) that will handle a given HTTP request. I don't see any reasons why this should be hard to do. In fact I have already started working on that. OK - to be frank, what I started to work on was another web framework. I decided that I would like to have a mini framework and started coding it. Only now, after having the first CRUD example written in it, I can see that all I wrote is just a dispatch system, the other parts are freely available at CPAN. I can use Plack for the web engine abstraction and Plack::Test for testing, I can use Bread::Board for application components creation and Moose as the object framework - no need to reinvent the wheel.

Wednesday, January 13, 2010

MST explains the ideas lying behind his 'being a bastard'

It always seemed a bit weird when I saw mst kick himself out of an IRC channel - now we have it all nicely explained. Next time we'll have a self tickling machine, I am sure.