There’s a running theme on this blog, if you’ve read many of my posts. It’s that most posts come as a result of some
fireshit-storm I set off on twitter or wherever else when I make a claim that almost everyone seems to disagree with. I then feel the obligatory incumbency to at least explain myself in a detailed blog post. This post is no different.
On Saturday afternoon, I tweeted:
OH “frameworks are useful only for rapid prototyping. once you go to production, you should re-write and remove the frameworks”
This came from a conversation I had with a few people, and I paraphrased a few points into that one “OH”. Someone in the conversation later corrected me that “only” should have been “most”. OK, fine, whatever.
The context of our discussion was actually about CSS frameworks, like Twitter Bootstrap. The person who made the claim was railing against the use of such frameworks in production. He claimed they were bloated (slower load due to file-size) and they were quite obviously cookie-cutter. He basically agreed that they’re very useful for rapid prototyping, but as soon as you know what the site should look like and are happy with it, you should rip out all the frameworky stuff and make custom CSS for that design.
I liked that way of putting it. I suggested the same (well, kinda) was true of JS frameworks, and the others around the circle seemed to agree.
But oh boy, did I stab some sacred cow when I dared to tweet that claim out.
Religious flame-wars aside, people really seem to love them some JS frameworks. Emberists, Angulars, Backboners, unite! Down the with heretic who dare attack our way of life!
If you like your framework, fine. I’m not trying to tell you your framework choice is wrong. That’s for another post or conf talk.
But let me say this: almost all the reasons you use to justify why using said framework even once you push code to production, are IMO silly. I’ll grant you that you like your framework-of-choice, but I’m not going to grant you anything beyond personal preference as your foundation.
What’s in a name?
It’s important that I right-away give my definition for “framework”.
A framework is an opinionated tool which exerts a strong degree of influence over how you design and architect your code, and in so doing, makes a number of assumptions about how various tasks/problems should be solved, layers on auto-magical abstractions to hide the ugly parts, and bootstraps an awful lot of the basic structure for you.
Update: I recently came up with another metaphor to depict my definition of framework, and how it fits in between “tools & libraries” and “platforms”:
- Tools/Libraries: a geographic map you can consult on a trip (either physical folded map or app with a blinking GPS location icon).
- Frameworks: a turn-by-turn nav system with your destination pre-entered and which is chirping out directions on where you should turn, etc.
- (Server) Platforms (like .Net, Java, etc): a driver-less car/bus that you’re riding along in as a passenger.
jQuery/Dojo/YUI are not a frameworks. They are libraries or tools. At most, they suggest certain ideas, but they just sit there latently, unassuming, unobtrusive to your page/app, but yet provide the utilities you need should you choose to grab them from the toolbox and put them to work.
Angular, Backbone, Ember… these are frameworks. There’s an enormous and obvious difference between a project built in one versus the others.
Other people define these things differently, and find different nuances to obsess about. I don’t care. Save your breath with the nit-picking. At least you know where I’m coming from in this post.
I have absolutely no problem with tools and libraries.
I actually don’t have a problem if you even choose to use a framework… except that I don’t think you should leave a framework in place once you’re ready to go to production.
And that word “ready” is where we likely differ. Because I’d say you’re not ready if you’re still relying on a framework.
Frameworks are awesome for rapid prototyping. In fact, some of them were originally created for exactly such purposes.
But somewhere along the way, I think we got off-track, and we decided that what’s good for the prototype is good for the production app. And so people started designing fancy complex frameworks that were intended from the start to be your production app foundation. This is where we went wrong, IMO.
I think frameworks should be used to rapidly prototype while you are conducting what I’d call “exploratory development” — figuring out the problem domain and how best to approach it. Frameworks excel at making such nimble and quick changes.
As you begin to understand the problem space better, and narrow down on how you’ll solve it, I think you should begin removing the framework bits.
Because abstractions are slow. Abstractions are harder for new people to learn from scratch. Abstractions hide necessary details when bug-triaging. Abstractions hand-cuff you into a certain way of thinking about things, a certain way of doing things.
Ivory Tower of Aloof
I’m sure by now most of you probably think I’m spouting off from some ignorant, aloof, ivory tower type of mentality and that I am ignorant of what the reality on the ground is, you know, in the real world.
Or you’re assuming that I have no idea how to work on teams and that this mindset only works for lone cowboys.
You know what they say when you “ass-u-me”, right?
I’ve spent over 13 years in the (web) development industry. I can’t even begin to tell you how many times I was forced to take code I deliberately intended only as a prototype and shove it into production, and then try to stomach the consequences of when they find out.
Just because that’s reality doesn’t make it right. Just because every boss and client out there insists on this, because that’s all they’ll approve a budget for, doesn’t make it right. Just because all your peers are doing it, and if you don’t, you’ll lose your job, doesn’t make it right.
I still feel bad for all those prototypes I let leak into the production world. There’s an awful lot of code I’m proud of, but there’s plenty more that I’m embarrassed by.
Frameworks are like color-by-numbers for painting. You can paint a nice looking picture color-by-color, number-by-number. You can even learn about painting technique, brush selection, color theory (mixing colors), etc — all that is great to learn in color-by-numbers painting.
But you wouldn’t take one of those paintings, clearly a cookie-cutter reproduction that a thousand other people could have produced, and call that salable art. The color-by-numbers painting you did is going to hang on mom’s refrigerator, not in the art museum. Let’s just be honest about that.
Once you learn how to paint, it’s time to actually paint. Original paintings. Custom paintings. Skillful and talented paintings. Paintings that are uniquely yours. Paintings that specifically capture some moment, some emotion, some experience. That’s how you make a career as a painter.
And that’s how you need to make a career as an application developer.
Patterns & Re-usability
I recently worked on a decently high-profile site with a team of other developers. It was a completely one-off, custom site, with very little chance of needing long-term maintenance beyond the initial release. Actually, each page was sort of its own little micro-site. All together, though, I’d say the site was a pretty good size, at least 20k+ lines of code. So we’re not just talking about a simple marketing page.
The overall site needed many of the basics of organizational architecture, like URL history management, navigation, Ajax’ing of links, templates, events, etc. I built all that. And I did it totally custom, as opposed to pulling out some framework from the popular-o-sphere.
Why? Because I already understood that (architecture) domain pretty well. I’ve done similar “single-page apps” dozens of times. I’m getting a little better each time I do it. I learn new lessons about easier ways to mix the pieces together with each project.
I had plenty of previous code I could dip into. I went and copy-pasted from a variety of previous projects to get me started. Before too long, I had a basic functioning skeleton of a site together. No frameworks.
But of course I had plenty of re-usability, because I already knew many best practices for those various tasks, having done them over and over before.
It would have been silly for me to eschew everything I knew beforehand and start from scratch.
But here’s one of the big myths about frameworks: they’re the only way you get rapid re-use and best-practice patterns into a new project. In other words, if you’re not using a framework, you must be re-inventing some wheel. Bullshit. Know your craft, and repeat what you’ve done right before. And even improve upon it.
The glue I wrote for these various bits was customized to various constraints of my project. But I didn’t need to reinvent how my link ajaxification worked, or how I managed templates, or even how modules communicate through events. This was all stuff I’d done before, so I just rinsed-and-repeated.
You know what I did? I wrote a framework for that site, and I called it “the site”. The other developers didn’t really have any trouble creating new “pages” in my architecture. Routing and page-bootstrapping were as simple as some basic conventions and patterns, which took half a wiki-page to explain. No problems.
And we of course set up some nice grunt tasks to automate any of the sticky parts, to make it flow even smoother.
It wasn’t all perfect, though. As we went along, I realized some of the “architecture” decisions I made weren’t optimal. Neither in terms of performance nor in terms of other developers being able to collaborate quickly. So I had to refactor and adjust. I had to ditch a few things I’d previously used and rewrite them.
But the task of doing such things was way easier since I’d written all the architecture myself. It would have been much harder if I was realizing “you know, Backbone models aren’t working for us, for X, Y, Z reasons, so I’m going to have to hack and customize them in the following 15 ways…”
There’s been lots of blog posts over the last year about people doing exactly those sorts of customization-hacks for all the major frameworks. And the description of the epic journeys into hackdom that these tasks require can leave your head spinning, and thinking “I’d never be able to do that much work to customize a framework on my own project.”
Why does this happen? Because the real world is messier than it appears in that framework’s online documentation. Because that framework had to make certain assumptions for the masses which may or may not fit your needs. Because… we have to adjust.
We have to be able to adjust. In fact, the ability to adjust rapidly is far more important than the ability to rapidly prototype. The stronger the opinions and insistence upon pattern that your “framework” brings, the harder it will be for you to adjust and refactor later.
By stark contrast, however, some of the developers on the team I was working on had never really worked on anything except with actual frameworks. Two of them came from a Backbone background. For their individual micro-site pages, again completely custom interactive (game-like) experiences, they seemed to struggle to understand how to organize their code.
Why? Because I hadn’t chosen Backbone as the overall framework for the site. Backbone seemed overkill for even my complex architecture bit. But it seemed ludicrously over-blown for these tiny one-off pages.
And yet, what they ended up doing was pulling in, for each of those pages, a subset of Backbone. They had mini-models (which were just a few config variables) and a mini-view (which just called out to the basic html templates I had set up). They didn’t even use the part that I like the best about Backbone: events. Because I already had an event system set up in my architecture’s “framework”. And it was perfectly suitable.
See, frameworks can, all too easily, become a crutch. You get so used to the framework doing stuff for you, when you’re tasked with doing something custom and specific yourself, you’re lost.
Here’s another tried-and-true analogy: when all you have is a hammer, everything looks like a nail. When all you have ever done is Backbone, everything looks like a Backbone to you.
Another myth that perpetuates around frameworks is that they’re so useful for teams because they let everyone collaborate together more easily.
True… and false. The “framework” I built for the aforementioned site did just that. But, it wasn’t really a framework, per se. It was a loose collection of good patterns, utilities, best-practices, lightly glued together, just enough for the task, no more, no less.
There actually was no value in picking an established, popular framework for the task, because only 2 of the 10 team members had ever used Backbone before. I’m sure a few others had used other ones, but it’s not like we had 10 hardcore ninja Backboners chomping at the bit to hack some awesome Backbone app together.
No, in the real world, the theory of “oh, everyone’s used Backbone before, this app will be easy for us all to work on” falls flat. Every developer comes from their own background, and your team is a hybrid mixture of various levels of experience. One dude saw Backbone done one way, and another dude saw it done totally differently. Getting those two to work together on a Backbone project is no less difficult just because you picked Backbone.
Whatever framework or “framework” we chose, everyone still had to figure out how to do what they needed to do within the context of the app. The framework was no silver bullet that meant we could all blindly start coding and everything would work perfectly.
Don’t substitute a “well known framework” as a means to code maintenance instead of good and proper documentation (both in code and outside of it).
Well written and architected code does not require a framework, but it seems many people have trouble building maintainable code without them. Don’t be one of those lazy people.
Write code that someone 6 months from now can read code-comments and your wiki pages and have a reasonable understanding of your “framework” so they can get up and going. That’s all you need. Popular frameworks don’t give you that automagically, so they’re not an adequate substitute for well-written and well-documented code.
Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live.
That’s an apropos quote here. But here’s an even better one, IMO:
Write each line of code as if you’re the last human being that will ever see it.
Write code that’s of quality, for the sake of quality, and if someone ever does have to touch that line later, it will be a maintainable line of code by default.
Pain: now or later
What this boils down to is that you almost never start off a project from line 1 of the code with a perfect understanding of how to build it. No framework out there is going to fix that.
What the framework will do is get you up and going quickly. In no time, you’ll have pages and logins and CRUD operations flying about. You’ll have nice looking standardized buttons and forms and multi-select lists galore. Your boss and your client will be happy because they see things quickly evolving, and that lets them get farther down the road of thinking about the problem domain.
They don’t want you to introduce them to any pain at this point. They certainly don’t want you to remind them, “hey we used a framework, it’s probably not sufficient for production, we need to build time into the release schedule for some refactoring.”
But you know what else they don’t want? They don’t want the app to fall over 6 months into production, either due to performance bottlenecks, or lack of flexibility when the problem domain suddenly changes out from underneath you.
THAT is often way more painful, and way more visible.
You’re going to have some pain along the way. Depending on how good you are, that will be more pain or less pain. But pain nonetheless. No magic framework you pick is going to isolate you from it. Put on your big-boy or big-girl pants and suck it up. This is going to hurt.
The question is, when do you want your pain? A little bit at a time, as you begin to refactor your app from the framework-prototype phase into production-ready, or after you have a million pissed off users because of too many Fail-Whales?
I love reminding people of this:
You will lose 100% of the battles you don’t fight. And only 99% of the ones you do fight.
This way of thinking about frameworks as prototyping tools rather than production app foundations is uncomfortable and will piss people off. You’ll have project budgets that get busted. You’ll have unhappy clients who will threaten to fire you.
Yeah, yeah, yeah.
But the more responsible way to act in this industry is to fight the harder battles, to push back and try to get the stakeholders to understand what you’re concerned about.
Your boss and your client don’t understand our industry, they don’t understand how the web platform works. And they will rarely care about such details. They’ll never care if you never help teach them by pushing back.
The 1% of the time when you win such a battle and you get some extra time to do things a little more correctly, and that means pulling some of the framework out and building custom-and-specific code for the task at hand, the overall quality of your project will go up. Just a little bit, but it’ll go up.
The next time you find yourself writing Angular, Backbone, or Ember code… just ask yourself: Is this really production-quality code, or am I just doing fancy prototyping?
The answer may
surprise frighten challenge you.