Move Over LAMP, Make Way for JAMM
After working heads-down with Meteor and MongoDB for four months, I haven’t run into any show-stopping snags.
You’ve likely run into the acronym LAMP which describes an enormously popular application architecture based on Linux, Apache, MySQL and PHP. The combination of JavaScript, Meteor and MongoDB is so powerful and cost-effective, it deserves its own acronym. So move over LAMP and make room for JAMM (Javascript, Meteor, MongoDB).
Working with these tools has made me appreciate scrappy JavaScript, particularly when combined with powerful add-ons like jQuery and Underscore. JavaScript can be made modular, yielding key benefits of encapsulation and object-orientation (purists may argue but they’re splitting hairs). My own fears about leaving the Java “tribe” seem unfounded: everything you need for a typical data-centric project is available, open source, lovingly crafted by a growing list of true believers in Node.js and Meteor.
I think we’ll see more and more enterprise-class, cloud-based applications written using nothing but JavaScript. Many forward-thinking companies have been infected by this trend and have made enormous investments in JavaScript, albeit still using mature technologies such as PHP and AJAX. With deep pockets, they’ve spared no expense on their front-end code. Meteor lowers the bar, making JavaScript-centric, reactive front ends available to the masses at low cost.
But adjusting to these new tools can be disorienting, and I find myself comparing and contrasting JAMM to things with which I am more familiar. Over the past decade, I’ve been working on rule-based systems that conform to three-tier architecture.
With this architecture, the client tier, typically a web page or hand held device, communicates with an application server that comprises the middle tier. The middle tier contains business rules that operate on a domain model (i.e., object instances that contain enterprise data). In most cases, the domain model is mapped to a database, and in the Java world, often using Hibernate, the leading object-relational mapping system.
By convention, in three-tier architecture, the client tier is typically regarded as “dumb” in that it merely renders facts that are derived by business rules in the middle tier. Granted, the front end has mechanical JavaScript code for things like animations, tabs and managing powerful widgets such as trees and tables, but typically no business logic.
In the three-tier approach, the database tier is frequently seen as nothing more than a storage system, but admittedly in many cases, firms fudge by coding some business logic in database-resident stored procedures and triggers that can technically be characterized as rules. People will argue about the merits of this, but I’ve honestly become fatigued by the controversy; it is mostly religion.
With three-tier architecture, the middle tier is king. The middle tier encapsulates a centrally-controlled domain model that is in a consistent, canonical form (i.e., objects). In theory, by centralizing business rules in the middle tier, cost can be reduced, and software quality can be improved.
Irrespective of whether potential benefits are realized, three-tier architecture is pervasive. A consensus about the viability of this architecture emerged in the early 1990’s and it has remained largely unchallenged to this day.
Tangible cost benefits of three-tier architecture can be difficult to achieve due to complexity. Object-relational mapping is not straightforward due to a set of technical problems collectively referred to as impedance mismatch. It has taken many years of focused effort for Hibernate to be regarded as production-ready. Even now, performance considerations make it likely that caching systems will be necessary, effectively carrying an object-oriented copy of frequently-referenced data in the middle tier.
It takes extraordinary effort to maintain the illusion that our data is represented as neutral objects when in fact the underlying data is stored in relational form. The cost of dealing with this complexity is real, including the difficulty of recruiting developers that have mastered object/relational technologies, but also in operations and technical support, where problems can be difficult to diagnose and correct. Much of this complexity and cost can be reduced by JAMM.
MongoDB as Object Authority
MongoDB stores and maintains data in a form that is functionally equivalent to a traditional middle-tier domain model. Because of this, there is no need to maintain a extra object-oriented copy of the data in the middle tier; instead, middle-tier rules operate upon objects in the database tier, which becomes the central authority for persistent and non-persistent facts. With this approach, the middle tier can be characterized as stateless.
To an engineer familiar with traditional three-tier architecture, this shift in design can trigger alarms. I explored my own feelings about this, and found that they boiled down to visceral concerns about database performance.
To counter these concerns, it is important to understand that accessing data in MongoDB is much faster than an object/relational system. Given a Mongo ID of a document (tantamount to primary key), data can be accessed rapidly because:
- In many cases, the data to be accessed will already be memory
- The data may be indexed in extraordinary ways, including indexing every single field of a given record
- The database tier and middle tiers may in fact be in the same machine, reducing communications overhead
- There is no mapping overhead because the data is stored in object form
Rules in the middle tier can access just the data they need using granular MongoDB selectors (akin to database SELECT statements), and make state changes to MongoDB without carrying an object-oriented copy of the data.
With this approach MongoDB can be viewed as the state authority for both persistent and non-persistent data, supplanting the middle tier. I stress non-persistent, because MongoDB is so fast and convenient, it can be used to handle non-persistent data that would traditionally be kept only in the middle tier.
In short, we need to resist the tendency to look at MongoDB as just a storage system. It can be elevated to a higher plane to become the state authority, the keeper of canonical objects.
Rules on Client Tier
Because JAMM is implemented in 100% JavaScript, it is possible to deploy business rules to the client tier, the middle tier or both. Although purists may resist the idea of deploying business rules to the client, I have come to see this as a stupendous opportunity. Example opportunities for rules on the client include:
- Data validation without requiring a server round trip
- Data validation via calls to external systems without involving the middle tier (e.g., Google Places API)
- Conditional forms (i.e., certain parts of a web page being displayed or hidden based on answers to questions)
Meteor allows JavaScript rules to be moved indiscriminately from middle tier to the client or vice-versa, without programming changes. This permits you to deploy rules where they make the most sense, resulting in improved performance and user experience, and allowing the client to behave reasonably in the face of a spotty connection to the server.
Look forward to more applications pushing rules out to the client tier, and using middle tier services more sparingly for heavy number-crunching or for financial transactions where security is a concern.