Let’s talk about frameworks (again)
Over the past year or so I’ve written several articles on frameworks, mostly talking about the pros and cons of using them and specific design decisions pertaining to specific frameworks. For the most part this has been in the context of programming — specifically Python and JavaScript programming — because, well, I’m a programmer; this is what I do for a living. But every so often the general topic of frameworks for the Web, recently focused on frameworks for client-side technologies, rears its ugly head again and people have all the same arguments over again. Which is a shame, because they tend to obscure more relevant (and, hence, more important) arguments.
What follows here is not an opinion on any specific framework or any particular use of a framework; I’d simply like to lay out some definitions and common themes, and hopefully provide some framing for future discussions which will avoid the need to have the same tired flame wars every time this topic comes up.
What is a framework, anyway?
Way back when I started my original frameworks series, I tried to provide a definition of “framework” which made sense for server-side application frameworks like Django and Rails:
When we talk about a “framework” in the context of web development, we’re basically talking about a set of tools that’s designed to help you quickly build some sort of web application. Maybe that application is a content-management system for a business. Maybe it’s an online store. Maybe it’s a social application like Flickr or del.icio.us. Whatever the application is, a good framework is designed to ease some of the burden of its development by handling common, tedious or repetitive tasks for you.
A typical framework will provide libraries of code for handling things like data modeling, database access, page templating and URL mapping. It may also go further and attempt to give you components for common situations like user authentication — the general idea is to provide a useful baseline of suitably generic functionality that’s needed by most web applications.
That’s still not a bad definition for this narrow scope, and gives some hints toward a broader definition; the key phrase is this:
Whatever the application is, a good framework is designed to ease some of the burden of its development by handling common, tedious or repetitive tasks for you.
And in the slightly broader context of all web development — back-end or front-end — the idea of a set of reusable components to cover common situations works well. I’ve written, for example, about what I think makes a good JavaScript “framework”, and this definition covers my wish list pretty thoroughly; there are some things you have to do all the time in JavaScript, which are tedious to write out by hand every single time, and so a single, reusable implementation that you can call upon whenever you need it can be an awfully handy thing.
Also on the front end, CSS frameworks like Blueprint or the YUI CSS tools follow the same pattern: CSS-based design work tends to involve a fair number of common, repetitive, and ultimately tedious tasks — sidestepping browser default styles, laying out a grid, standardizing typography, etc. — which seem as if they lend themselves nicely to being handled by a reusable framework.
In general, this sort of development pattern — identifying common tasks and abstracting them out into a single, reusable implementation — is one of the most important in a programmer’s repertoire. You’ll sometimes hear people joke that good programmers are “lazy”, and what this means is simply that good programmers tend to see duplicated work as a bug, and try to fix it. The result, in many cases, is a framework.
“Frameworks” versus “libraries” versus “snippets”
While I’m on the topic of definitions, I’d like to pause and consider a largely semantic, but seemingly contentious, debate about just when the word “framework” should be used, and whether there’s a difference between “frameworks”, “libraries”, “snippets” and various synonyms of these terms. Personally, I think the difference is largely in how each one is used, particularly the extent to which the finished product is coupled to the “framework”. Some examples will hopefully make this clear:
- A Django or Rails application is entirely coupled to the framework; without the framework it simply can’t exist, because nearly every part of it will rely heavily on libraries or utilities provided by the framework. This is, in a broad sense, probably the place where “framework” is the best term, and is distinguished by the fact that switching to a different framework would involve a more or less complete rewrite of the application.
-
A JavaScript application which uses a set of normalized wrappers to handle browser inconsistencies in
XMLHttpRequest
and implementations of specific DOM features like event listeners can probably switch pretty easily to using a different set of wrappers; parts of the application which fire offXMLHttpRequest
s or attach event listeners will need to be changed to use the new wrapper functions, but the logic which decides when to use those functions and which handles the responses and events will probably come through unchanged. This is a case where the term “library” is probably most appropriate; switching doesn’t involve a complete rewrite, but is still a bit of work. - A site which uses specific techniques to work around browser CSS inconsistencies (say, conditional comments or browser-specific “hacks”) in its design can switch to using a different set of techniques extremely quickly; setting aside the testing which would need to be performed for any CSS change, the total work here is probably no more than a couple minutes’ work copying and pasting. And so the best term here is likely to be “snippets”, which emphasizes the fact that these are small, isolated bits of code which are easy to remove and replace.
Any of these can, in theory, simply be collections of code a single person has built up through experience on various projects, or can be polished into a released product intended for general use; collected snippets of code can become a published “cookbook”, and libraries and frameworks go from private to public all the time.
It’s also relatively common for a set of snippets to become a library, and for a library to become a framework; Blueprint, for example, is quite clearly a framework (because the overall CSS will rely heavily on it, and will likely need to be completely rewritten to switch away from it), but it’s easy to see how it evolved from a library of more isolated components, and how those in turn evolved from collections of snippets.
And it’s possible, though not quite as common, to work in reverse: frameworks sometimes change direction and begin evolving into libraries, for example (Zope has been heading that way for a while).
It’s not a flaw, it’s a trade-off
Now that we’ve got a decent baseline for deciding what a “framework” is, we can delve into some of the common themes of arguments about frameworks; for the most part, they fall into categories that I’ve already covered (twice, actually), but I’d like to revisit the topic and maybe explain it a bit more clearly, because many common criticisms of frameworks — in all fields of web development, from back-end programming to front-end behavior and style — boil down to a single argument: “this is a trade-off I don’t want to make”.
Most commonly, you’ll hear points like the following:
- Frameworks “bloat” the finished product, because they contain a lot of code you won’t actually be using.
- Frameworks are dangerous because they let people do things without needing as much knowledge or experience of the problem domain.
- Frameworks usually involve third-party code, and so involve third-party bugs.
- None of the frameworks correspond to (fill in your preferred pattern or philosophy of development here).
In each of these cases, the argument gets obscured by the use of overzealous generalizations. What’s often being said is not “Framework Y is bad because of X”; rather, what’s being said is “Framework Y is not a good fit for my project because of X”, which is an entirely different thing.
Consider the first argument: frameworks “bloat” your final deliverable with all the extra code that you’re not using, but which has to be included in the framework in order to serve general-purpose needs. In actual practice, this is a trade-off to consider, and “will this bloat my product” is entirely the wrong question to ask. Instead, you should be asking questions like:
- How much of the framework will I actually use? If it’s not much, can I separate those parts out or find smaller libraries or snippets which provide the same functionality?
- Does the amount of extra code present a major drain on an important resource? If you’re talking about a few megabytes of framework code sitting resident in memory — a full copy of Django, for example, weighs in at a little under 9MB and not all of it will be in memory all the time — it may not be significant enough to make the framework unacceptable.
-
Can the resource usage be mitigated? JavaScript and CSS frameworks look like they should eat up a lot of bandwidth and slow down your page load times, but it’s often possible to “minimize” the files you actually serve (by stripping comments and whitespace), or to use compression techniques (like Apache’s
mod_deflate
) to reduce file sizes before sending anything over the wire (and, in fact, most such frameworks offer “full” and “minimized” versions for precisely this purpose). - How complex is the functionality the framework will be providing? Depending on your developer resources, it may be better to accept code you won’t use in exchange for a significant head start on development time.
In other words, black-and-white pronouncements of “Framework X will bloat the application” are next to useless outside the context of flame wars; the job of a professional is to look beyond those sorts of generalizations and ask, instead, what trade-offs will be involved in using the framework and whether those trade-offs are acceptable for the particular project you’re working on. The same is true of all the other over-generalized arguments:
- It’s true that a framework often makes it easier for newcomers, or people with little knowledge of the specific domain, to get up and running, but sometimes that’s not a bad thing; using a framework can just as easily teach key concepts and best practices, and if you need to bring someone new onto a project with a tight deadline you’ll be better off if the tools you’re using are easy to pick up quickly (see Brooks’s Law for details). The ability to quickly bring people on and up to speed can frequently outweigh the worry of “rookie mistakes”.
- It’s true that many frameworks involve third-party code which you (or your organization) didn’t write and so hasn’t necessarily gone through the same level of quality assurance as something you’d produce internally, but any framework worth its salt will have a publicly-searchable bug database and a slew of “I hate Framework X because Y and Z are hard/don’t work/need improvment” blog posts. This means it’s easy to build up an idea of how well a given framework can help with your current project; if its major bugs are in components you won’t be using, for example, they may simply be irrelevant to your decision.
- It’s true that a framework might not conform to your own preferred patterns or philosophies of development; it may use design patterns you don’t like, or it may take a different stance on philosophical issues, and so you wouldn’t feel as comfortable using it as you would with something you’d develop on your own. But, again, this is a trade-off to consider: if the savings in time or complexity outweigh the philosophical concerns, it might be better for your project to just hold your nose and go with the framework.
Of course, it cuts both ways
The fact that most of the broad generalizations used in arguments against frameworks are really better articulated in terms of trade-offs to evaluate in the context of specific projects means that most broad generalizations used in favor of frameworks are of the same substance:
- Frameworks are often claimed to provide a faster way to work, but involve the trade-off of time spent learning the framework.
- The general-purpose nature of frameworks, while a good thing most of the time, comes with the trade-off of being less well-suited to highly specialized situations.
- Sometimes a project will be better served by one or two narrowly-focused libraries, or smaller, well-placed snippets of code, than by the full weight of a framework.
- The high level of abstraction involved in framework-based development can be a downside at times, as every layer between the developer and the “bare metal” or equivalent incurs both conceptual and physical overhead.
The moral of the story
There’s a lot of hype and a lot of bile right now surrounding web frameworks of all sorts, both front-end and back-end. I think this is mostly due to the fact that they’re gaining much broader visibility; while framework-based development has been standard practice in a lot of “enterprise” shops for years now (almost exclusively in Java or .NET-based languages), it’s only with the last two years or so that they’ve really become accessible and attractive to folks working in the “big belly” of the Web: designers and developers working on their own, or at small- to medium-sized shops where the footprint (and, often, the price tag) of the older frameworks ruled out their use. And with a larger audience comes a larger and louder debate.
The lesson to take home, though, is that there are no quick and easy decisions. Deciding whether to use a framework at any level of your development process isn’t something you can base on the heated and essentially overgeneralized arguments made by people on both sides of the debate. Instead, like pretty much everything else in this industry, it comes down to careful evaluation and a series of trade-offs: there (still) ain’t no such thing as a free lunch, but that doesn’t mean you can’t shop around for a reasonably-priced meal.
Tomorrow: back to Django blogging.