- Model: Your data as an object
- Controller/ViewModel/Presenter/Whatever: the business logic of your app
View: The HTML templates for your app
But after using a few (Knockout, Angular, Ember, and Backbone) I've noticed there's a forth component. It's the widgety type of logic - logic that isn't about your business, but extents the browser functionality - that cool datepicker, color picker, an awesome visualization with D3, maybe a 3D flip switch intstead of a checkbox. That stuff that is a DMZ to the DOM - Knockout's
bindingHandlers, Angular's directives, and Handlebar helpers. They aren't about how you map your view model / controller to the DOM, but about extending the functionality of the DOM.
Why is this important? Keeping selector strings out of your controllers and view models is vital for the separation of concerns and tesability. Keeping this 4th aspect as the DMZ to the DOM helps to separate these concerns. Say you do have a complicated problem to solve in your app, and you come up with a cool way to visuallize it. You could put it all in one module... but now what happens when you release it and users don't like that widget and they want something more traditional? It will be harder to pull it out. Or the opposite where that widget is really awesome and you want to use it elsewhere... now lots of work to pull the business logic out. Let those two evolve independently and they grow and improve much more rapidly.
Why node.js is Awesome, Part 1: The Single Responsibility Principle
My favorite thing about node.js and the npm community is something that can't easily be put on a spec sheet. It's adherance to the single responsiblity principle.
Take a look at some of the most depnended on npm modules - they're often very small, like mkdirp, which is simply
mkdir -p in node. glob matches files like a shell does. node-uuid just generates UUIDs.
Is there a bug in the module? The module is small enough and tested well that you can dive in and help out, and send the bug fix as a pull request on GitHub. Don't like the design of the module your using, or development died out? Swap it out with a different module, and wire it up to your loosely coupled system.
This is definately a change in culture, as though I didn't use Rails much, but that community likes it's big frameworks that do a lot of magic. Which is nice until you disagree with an aspect of that magic, or need to tweak it or swap it out with something else for this one scenario.
A great coworker of mine once told me "The key to complexity is composition", which I have experienced to be true.