Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 237 lines (220 sloc) 13.875 kb
915520eb » Zbigniew Lukasiak
2010-11-15 article
1 <html>
2 <head>
3 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
4 </head>
5 <body>
6 <h1>Why WebNano</h1>
7
8 There are some common parts of many web applications, things like a login page,
9 a comment box, an email confirmation mechanism, a generic
10 CRUD page - all of them are quite well defined and one can think that
11 it should not be too
12 difficult to abstract them away into libraries. And yet, every time you start a
13 web application you need to write that boring comment box again and
14 again. Why there are so few of such libraries? Why writing them is so hard?
15 There are more and less important reasons - but there are many of them and I
16 guess that eventually most of such application components projects die the
17 death of a thousand cuts. Some of those problems can be solved and I believe
18 that solving them would make a difference. WebNano is my attempt at doing that.
19 <p>
7aed9ac0 » Zbigniew Lukasiak
2010-11-15 article
20 Probably the most popular Perl web framework is Catalyst now, it is also the
21 web framework I know the best - this is why I choose it as the point of reference
22 for the analysis below.
915520eb » Zbigniew Lukasiak
2010-11-15 article
23
24 <h2>Controllers in request scope</h2>
25
26 Five years ago I was staring at the first Catalyst examples and I had this
27 foggy intuition that there is something not quite optimal there. The essence
28 of object oriented programming is that the most accessed data is made available
29 to all methods in a class without
30 explicitly passing them via parameters. But the examples always started with
31 <code>my ( $self, $c, ... ) = @_</code>, not very DRY. The <code>$c</code>
32 parameter was dragged everywhere as if it was plain old procedural programming.
33 <p>
34 At some point I <a
35 href="http://perlalchemy.blogspot.com/2009/10/catalystcomponentinstancepercontext.html">
36 counted how often methods from the manual use the controller object versus
37 how often they use the context object which contains the request data</a> -
38 the result was 117 and 38 respectively. Many people commented that their code
39 often uses the controller object. It's hard to comment on this until the code
40 is made public, my own experience was very close to that show by the manual,
41 but this disproportion is only an illustration. The question is not
42 about switching $c with $self. The question is why the
43 request data, which undeniably is in the centre of the computation carried on
44 in controllers, has to be passed around via parameters just like in plain old
45 procedural code instead of being made object data freely available to all
46 methods?
47 <p>
48 My curiosity about this was never answered in any informative way until about
49 year ago I finally got a reply in private communication from some members of
50 the core team - they want the controller object to be mostly immutable, and
51 that of course would not be possible if one of it's attributed contained data
52 changing with each new request. Immutable objects are a good design choice and
53 I accepted this answer but later I though: Wait a minute - what if we recreated
54 the controller object anew with each request? Then it could hold the request
928701c8 » Zbigniew Lukasiak
2010-11-20 less assigning
55 data and still be immutable for his whole life time. Catalyst controllers
56 are created at the starup time, together with all the other application
57 components (models and views) and changing that does not seem feasible - that's
58 why I decided to try my chances with writing a new web framework.
915520eb » Zbigniew Lukasiak
2010-11-15 article
59 <p>
7aed9ac0 » Zbigniew Lukasiak
2010-11-15 article
60 I have tried many Perl web frameworks but I
915520eb » Zbigniew Lukasiak
2010-11-15 article
61 found only one more that uses controllers in request scope - it is a very
62 fundamental distinguishing feature of WebNano. It's not only about reducing
63 the clutter of repeatable parameter passing - I believe that putting object into
64 their natural scope will fix a lot of the widely recognized <a
65 href="http://jjnapiorkowski.vox.com/library/post/does-anyone-else-hate-the-stash.html">problems
749e35be » Zbigniew Lukasiak
2010-11-20 some typos; some cleaning
66 with the Catalyst stash and data passed through it</a>. In procedural
915520eb » Zbigniew Lukasiak
2010-11-15 article
67 programming it is not a controversial rule to put your variable declarations
68 into the narrowest block that encompasses it's usage - the same should be true
928701c8 » Zbigniew Lukasiak
2010-11-20 less assigning
69 for objects. Sure using the same controller to serve multiple request is a bit
70 faster then recreating it each time - but that gain is not that big -
71 <a href="http://www.cpantesters.org/cpan/report/7c61aa08-d810-11df-8503-f91d06264d1f">Object::Tiny
72 on one of the tester machines could create 714286 object per second</a> and even
73 Moose - the slowest framework tested there can create more then a 10000 objects
74 per second. Eliminating a few of such operations, in most circumstances, is not
75 worth compromising on the architecture.
76
77 By the way I also tested these theoretical estimations with more
b7d2a23c » Zbigniew Lukasiak
2010-11-15 article
78 down to earth <a href="http://httpd.apache.org/docs/2.0/programs/ab.html">ab</a>
79 benchmarks for a trivial application serving just one page -
12f770b8 » Zbigniew Lukasiak
2010-11-23 not so speedy any more with debuggnig
80 WebNano came out as the fastest framework tested. This is
928701c8 » Zbigniew Lukasiak
2010-11-20 less assigning
81 still not very realistic test - but should be enough to show
82 that the cost introduced by this design choice does not need to be big.
915520eb » Zbigniew Lukasiak
2010-11-15 article
83
84
85 <h2>Decoupling</h2>
86
87 The reason why WebNano is the fastest framework is probably that it just does
88 not do much. WebNano is really small, in it's 'lib' directory it currently has
4e391663 » Zbigniew Lukasiak
2010-11-23 sloc
89 just 240 lines of code (as reported by <a href="http://www.dwheeler.com/sloccount/">sloccount</a>)
749e35be » Zbigniew Lukasiak
2010-11-20 some typos; some cleaning
90 and <a href="http://deps.cpantesters.org/?module=WebNano;perl=latest">minimal
91 dependencies</a>. There are CPAN libraries covering all corners of web
915520eb » Zbigniew Lukasiak
2010-11-15 article
92 application programming - what the framework needs to do is provide a basic
928701c8 » Zbigniew Lukasiak
2010-11-20 less assigning
93 structure and get out of the way.
94 <p>
95 Catalyst started the process of decoupling the web framework from the other
96 parts of the application, with Catalyst you can use any persistence layer for
97 the model and any templating library for the view. The problem is that the
98 <code>model</code> and <code>view</code> methods in Catalyst become rather empty
99 - there is no common behaviour among the various libraries - so all these
100 methods do is finding the model or view by it's name. For WebNano I decided
101 that <code>->Something</code> is shorter and not less informative then
915520eb » Zbigniew Lukasiak
2010-11-15 article
102 <code>->model('Something')</code> - and I got rid of these methods.
103 <p>
104 The other thing that I decided not to add to WebNano is initialization of
cde2635c » Zbigniew Lukasiak
2010-11-20 - to and
105 components. Component initialization is a generic task and it can be done in
106 a similar way for all kinds of programs and the library that does that job does
928701c8 » Zbigniew Lukasiak
2010-11-20 less assigning
107 not need to know anything about the web stuff. At CPAN there are such
108 libraries. For my limited experiments <a
749e35be » Zbigniew Lukasiak
2010-11-20 some typos; some cleaning
109 href="http://search.cpan.org/dist/MooseX-SimpleConfig/">MooseX::SimpleConfig</a>
928701c8 » Zbigniew Lukasiak
2010-11-20 less assigning
110 was very convenient, for more complex needs <a
749e35be » Zbigniew Lukasiak
2010-11-20 some typos; some cleaning
111 href="http://search.cpan.org/dist/Bread-Board/">Bread::Board</a> seems like
928701c8 » Zbigniew Lukasiak
2010-11-20 less assigning
112 a good choice. This initialization layer needs to know how to create all the
113 objects used by the application - but you don't need any kind of WebNano adapter
114 for them.
915520eb » Zbigniew Lukasiak
2010-11-15 article
115
116 <h2>Localized dispatching</h2>
117
118 Out of the box WebNano supports only very simple
119 dispatching model - this can be enough because this default dispatching is
120 so easy to extend and override on per controller basis. Dispatching is about
121 what subroutine is called and with what arguments - this is strongly tied to
122 the subroutines themselves. This is why I don't believe in external
123 dispatchers where you configure all the dispatching for the application in one
124 place. The dispatching might be in one place - but all practical changes need
125 to be done in two.
126 <p>
127 Writing a dispatcher is not hard - it becomes hard and
128 complex when you try to write a dispatching model that would work for every
129 possible application. I prefer to write a simple dispatcher covering only the
130 most popular dispatching scenarios - and let the users of my framework write
749e35be » Zbigniew Lukasiak
2010-11-20 some typos; some cleaning
131 their own specialized dispatching code for their specialized controllers. With
915520eb » Zbigniew Lukasiak
2010-11-15 article
132 WebNano this is possible because these specialized dispatchers don't interfere
133 with each other.
134 <p>
135 I also believe that this will make the controller classes more encapsulated
136 - thus facilitating building libraries of application controllers.
137
138 <h2>Granularity</h2>
139
140 I like the way Catalyst structures your web related code into controller
141 classes - this is a step forward from the <a
3a142126 » markstos
2010-12-15 A non-version-specific link to CGI::Application.
142 href="http://search.cpan.org/perldoc?CGI::Application">CGI::Application</a>
915520eb » Zbigniew Lukasiak
2010-11-15 article
143 way of packing everything into one class. I don't have any hard data to
144 support that - but the granularity of packing a few related pages into one
145 controller class feels just about right. It gives room for expansion by adding
146 new classes and dividing existing ones - and it also does not clutter the
147 application code with too many nearly empty classes. This is a very important
148 feature and in WebNano I copied this.
149
150 <h2>Experiments with inheritance and overriding</h2>
151
152 One of the WebNano tests is an application that a subclass of the main test
153 app. It passes all the original tests and could be completely empty if I did
154 not want to test the overriding of the inherited parts. I have seen many times
155 a need for such behaviour, from 'branding' websites, through SAAS to reusable
749e35be » Zbigniew Lukasiak
2010-11-20 some typos; some cleaning
156 intranet tools - most of the time this was solved by copying the code.
915520eb » Zbigniew Lukasiak
2010-11-15 article
157 Inheritance has it's problems but it would fit well this ad-hoc reuse and it is
158 still better then 'cut and paste' programming. The key point here is that you
159 need to override much more than just methods. The experiment I am doing with
160 WebNano is about overriding application parts: controllers, templates and
161 configuration, and independently at the level of individual controllers once
162 again overriding it's templates, plus of course the standard OO way of method
163 overriding.
164
165 <p>
166 I think with this type of inheritance it would be more
167 natural to publish applications to CPAN, because they could be operational
b7d2a23c » Zbigniew Lukasiak
2010-11-15 article
168 without any installation. A user could run them directly from @INC and only
915520eb » Zbigniew Lukasiak
2010-11-15 article
169 later override the configuration or templates as needed.
170
171 <h2>Universality</h2>
172 In the most common case a web application serving a request needs to: fetch
173 data from the database, do some computation over this data and render a
174 template with the computed values. Doing those tasks typically takes over 99%
175 of the overall time spent serving a request. The 1% of time spent in the
176 application framework processing does not matter much and reducing it further
177 would not result in any noticeable speed increase of the whole application.
178 Yet there might be some rare cases where the application needs to serve for
179 example small JASON data chunks from a memory cache - even when this is a small
180 and simple part of the application - if it generates enough volume - then the
181 speed of the framework suddenly becomes important. Would you code that part in
182 PHP?
183 <p>
184 It is well known that using Moose generates some significant startup overhead.
185 For web applications running in persistent environments - this does not matter
186 much because that overhead is amortized over many requests, but if you run your
187 application as CGI - this suddenly becomes important. I was very tempted to
188 use Moose in WebNano - but even if CGI is perceived so passe now - it is still
189 the easiest way to deploy web applications and also one that has the most
190 widespread support from hosting companies. Fortunately using MooseX::NonMoose
191 it is very easy to treat any hash based object classes as base classes for
192 Moose based code, so using WebNano does not mean that you need to stick to the
193 simplistic Object Oriented Framework it uses.
194 <p>
195 The plan is to make WebNano small, but universal, then make extensions that
196 will be more powerful and more restricted. I think it is important that the
197 base platform can be used in all kinds of circumstances.
198
199 <h2>Conclusions</h2>
200 It is early to say if WebNano will live to the promise of facilitating the
201 development of web application components. There is a first component at CPAN:
749e35be » Zbigniew Lukasiak
2010-11-20 some typos; some cleaning
202 <a href="http://search.cpan.org/dist/WebNano-Controller-CRUD/">WebNano::Controller::CRUD</a>.
915520eb » Zbigniew Lukasiak
2010-11-15 article
203 It still bears the label 'experimental' - but I used it in <a
749e35be » Zbigniew Lukasiak
2010-11-20 some typos; some cleaning
204 href="https://github.com/zby/Nblog">Nblog</a>. When I compare it to my
915520eb » Zbigniew Lukasiak
2010-11-15 article
205 first similar product <a
749e35be » Zbigniew Lukasiak
2010-11-20 some typos; some cleaning
206 href="http://search.cpan.org/~wreis/Catalyst-Example-InstantCRUD-0.037/lib/Catalyst/Example/Controller/InstantCRUD.pm">Catalyst::Example::Controller::InstantCRUD</a>,
928701c8 » Zbigniew Lukasiak
2010-11-20 less assigning
207 there aren't many differences. As predictable the methods have one less parameter
208 (<code>$c</code>), and I think it's inheritable templates are
209 nice at deployment - you don't need to write your own templates to see it working,
210 later you can easily override the defaults. There is a bit more dispatching
211 code - but thanks to that the result object is being retrieved from the model in
212 only one place. In Catalyst this could also be done now by using the chained
8760da98 » Zbigniew Lukasiak
2010-11-22 CRUD variations in article
213 dispatching. In the
214 <a href="https://github.com/zby/WebNano/tree/master/examples/DvdDatabase/lib/DvdDatabase/Controller/">examples directory</a>
215 there are four variations on this CRUD theme - I am still not decided about
216 what is the optimal one.
928701c8 » Zbigniew Lukasiak
2010-11-20 less assigning
217 <p>
218 The surprising thing when
915520eb » Zbigniew Lukasiak
2010-11-15 article
219 converting Nblog from Catalyst to WebNano was how little I missed the rich
220 Catalyst features, even though WebNano has still so little code. I think it is
221 a promising start.
222
223 <p>
224 Recently I discovered that many of my design choices are echoed in the
225 publications by the Google testing guru <a
749e35be » Zbigniew Lukasiak
2010-11-20 some typos; some cleaning
226 href="http://misko.hevery.com/">Miško Hevery</a>. My point of departure
915520eb » Zbigniew Lukasiak
2010-11-15 article
227 for the considerations above were general rules - like decoupling,
228 encapsulation etc - his concern is testability - but the <a
749e35be » Zbigniew Lukasiak
2010-11-20 some typos; some cleaning
229 href="http://misko.hevery.com/2008/08/21/where-have-all-the-singletons-gone/">resulting
230 design</a> is remarkably similar. There is a lot of good articles at his
915520eb » Zbigniew Lukasiak
2010-11-15 article
231 blog, some were similar to <a
749e35be » Zbigniew Lukasiak
2010-11-20 some typos; some cleaning
232 href="http://misko.hevery.com/2009/04/15/managing-object-lifetimes/">what I
233 already had thought over</a>, <a
234 href="http://misko.hevery.com/2009/04/08/how-to-do-everything-wrong-with-servlets/">others</a>
915520eb » Zbigniew Lukasiak
2010-11-15 article
235 were completely new to me. I recommend them all.
236 </body>
237 </html>
Something went wrong with that request. Please try again.