Nov 22

Today I’d like to present another Ant script for Scala development. I promise it’s going to be the last one, but I felt this mini series wouldn’t be complete without it. This script is for developing a Lift application with Scala. I became interested in Lift in the first half of this year, but unfortunately, I wasn’t able to install it when I wanted to give it a try, because of some besetting problems with Maven. Deplorably, the Lift developers have made Maven a requirement for Lift. If you go to the Lift download page, you wont find a Lift package but a Maven package which you must install in order to retrieve Lift from the central repository. Alternatively, you can fetch the latest Lift sources from GitHub, but then you still need Maven to get the examples to work. Since Maven and I have a difficult relationship, I mentioned this to the Lift community earlier this year. The community seemed quite pleased with Maven, however, and had little interest in supporting alternatives. Hence, I’ve adapted the Ant script from the last article in order to work with Lift and -while we are at it- replaced the Jetty server that is bundled with Lift with Tomcat.

I hope this will be useful for people interested in tinkering with Lift who want to avoid the aggravation of having to deal with Maven. As usual, you can download the project sekeleton and Ant build file right here. I have packaged the Lift 1.0 jars as well as its dependencies (commons-fileupload.jar and log4j.ar), so that you can get the helloworld example to run without additional installation steps. If you plan to use this for your work, you should replace the Lift jars with the most recent versions from GitHub. The Ant script has the same target definitions as the one I presented for general Web development including deploy, undeploy and reload. The Lift dependencies are likewise handled in the same way, as the script uses everything it finds in the WEB-INF/lib directory. Your only responsibility is to put the right jars in there. The main difference consists of a different directory tree structure that reflects the layout of a standard Lift project. This means you won’t have to rearrange things if you move a project from Maven to Ant. In fact all of the Lift examples should run simply by dropping in the sources (I’ve tried this for a few but not all examples). So, here’s the Ant script:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
<?xml version="1.0"?>
<project name="hellolift" default="build">
 
  <!-- root directory of this project -->
  <property name="project.dir" value="."/>
 
  <!-- root directory of Scala installation -->
  <property name="scala.home" 
    value="C:\\Program Files\\Scala"/>
 
  <!-- root directory of Tomcat installation -->
  <property name="server.home" 
    value="C:\\path\\to\\Tomcat\\installation"/>
 
  <!-- URL for Tomcat's manager application -->  
  <property name="server.manager.url" 
    value="http://dev:8080/manager"/>
 
  <!-- account name for Tomcat's admin account -->  
  <property name="server.manager.username" value="admin"/>
 
  <!-- password name for Tomcat's admin account -->  
  <property name="server.manager.password" value="admin"/>
 
  <!-- location of scalatest.jar for unit testing -->
  <property name="scalatest.jar" 
    value="C:\\path\\to\\scalatest-1.0\\scalatest-1.0.jar"/>
 
  <target name="init">
 
    <!-- derived path names -->
    <property name="source.dir" value="${project.dir}/src"/>
    <property name="web.dir" value="${project.dir}/web"/>
    <property name="classes.dir" 
      value="${web.dir}/WEB-INF/classes"/>
    <property name="lib.dir" 
      value="${web.dir}/WEB-INF/lib"/>
    <property name="webapp.dir" 
      value="${server.home}/webapps/${ant.project.name}"/>
    <property name="test.dir" value="${project.dir}/test"/>
 
    <!-- scala libraries for classpath definitions -->
    <property name="scala-library.jar" 
      value="${scala.home}/lib/scala-library.jar"/>
    <property name="scala-compiler.jar" 
      value="${scala.home}/lib/scala-compiler.jar"/>
 
    <!-- classpath for the compiler task definition -->   
    <path id="scala.classpath">
      <pathelement location="${scala-compiler.jar}"/>
      <pathelement location="${scala-library.jar}"/>
    </path>
 
    <!-- classpath for project build -->
    <path id="build.classpath">
      <pathelement 
        location="${server.home}/lib/servlet-api.jar"/>
      <pathelement location="${scala-library.jar}"/>
      <fileset dir="${lib.dir}">
        <include name="*.jar"/>
      </fileset>
      <pathelement location="${classes.dir}"/>
    </path>
 
    <!-- classpath for unit test build  -->
    <path id="test.classpath">
      <path refid="build.classpath"/>
      <pathelement location="${scalatest.jar}"/>
    </path>
 
    <!-- definition for the 
      "scalac" and "scaladoc" ant tasks -->
    <taskdef resource="scala/tools/ant/antlib.xml">
      <classpath refid="scala.classpath"/>
    </taskdef>
 
    <!-- definition for the "scalatest" ant task -->
    <taskdef name="scalatest" 
      classname="org.scalatest.tools.ScalaTestTask">
      <classpath refid="test.classpath"/>
    </taskdef>
 
    <!-- definition for the "reload", "deploy" 
      and "undeploy" Tomcat tasks -->
    <taskdef name="deploy" 
      classname="org.apache.catalina.ant.DeployTask">
      <classpath 
        path="${server.home}/lib/catalina-ant.jar"/>
    </taskdef>
    <taskdef name="reload" 
      classname="org.apache.catalina.ant.ReloadTask">
      <classpath 
        path="${server.home}/lib/catalina-ant.jar"/>
    </taskdef>
    <taskdef name="undeploy" 
      classname="org.apache.catalina.ant.UndeployTask">
      <classpath 
        path="${server.home}/lib/catalina-ant.jar"/>
    </taskdef>
 
  </target>
 
  <!-- compile project -->
  <target name="build" depends="init" description="build">
    <buildnumber/>
    <tstamp/>
    <mkdir dir="${classes.dir}"/>
    <mkdir dir="${lib.dir}"/>
    <copy file="${scala-library.jar}" todir="${lib.dir}"/>
    <scalac 
      srcdir="${source.dir}" 
      destdir="${classes.dir}"
      classpathref="build.classpath"
      force="never"
      deprecation="on"
    >
      <include name="**/*.scala"/>
    </scalac>
  </target>
 
  <!-- create a deployable web archive -->
  <target name="war" depends="build" description="war">
    <war destfile="${project.dir}/${ant.project.name}.war"
      webxml="${web.dir}/WEB-INF/web.xml"
      basedir="${web.dir}"
    />
  </target>
 
  <!-- creates a deployable web archive with 
    all classes packed into a single jar file -->
  <target name="packedwar" 
    depends="build" description="packedwar">
    <jar destfile="${lib.dir}/${ant.project.name}.jar" 
      basedir="${classes.dir}"
      duplicate="preserve">
      <manifest>
        <section name="Program">
          <attribute name="Title" 
            value="${ant.project.name}"/>
          <attribute name="Build" value="${build.number}"/>
          <attribute name="Date" value="${TODAY}"/>
        </section>
      </manifest>
    </jar>
    <delete dir="${classes.dir}"/>
    <war destfile="${project.dir}/${ant.project.name}.war"
      webxml="${web.dir}/WEB-INF/web.xml"
      basedir="${web.dir}"
    />
    <delete file="${lib.dir}/${ant.project.name}.jar"/>
  </target>
 
  <!-- deploy project on Tomcat server -->
  <target name="deploy" depends="war" description="deploy">
    <mkdir dir="${webapp.dir}"/>
    <copy todir="${webapp.dir}">
      <fileset dir="${web.dir}"/>
    </copy>
    <deploy url="${server.manager.url}"
      username="${server.manager.username}"
      password="${server.manager.password}"
      path="/${ant.project.name}"
      localWar="${project.dir}/${ant.project.name}.war"
      />
  </target>
 
  <!-- update and reload project on Tomcat server -->
  <target name="reload" 
    depends="build" description="reload">
    <copy file="${scala-library.jar}" todir="${lib.dir}"/>
    <copy todir="${webapp.dir}">
      <fileset dir="${web.dir}"/>
    </copy>
    <reload url="${server.manager.url}"
      username="${server.manager.username}"
      password="${server.manager.password}"
      path="/${ant.project.name}"/>
  </target>
 
  <!-- remove project from Tomcat server -->
  <target name="undeploy" 
    depends="init" description="undeploy">
    <undeploy url="${server.manager.url}"
      username="${server.manager.username}"
      password="${server.manager.password}"
      path="/${ant.project.name}"/>
  </target>
 
  <!-- build unit tests -->
  <target name="buildtest" depends="build">
    <mkdir dir="${test.dir}/build"/>
    <scalac 
      srcdir="${test.dir}" 
      destdir="${test.dir}/build" 
      classpathref="test.classpath"
      force="never"
      deprecation="on"
    >
      <include name="**/*.scala"/>
    </scalac>
  </target>
 
  <!-- run unit tests -->
  <target name="test" 
    depends="buildtest" description="test">
    <scalatest runpath="${test.dir}/build">
      <reporter type="stdout" config="YFABRT"/>
      <membersonly package="suite"/>
      <!-- <reporter type="graphic" config="YFABRT"/> -->
      <!-- <suite classname="suite.TestSuite"/> --> 
    </scalatest> 
  </target>
 
  <!-- delete all build files -->
  <target name="clean" depends="init" description="clean">
    <delete dir="${classes.dir}"/>
    <delete dir="${project.dir}/doc"/>
    <delete dir="${test.dir}/build"/>
    <delete file="${lib.dir}/scala-library.jar"/>
    <delete file="${project.dir}/${ant.project.name}.war"/>
  </target>
 
  <!-- create API documentation in doc folder -->
  <target name="scaladoc" 
    depends="build" description="scaladoc">
    <mkdir dir="${project.dir}/doc"/>
    <scaladoc 
      srcdir="${source.dir}" 
      destdir="${project.dir}/doc" 
      classpathref="build.classpath" 
      doctitle="${ant.project.name}" 
      windowtitle="${ant.project.name}"/>
  </target>
 
</project>
Share and Enjoy:
  • Digg
  • del.icio.us
  • Technorati
  • Facebook
  • Mixx
  • Google
  • YahooMyWeb
  • Slashdot
  • LinkedIn
  • blogmarks
  • Live
  • description
  • StumbleUpon
  • Ma.gnolia
  • MisterWong
  • NewsVine
  • Reddit
  • Spurl
  • Yigg
  • E-mail this story to a friend!
Nov 8

In my last blog entry I introduced an Ant script for building a stand-alone application with Scala. Today I present a script for building a Scala web application. Just as in the last example, you can download the script and the project skeleton layout for a “Hello World” application. The difference is that this application prints the infamous words on a web page rather than on the console. Things get slightly more complicated in a web application, because we need to interact with a web server to run the program. This is reflected by the Ant script below which has additional target definitions for deploying, undeploying and reloading the application on the server. I chose Tomcat for the server, because it’s a popular choice for Java web development and because Tomcat is mature, lightweight, and standards-compliant. If you use another web server, you may have to make some small modifications, but the overall structure should be the same. The script disregards web frameworks altogether and the “Hello World” application is simply implemented as a servlet. Since the file structure reflects the standard layout for a Java web application, it should be straightforward to get this to work with any Java web framework.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
<?xml version="1.0"?>
<project name="hello" default="build">
 
  <!-- root directory of this project -->
  <property name="project.dir" value="."/>
 
  <!-- root directory of Scala installation -->
  <property name="scala.home" 
    value="C:\\Program Files\\Scala"/>
 
  <!-- root directory of Tomcat installation -->
  <property name="server.home" 
    value="C:\\path\\to\\Tomcat\\installation"/>
 
  <!-- URL for Tomcat's manager application -->  
  <property name="server.manager.url" 
    value="http://dev:8080/manager"/>
 
  <!-- account name for Tomcat's admin account -->  
  <property name="server.manager.username" value="admin"/>
 
  <!-- password name for Tomcat's admin account -->  
  <property name="server.manager.password" value="admin"/>
 
  <!-- location of scalatest.jar for unit testing -->
  <property name="scalatest.jar" 
    value="C:\\path\\to\\scalatest-1.0\\scalatest-1.0.jar"/>
 
  <target name="init">
 
    <!-- derived path names -->
    <property name="source.dir" value="${project.dir}/src"/>
    <property name="web.dir" value="${project.dir}/web"/>
    <property name="classes.dir" 
      value="${web.dir}/WEB-INF/classes"/>
    <property name="lib.dir" 
      value="${web.dir}/WEB-INF/lib"/>
    <property name="webapp.dir" 
      value="${server.home}/webapps/${ant.project.name}"/>
    <property name="test.dir" value="${project.dir}/test"/>
 
    <!-- scala libraries for classpath definitions -->
    <property name="scala-library.jar" 
      value="${scala.home}/lib/scala-library.jar"/>
    <property name="scala-compiler.jar" 
      value="${scala.home}/lib/scala-compiler.jar"/>
 
    <!-- classpath for the compiler task definition -->   
    <path id="scala.classpath">
      <pathelement location="${scala-compiler.jar}"/>
      <pathelement location="${scala-library.jar}"/>
    </path>
 
    <!-- classpath for project build -->   
    <path id="build.classpath">
      <pathelement 
        location="${server.home}/lib/servlet-api.jar"/>
      <pathelement location="${scala-library.jar}"/>
      <fileset dir="${lib.dir}">
        <include name="*.jar"/>
      </fileset>
      <pathelement location="${classes.dir}"/>
    </path>
 
    <!-- classpath for unit test build  -->
    <path id="test.classpath">
      <path refid="build.classpath"/>
      <pathelement location="${scalatest.jar}"/>
    </path>
 
    <!-- definition for the "scalac" 
      and "scaladoc" ant tasks -->
    <taskdef resource="scala/tools/ant/antlib.xml">
      <classpath refid="scala.classpath"/>
    </taskdef>
 
    <!-- definition for the "scalatest" ant task -->
    <taskdef name="scalatest" 
      classname="org.scalatest.tools.ScalaTestTask">
      <classpath refid="test.classpath"/>
    </taskdef>
 
    <!-- definition for the "reload", "deploy" 
      and "undeploy" Tomcat tasks -->
    <taskdef name="deploy" 
      classname="org.apache.catalina.ant.DeployTask">
      <classpath 
        path="${server.home}/lib/catalina-ant.jar"/>
    </taskdef>
    <taskdef name="reload" 
      classname="org.apache.catalina.ant.ReloadTask">
      <classpath 
        path="${server.home}/lib/catalina-ant.jar"/>
    </taskdef>
    <taskdef name="undeploy" 
      classname="org.apache.catalina.ant.UndeployTask">
      <classpath 
        path="${server.home}/lib/catalina-ant.jar"/>
    </taskdef>
 
  </target>
 
  <!-- compile project -->
  <target name="build" depends="init" description="build">
    <buildnumber/>
    <tstamp/>
    <mkdir dir="${classes.dir}"/>
    <mkdir dir="${lib.dir}"/>
    <copy file="${scala-library.jar}" todir="${lib.dir}"/>
    <scalac 
      srcdir="${source.dir}" 
      destdir="${classes.dir}"
      classpathref="build.classpath"
      force="never"
      deprecation="on"
    >
      <include name="**/*.scala"/>
    </scalac>
  </target>
 
  <!-- create a deployable web archive -->
  <target name="war" depends="build" description="war">
    <war destfile="${project.dir}/${ant.project.name}.war"
      webxml="${web.dir}/WEB-INF/web.xml"
      basedir="${web.dir}"
    />
  </target>
 
  <!-- creates a deployable web archive with all classes
    packed into a single jar file -->
  <target name="packedwar" 
    depends="build" description="packedwar">
    <jar destfile="${lib.dir}/${ant.project.name}.jar" 
      basedir="${classes.dir}"
      duplicate="preserve">
      <manifest>
        <section name="Program">
          <attribute 
            name="Title" value="${ant.project.name}"/>
          <attribute name="Build" value="${build.number}"/>
          <attribute name="Date" value="${TODAY}"/>
        </section>
      </manifest>
    </jar>
    <delete dir="${classes.dir}"/>
    <war destfile="${project.dir}/${ant.project.name}.war"
      webxml="${web.dir}/WEB-INF/web.xml"
      basedir="${web.dir}"
    />
    <delete file="${lib.dir}/${ant.project.name}.jar"/>
  </target>
 
  <!-- deploy project on Tomcat server -->
  <target name="deploy" depends="war" description="deploy">
    <mkdir dir="${webapp.dir}"/>
    <copy todir="${webapp.dir}">
      <fileset dir="${web.dir}"/>
    </copy>
    <deploy url="${server.manager.url}"
      username="${server.manager.username}"
      password="${server.manager.password}"
      path="/${ant.project.name}"
      localWar="${project.dir}/${ant.project.name}.war"
      />
  </target>
 
  <!-- update and reload project on Tomcat server -->
  <target name="reload" 
    depends="build" description="reload">
    <copy file="${scala-library.jar}" todir="${lib.dir}"/>
    <copy todir="${webapp.dir}">
      <fileset dir="${web.dir}"/>
    </copy>
    <reload url="${server.manager.url}"
      username="${server.manager.username}"
      password="${server.manager.password}"
      path="/${ant.project.name}"/>
  </target>
 
  <!-- remove project from Tomcat server -->
  <target name="undeploy" 
    depends="init" description="undeploy">
    <undeploy url="${server.manager.url}"
      username="${server.manager.username}"
      password="${server.manager.password}"
      path="/${ant.project.name}"/>
  </target>
 
  <!-- build unit tests -->
  <target name="buildtest" depends="build">
    <mkdir dir="${test.dir}/build"/>
    <scalac 
      srcdir="${test.dir}" 
      destdir="${test.dir}/build" 
      classpathref="test.classpath"
      force="never"
      deprecation="on"
    >
      <include name="**/*.scala"/>
    </scalac>
  </target>
 
  <!-- run unit tests -->
  <target name="test" 
    depends="buildtest" description="test">
    <scalatest runpath="${test.dir}/build">
      <reporter type="stdout" config="YFABRT"/>
      <membersonly package="suite"/>
      <!-- <reporter type="graphic" config="YFABRT"/> -->
      <!-- <suite classname="suite.TestSuite"/> --> 
    </scalatest> 
  </target>
 
  <!-- delete all build files -->
  <target name="clean" depends="init" description="clean">
    <delete dir="${classes.dir}"/>
    <delete dir="${project.dir}/doc"/>
    <delete dir="${test.dir}/build"/>
    <delete file="${lib.dir}/scala-library.jar"/>
    <delete file="${project.dir}/${ant.project.name}.war"/>
  </target>
 
  <!-- create API documentation in doc folder -->
  <target name="scaladoc" 
    depends="build" description="scaladoc">
    <mkdir dir="${project.dir}/doc"/>
    <scaladoc 
      srcdir="${source.dir}" 
      destdir="${project.dir}/doc" 
      classpathref="build.classpath" 
      doctitle="${ant.project.name}" 
      windowtitle="${ant.project.name}"/>
  </target>
 
</project>

The directory structure differs slightly from that for a standalone application. We have an additional web directory for web content. It contains the WEB-INF directory where all class files and  libraries go. During development, class files are directly copied to the server without packaging. This ensures faster deploy/test cycles. In addition, there are Ant tasks for putting class files into a single jar  and for creating a distributable war file (war, packedwar). I have tried to keep the number of properties that need to be changed down to a minimum. Obviously, you need to set the home directories of your Scala, Scalatest, and Tomcat installations. You might also have to change the admin password for the Tomcat manager application which is used for automated deployment. Here is a summary of the defined targets:

  • build = compile your webapp and put class files into the WEB-INF/classes directory.
  • war = build a deployable web archive.
  • packedwar = build a deployable web archive with all class files packed into a jar.
  • deploy = deploy your webapp on Tomcat server.
  • reload = update project files on server and reload application.
  • undeploy = remove webapp from Tomcat server.
  • test = build and run unit tests (using Scalatest).
  • clean = delete all build files.
  • scaladoc = create API documentation from sources and put it into the in ./doc directory.
  • package = create a distributable zip archive that contains all dependencies plus Scaladocs.
Share and Enjoy:
  • Digg
  • del.icio.us
  • Technorati
  • Facebook
  • Mixx
  • Google
  • YahooMyWeb
  • Slashdot
  • LinkedIn
  • blogmarks
  • Live
  • description
  • StumbleUpon
  • Ma.gnolia
  • MisterWong
  • NewsVine
  • Reddit
  • Spurl
  • Yigg
  • E-mail this story to a friend!
Oct 5

Perhaps suggesting to eschew web frameworks for web application development is playing the devil’s advocate. Perhaps it is even foolish. To renounce the productivity boost one gets with a properly designed framework does not sound like sensible advice. Only ignorant script kiddies entertain such ideas. Well, for the most part that is true. A web framework does indeed simplify application development if it is chosen well. It does even more if it is designed well. It can provide architectural support for building maintainable applications. It can help with the plumbing and provide conceptual structure to guide the development process.

So, what speaks against using a web framework? Plenty actually, especially at the lower end of the spectrum and especially with dynamic languages. The main problem with web frameworks is that they add overhead. This means that the added functionality and structure is bought at the cost of performance degradation. The graveness of this problem depends on the system architecture. One  needs to keep in mind, that dynamic languages are interpreted at runtime, which makes them CPU-intensive and relatively slow. Because the life cycle of a script is essentially stateless and single-step, classes and data structures need to be rebuild and reloaded (in theory) at each request. In practice, this does not happen, because servers are designed to provide at least rudimentary caching. However, the runtime performance of interpreted languages is typically several magnitudes smaller than that of a compiled language, which magnifies the problem.

To illustrate my point, consider these benchmarks for PHP frameworks kindly provided by Paul M. Jones. According to these figures, a trivial PHP page is served by Apache 2 at a performance reduction of 43% compared to static HTML. The use of various PHP web frameworks further reduces performance by 85% - 95% compared to a PHP page that merely echoes content. Although it can be expected that these figures develop inverse logarithmically with increasing application code complexity, the slowdown is significant. PHP offers a number of remedies, such as  opcode caching, object caching, and products such as Zend Server, APC, and MCache, yet performance is unlikely to get even close to that of a compiled language.

Furthermore, there is the question whether the complexity of the project justifies the complexity introduced by a web framework. Would you use a web framework for building a guestbook script? Probably  not. What about a blog software? A photo gallery? A bulletin board? These types of applications are the mainstay of dynamic languages, such as PHP. It is the area where PHP really shines. Think of Wordpress, phpBB, Mediawiki, Drupal, osCommerce, Coppermine and other popular applications. They all have one thing in common: they don’t use a framework. Hence, before choosing a web framework for PHP development, it may be worth pondering if any is required. This suggestion may sound a bit contradictory, having just reviewed the Zend framework in a previous article. However, in my own practice I haven’t come across many complex PHP projects.

The commercial PHP projects I worked on during the last 10 years can roughly be divided into three categories: 1. extensions and customisations of open source packages, 2. intranet information systems, and 3. e-commerce systems and “catalogware”. Although the latter two may be considered candidates for web frameworks, the size of these projects was almost always small enough to do without. On several occasions, I chose to implement an “ultralight” MVC architecture by hand instead of using an out-of-the-box framework. The main reason for this was again performance. The “ultralight” approach is defined by implementing only the required functionality, which results in highly specialised design. In practice, this means slimming the controller, reducing DB abstraction to a thin wrapper around the native library, and foregoing a templating system in favour of embedded PHP.

The advantage of this approach is that you get separation of presentation and business logic, componentisation, and customisable control flow without the performance cost of full-blown framework. The disadvantage is that it is slightly more laborious to implement and less flexible. Don’t get me wrong. I have no problems imagining scenarios where I would want to use a PHP web framework such as the Zend framework. However, in these cases I’d probably be drawn towards using Java or (hopefully) Scala in the first place. In summary, I have found myself using PHP mostly in situations where a web framework seemed dispensable, while I have been using Java mostly in situations where a web framework seemed essential.

Share and Enjoy:
  • Digg
  • del.icio.us
  • Technorati
  • Facebook
  • Mixx
  • Google
  • YahooMyWeb
  • Slashdot
  • LinkedIn
  • blogmarks
  • Live
  • description
  • StumbleUpon
  • Ma.gnolia
  • MisterWong
  • NewsVine
  • Reddit
  • Spurl
  • Yigg
  • E-mail this story to a friend!

« Previous Entries Next Entries »