We have framework fatigue
A short while ago, I gave Angular a bit of a hard time, and although there were mixed reactions, one thing that stood out for me when all the objections and agreements had settled, was that most developers don't know what they really want from a framework, other than it needs to be easy! Most just accept the status quo and bend to the will of the behemoth they are trying to tame, when in fact, it is them being tamed – all the while making compromises that should not need to be made.
So some just throw their hands up and resign themselves to using what they've used before, or what they're told to use by others more senior (but no less disillusioned) on their team, or worse, what they're told to use by their boss who has almost no technical background.
However, as the complexity grows, which is the case with any app that lives long enough or is useful enough, the inevitable conclusion is the same – you’ve either rolled yourself a nice big ball of mud there, or you've gone ahead and rolled your own framework.
Rails is a perfect example of where this was particularly well done, and as a result, people use it to build all sorts of applications that were never intended by the original design. Given its room for manoeuvre and flexibility, Rails has been able to weather the storm thrown at it from all angles. Of course, there are issues that crop up from time to time, but Rails has been largely successful over its lifetime so far.
Favour convention over configuration
Since then a number of frameworks, products, libraries and more, have adopted the notion of making assumptions about the commonalities most developers would choose. They build those in as defaults, and unless tinkered with, it will hit the ground running in default mode and probably just work. This convention-based model is a great time saver and can go a long way towards making sure the framework stays out of your way, which I’ll go through in more detail later.
But I still see way too many frameworks falling back to configuration where none should be required. Unfortunately, this is often due to poor architecture, and lack of foresight in being able to swap out pieces of the system, which I’ll delve into next.
Be modular so that I can change you
It’s a good thing being able to configure a framework, and even better when those configurations fall back on conventions, but being able to swap out parts of a framework, or better yet, leave them out entirely is crucial when it comes to building web apps today – especially with the explosion of mobile devices. Not everybody is on a blazing fast internet connection and can afford to download a ton of script required to prop up your framework.
Modularity for the sake of size is not the only reason though. The development cycle costs money, lots of it. In order to save money (especially in start-ups) it pays to keep the development cycle tight and efficient. Working with a modular framework allows development to be more easily compartmentalised, and allows new team members to grasp that part of the work more easily by being exposed to a shallower learning curve.
Another reason for a modular framework is when you like many things about it, but fundamentally disagree with certain parts for whatever reason. This has been known to happen – dependency injection, templates and binding just to name but a few – and can quite often turn what would have been a symbiotic relationship into a soul-sucking nightmare.
Plugins also obviously fall into this category. If the framework is modular, it stands to reason that many of its components would have been built as plugins themselves thereby fleshing out a model which other developers could adopt to expand the ecosystem, because the points of integration are already there. React components are an incredible example of how this idea can take off and really bring cohesion and momentum to the community as a whole.
Have strong opinions, but weakly held
What do I mean by that? Well, if you've heard about frameworks being opinionated, what that should translate to is that they favour convention over configuration as well as a good modularity story as I spoke about above.
But it’s more than that.
Opinions are exactly that – opinions – they are statements made by one party, but not necessarily agreed with by all. They are not doctrine. Doctrine cannot change, opinions can. They are malleable, and with enough persuasion or evidence, they will alter their point of view. That is what I mean by weakly held.
The framework builders will aim to guide you by supplying best practices and optimizations in such a way that you will fall into the pit of success if they can help it. The framework builders believe that this is the best, most efficient way to use their framework, but as is too often pointed out, the builders cannot possibly know all situations or environments their code is put to work. Sometimes their way is not the best way, and we need to be able to change that opinion.
If you happen to work in an environment that strictly controls the way that HTML mark-up is written and validated for example, then any syntax that a framework forces you to into, that violates XHTML standards, would need to be substituted for another syntax, otherwise you could not use the framework.
If the framework cannot accommodate that, then it is not opinionated, it is simply rigid, like an old man yelling at you to get off his lawn when you are clearly there to cut the grass. Not willing to give up its ways, the framework forces you to compromise on your standards (company or otherwise) and possibly even your overall quality.
If I want to use React to manage the binding and rendering on a particular grid of data in my app because of its size or complexity, and I need it to render fast, then swapping out at page level should be straightforward. I shouldn’t necessarily have to do it for the whole app, but rather choose the best solution for the situation that presents.
Situations like these crop up all the time when building apps. If we are using a rigid framework, we are required to apply countless workarounds and even hacks to appease the framework. We are not given the option of doing what we decide is best, and that is not strong opinion, weakly held – that is doctrine, which inevitably produces a great big ball of mud.
Stay out of my way
Conventions, modularity and strong opinions all sound like good selling points a framework should have, but this my friends is where the fine balancing act comes in. You see, the flip side of that coin also has a name. Can you guess what it is? That’s right; it’s called the learning curve. Naturally, the more conventions, points of integration and opinions a framework has, the steeper the learning curve imposed on the developer.
Now, I’m not a big fan of learning curves for the sake of learning curves, especially when it comes to on boarding my teams. If you are going to force developers into a specific way of doing things, either syntactically, or architecturally, you need to make sure it isn’t obtrusive and that the developer can elect to do it a different way should they choose to put in the work.
One can expect a certain amount of framework markers to pepper the code and mark-up in your app, but you would hope that they remain on the periphery as much as possible. It is not unheard of for teams to port entire apps from one framework to another; in fact, it is quite common. Any framework that makes this difficult to do is by definition, going to get in your way.
It is likely that you are writing more code to please the framework, than you are for building your app. Frameworks that do not do this are more likely easier to port away from, but by the same token, you probably wouldn’t end up doing that because it is not getting in the way of writing app code. So ironically, making it easier to port away actually ends up building more loyalty.
Aurelia is a relatively new framework, but built on top of mature ideas, and is a perfect example of this point. It is convention based, has incredible modularity and exercises many malleable opinions. This is especially true when it comes to their data binding system for example:
Two-way binding is bad I hear you say
No problem, force everything into one-way binding using built in conventions, knowing that you will need to handle some rendering or persistence manually.
I don’t like the way it binds at all, not the syntax, nothing!
It’s not fast enough I need more speed!
I'm talking about all incredible things that some of the smartest folks in this field are coming up with here and now, with an eye on the future. I'm talking about ECMAScript 6 and 7 and onwards, all right all right, ES2015 if you insist.
We already know about the incredible work that transpiler teams such as Traceur and Babel are doing which allow us to clean up our code and write for the future, now, while deploying on yesterday’s landscape of browsers and devices. This was not impossible before transpilers, but incredibly prohibitive, as you had to tweak the hell out of your browsers (if they even supported the features). However, transpilers have brought the beauty of this to our developer teams here and now, with minimal fuss, and there’s no excuse not to use it going forward.
If you’re going to throw annotations like CoffeeScript or TypeScript into the mix, then that’s all for the good, but for the love of all that is holy, please make it opt-in. Not everybody has drunk that particular Kool-Aid just yet, and you won’t be making any friends forcing it down people’s throats. I’m looking at you Angular 2.
Coupled with transpilers, I’m also talking about the testing, packaging and deployment solutions out there today which have enabled us to automate our lifecycle thoroughly. The Npm’s, Gulp’s and Grunt’s, Jasmine’s and Karma’s of the world must be embraced to complete the lifecycle.
In addition, don’t tie us to a specific back-end technology by making assumptions. Just as there are many front-end frameworks, so too, do we have a huge variety of back end providers – especially in this melting pot we’ve created. It could range anywhere from Node, to .Net, to Python, Ruby, PHP, Scala, Firebase, and even COBOL for crying out loud! Touting your framework as Isomorphic or whatever, when it is actually only applicable to a minute fraction of back-ends doesn’t help your cause, and can hardly be considered a feature. Be honest about what your framework is capable of, where it fits best if it has a particular niche, and help us as developers to make that decision of which framework to use for our purpose that much easier.
Images courtesy of gizmag.com, architecturelab.net and 2gbuildingservices