Criticisms of Spring, Struts, PHP, and Rails
Spring/Spring MVCThe Spring Framework is popular. It has also met with a disturbing lack of criticism. For example, a Google search for 'spring framework criticism' shows very little serious discussion of possible drawbacks (aside from some interesting comments by Bob Lee). As a second example, the wikipedia article on Spring often reads as an advertising brochure, and lacks the neutral point of view usually found on that site.
The following remarks are based on Spring 2.0.
(Note : of course, Spring itself isn't a web application framework - Spring MVC is. However, when building a Spring MVC app, Spring is necessarily involved, so discussion of Spring itself is relevant in this context.)
Spring is huge.
The unzipped distribution is over 150 Meg. Spring is not a single framework. Rather, it's more of a collection of independent tools, with its Dependency Injection framework as the core item, Spring MVC as its web framework, and many other tools besides.
Some immediate consequences of this large size :
- it's complex.
- it has no clear focus. It includes "everything and the kitchen sink".
- its javadoc has over 2400 classes.
- its lib directory contains 49 other tools, totaling 82 jars. It's true that an application would never require them all, but this clearly a non-trivial number of possible dependencies.
- it takes significant time to learn about all of its parts.
- Joshua Bloch's dictum of "when in doubt, leave it out" hasn't been applied to this tool with much enthusiasm.
Spring has many bad names for things.
In designing an API, the importance of proper names cannot be underestimated. A good name will communicate clearly the purpose or general idea behind an item. A bad name causes the reader to feel confused.
Spring has many bad names. Some examples :
|Name||Context||Why This Is A Bad Name|
|singleton||scoping||These items aren't singletons in the commonly accepted sense of the word.|
|abstract||scoping||Has two meanings, one of which doesn't refer to an abstract type.|
|set/list||wiring||These items don't necessarily correspond to the familiar Set and List.|
|Spring MVC||web||This the name of the web app framework, but you would never know it from the name.|
|global-session||scoping||Refers to portals, but doesn't mention portal in any way|
|command||web||Refers to objects that hold request parameters. Command is usually reserved for action classes, not data-related classes.|
|RequestContext||web||This refers to request parameters. In web apps, context refers to the application context, not request params.|
|AccessDecisionManager||security||Performs authorization. Name unclear.|
|ProviderManager||security||Performs authentication. Name unclear.|
|ThrowawayController||web||Refers to the fact that the object can be garbage collected after use. From the point of view of the caller, this detail is irrelevant.|
|bean||wiring||These items aren't actually Java Beans, since they don't need to conform to the Java Bean Specification (no-arg constructors aren't required).|
The prevalence of bad names in Spring is unfortunate.
Spring apps need a lot of XML.
Spring applications often use large amounts of XML. In typical Spring documentation, about half of the examples are in XML, not in Java. The example applications provided with Spring show that XML files specific to Spring are on average about 24% of the size of your Java files:
|App||Lines XML||Lines Java||XML as % of Java|
Anyone considering Spring should be aware that they will be spending a significant amount of time coding in XML.
Moving application development from Java to XML has many significant drawbacks for the typical developer:
- compile time errors are moved to runtime errors (this is the cause of many other problems).
- type safety is thrown out the window.
- refactoring is more difficult.
- modern IDEs are very adept at editing Java, but such tools are usually not available for editing XML.
- understanding such files often requires following a tedious 'trail of breadcrumbs' of string identifiers.
- names within a single XML file (or between XML files) can be mismatched. Typos are easy to make, but hard to find (a bad combination).
- XML is not particularly legible or concise.
- when working in a source code control environment, monolithic XML files that refer to multiple features will often be a source of contention between programmers working on different tasks.
- XML was intended as a tool for transfering data between systems. In general, Spring uses XML in a way that wasn't intended by its creators. (Some refer to this as "XML abuse", with some justification.)
Spring confuses coding with configuration.
As noted above, Spring apps contain significant amounts of XML. Thus, programmers spend a lot of time editing XML files when building their application. In other words, they spend a lot of time coding in XML.
Spring documentation refuses to acknowledge this fact. Instead, coding in XML is always referred to as "configuration". But this is both erroneous and egregiously misleading. For apparent marketing reasons, Spring wants you to think using XML is somehow inherently beneficial to your application. That is, since they are "only configuration files", they must therefore carry less burden or effort than regular coding. (Given the difficulties mentioned above, however, one could strongly argue that XML files require more effort, not less.)
However, if you are building an application, then you are coding. Configuration is applied to applications that have already been built and deployed. It's inaccurate and downright misleading to refer to any part of building an app as "configuration".
Here's a comparison of the typical meaning given to the word 'configuration', versus the meaning implied by Spring documentation:
|Item||Normal Config||Spring "Config"|
|Number of files||1||N|
|Total number of lines||small||large|
|When settings made||deploy time||development time|
|File format||simple text||highly structured XML|
|Items interdependent||usually not||common|
|Usually small tweaks to behavior||yes||no|
|Specify class names||rare||common|
|Specify method names||almost never||common|
Spring has too many parallel mechanisms.
Parallel mechanisms are different ways of doing more or less the same task. Instead of deciding on a single reasonable way of performing a task, there are often 2, 3, or even 4 variations on the same theme. This can be very frustrating, since you need to spend significant time, first understanding all the options, and then deciding which one to pick.
- N different ways of wiring 'beans' together.
- 4 differents ways to map URLs to controllers.
- 3 different ways to use JDBC template classes.
- 2 different ways of binding data to form controls in web apps.
- choosing between XML coding and annotations.
- Spring AOP and AspectJ have a lot of overlap between them.
- the Spring security mechanism is very similar to that of the Servlet API.
- ...and many other items.
Spring has many other issues as well.
- Spring MVC has embarrassing security holes in its own example applications.
- Spring MVC has security issues which it insists are not the fault of the framework. You decide.
- Spring MVC documentation has no clear guidance on Cross-Site Scripting (XSS) attacks, and no clear guidance on Cross Site Request Forgery (CSRF) attacks. These attacks are very common, and every web app framework should help you defend against them. The absence of any clear discussion of these issues is disturbing.
- your application code will often require cast operations.
- you will sometimes need to catch exceptions to implement logic branches. Many would disagree deeply with using exceptions in this way.
- Spring translates checked exceptions into unchecked exceptions. Many would disagree strongly with that approach.
- Spring doesn't help you implement toString, equals, or hashCode.
- you can't place your SQL statements in a plain text file.
- it doesn't encourage package-by-feature.
- you can't centralize display formats for various data types.
- Spring has no services or guidelines for implementing code tables.
- Spring doesn't encourage you to avoid ResourceBundle and its defects.
- wiring of 'beans' can be ambiguous, non-obvious, and can have circular dependencies.
- Spring MVC itself has no built-in services for validation or templating. Instead, you are pointed to other tools of questionable quality.
- Spring MVC takes validation out of your Model Objects (its proper home), and moves it into a separate class having a single method. This is very unfortunate, since validation is such an important part of most apps.
- it doesn't let you implement your Model Objects as immutables.
- you can't implement your forms in plain HTML.
Struts 1Struts has the curious distinction of being simultaneously the most widely used and the most widely criticized Java web framework. Although it enjoys wide adoption, very few of its users would actually prefer to use it.
The reason for this curious situation may be that Struts arrived very early on the scene. In the beginning, it had few if any rivals, and was able to "expand into a vacuum". When entering new territory (in this case servlet applications), many organizations simply adopt the most popular tools available. This is likely because they simply don't have any other basis for comparison. In this way, a mediocre tool such as Struts was able to enjoy wide adoption, without much criticism.
However, after using Struts for several years, many have concluded that it isn't a very good framework. Instead of speeding up development, it seems to actually slow it down. Here is a listing of some of its defects.
PHPHere are the major pitfalls and drawbacks of using PHP :
- PHP has the dubious distinction of having the largest number of security holes of any tool in its class. This fact alone is enough for many organizations to reject it.
- after 10 years of growth, PHP has become stagnant since 2005. This is very likely because people are now rejecting it in favor of other tools, as they have become available.
- PHP does not support Unicode, so it's difficult to implement multilingual applications with it. A web framework that doesn't support Unicode is a parochial anachronism - WWW does stand for world wide web, does it not?
- the PHP language has no formal specification. It was originally built informally, by a single programmer, who wasn't experienced in designing programming languages. (Evidence for this is the large number of security holes in PHP.)
- many complain that the APIs are a mess - inconsistent naming conventions, functions of dubious benefit, synonymous functions, silent errors, and so on.
- according to its creator, PHP was "not designed to win any beauty contests".
- PHP doesn't use convention over configuration. Its creator states unequivocally: "I absolutely hate programming frameworks that lock me into a certain way of approaching a problem." This is in exact contradiction to modern tools, which embrace such conventions, since they save time and money.
- PHP by itself isn't a Model-View-Controller framework. As a result, many PHP applications and examples suffer from a lack of separation of concerns. In the hands of an inexperienced programmer, using PHP by itself often leads to higher maintenance costs because of poor design. Thus, the use a of second tool, an MVC framework built on top of PHP, is almost always necessary.
RailsFor the typical Java developer, here are the major pitfalls and drawbacks of using Ruby On Rails.
Rails doesn't do much to protect the application programmer from common security issues:
- Rails is open to SQL injection attacks when you manually construct SQL statements.
- by default, Rails will attempt to automatically bind all request parameters to items in your code. That is, it doesn't always use a white list of accepted request parameters. This is an egregious design flaw for a web application framework.
- Rails apps usually store session data in files or database records. This is inherently less secure than Java's in-memory sessions, since people with access to the server may view private information.
- by default, Rails will log request parameter values in clear text, including passwords.
- it always uses PreparedStatement. This protects you from SQL injection attacks.
- it always uses a white list of acceptable request parameters.
- it uses Java's in-memory sessions.
- it never logs the value of request parameters whose name contains the text 'password'. In addition, the form-based login mechanism defined by the servlet API usually handles login. So, in this important case, the framework cannot log any items in the first place.
Rails has other issues as well.
- surprisingly, Rails has no explicit support for multilingual applications.
- Rails uses the Active Record pattern, where Model Objects have intimate knowledge of their own persistence. In WEB4J, Model Objects are not tightly coupled to the database in this way.
- by default, Rails takes control of the database schema. For many organizations, this is backwards, since the database schema is usually under the control of database administrators, not programmers. In WEB4J, the application never assumes that it "owns" the database.
- in Rails, using more than one database is possible, but rather inelegant. In WEB4J, using multiple databases is just as natural as using one.
- the views in Rails are rather different from regular hypertext. For most Java programmers, their overall appearance is a bit heavy on scripting.
- the code generated by Rails uses package-by-layer, which is inferior to the package-by-feature style encouraged by WEB4J.
- Rails does not support distributed transactions. It is true that WEB4J also does not have services related explicitly to distributed transactions. However, since you are using Java, a UserTransaction can always be used when it is available in your environment.
- using Rails means you have to learn an entirely new language, libraries, and idioms. When constructing a Rails application, your experience with Java and its libraries will be mostly irrelevant.