Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 238 lines (220 sloc) 13.875 kb
915520e article
Zbigniew Lukasiak authored
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>
7aed9ac article
Zbigniew Lukasiak authored
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.
915520e article
Zbigniew Lukasiak authored
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
928701c less assigning
Zbigniew Lukasiak authored
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.
915520e article
Zbigniew Lukasiak authored
59 <p>
7aed9ac article
Zbigniew Lukasiak authored
60 I have tried many Perl web frameworks but I
915520e article
Zbigniew Lukasiak authored
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
749e35b some typos; some cleaning
Zbigniew Lukasiak authored
66 with the Catalyst stash and data passed through it</a>. In procedural
915520e article
Zbigniew Lukasiak authored
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
928701c less assigning
Zbigniew Lukasiak authored
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
b7d2a23 article
Zbigniew Lukasiak authored
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 -
12f770b not so speedy any more with debuggnig
Zbigniew Lukasiak authored
80 WebNano came out as the fastest framework tested. This is
928701c less assigning
Zbigniew Lukasiak authored
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.
915520e article
Zbigniew Lukasiak authored
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
4e39166 sloc
Zbigniew Lukasiak authored
89 just 240 lines of code (as reported by <a href="http://www.dwheeler.com/sloccount/">sloccount</a>)
749e35b some typos; some cleaning
Zbigniew Lukasiak authored
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
915520e article
Zbigniew Lukasiak authored
92 application programming - what the framework needs to do is provide a basic
928701c less assigning
Zbigniew Lukasiak authored
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
915520e article
Zbigniew Lukasiak authored
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
cde2635 - to and
Zbigniew Lukasiak authored
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
928701c less assigning
Zbigniew Lukasiak authored
107 not need to know anything about the web stuff. At CPAN there are such
108 libraries. For my limited experiments <a
749e35b some typos; some cleaning
Zbigniew Lukasiak authored
109 href="http://search.cpan.org/dist/MooseX-SimpleConfig/">MooseX::SimpleConfig</a>
928701c less assigning
Zbigniew Lukasiak authored
110 was very convenient, for more complex needs <a
749e35b some typos; some cleaning
Zbigniew Lukasiak authored
111 href="http://search.cpan.org/dist/Bread-Board/">Bread::Board</a> seems like
928701c less assigning
Zbigniew Lukasiak authored
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.
915520e article
Zbigniew Lukasiak authored
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
749e35b some typos; some cleaning
Zbigniew Lukasiak authored
131 their own specialized dispatching code for their specialized controllers. With
915520e article
Zbigniew Lukasiak authored
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
3a14212 @markstos A non-version-specific link to CGI::Application.
markstos authored
142 href="http://search.cpan.org/perldoc?CGI::Application">CGI::Application</a>
915520e article
Zbigniew Lukasiak authored
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
749e35b some typos; some cleaning
Zbigniew Lukasiak authored
156 intranet tools - most of the time this was solved by copying the code.
915520e article
Zbigniew Lukasiak authored
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
b7d2a23 article
Zbigniew Lukasiak authored
168 without any installation. A user could run them directly from @INC and only
915520e article
Zbigniew Lukasiak authored
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:
749e35b some typos; some cleaning
Zbigniew Lukasiak authored
202 <a href="http://search.cpan.org/dist/WebNano-Controller-CRUD/">WebNano::Controller::CRUD</a>.
915520e article
Zbigniew Lukasiak authored
203 It still bears the label 'experimental' - but I used it in <a
749e35b some typos; some cleaning
Zbigniew Lukasiak authored
204 href="https://github.com/zby/Nblog">Nblog</a>. When I compare it to my
915520e article
Zbigniew Lukasiak authored
205 first similar product <a
749e35b some typos; some cleaning
Zbigniew Lukasiak authored
206 href="http://search.cpan.org/~wreis/Catalyst-Example-InstantCRUD-0.037/lib/Catalyst/Example/Controller/InstantCRUD.pm">Catalyst::Example::Controller::InstantCRUD</a>,
928701c less assigning
Zbigniew Lukasiak authored
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
8760da9 CRUD variations in article
Zbigniew Lukasiak authored
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.
928701c less assigning
Zbigniew Lukasiak authored
217 <p>
218 The surprising thing when
915520e article
Zbigniew Lukasiak authored
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
749e35b some typos; some cleaning
Zbigniew Lukasiak authored
226 href="http://misko.hevery.com/">Miško Hevery</a>. My point of departure
915520e article
Zbigniew Lukasiak authored
227 for the considerations above were general rules - like decoupling,
228 encapsulation etc - his concern is testability - but the <a
749e35b some typos; some cleaning
Zbigniew Lukasiak authored
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
915520e article
Zbigniew Lukasiak authored
231 blog, some were similar to <a
749e35b some typos; some cleaning
Zbigniew Lukasiak authored
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>
915520e article
Zbigniew Lukasiak authored
235 were completely new to me. I recommend them all.
236 </body>
237 </html>
Something went wrong with that request. Please try again.