Libraries vs Frameworks
We love the work that we do. We love coding and programming. It is like opening a brand new puzzle everyday and spending the time to solve that puzzle. We have contributed to a variety of projects ranging from building a monolithic application using closed source product like WebSphere Commerce Server – WCS (probably not the best use of our expertise), and worked on open source projects. The most rewarding projects have been the ones using open source software, it is like building a Lego structure without the instructions.
In the past few years, our concentration of work has been front end development. We have been an avid consumer of all things JavaScript, HTML, and CSS. We have written code using “vanilla” JS, jQuery, KnockoutJS, BackboneJS, AngularJS, and ReactJS + Flux. We have also been looking from afar at CSS frameworks like Bootstrap and Foundation. I am a bit concerned about the direction the development of frameworks for the front end, albeit JavaScript or CSS, are going.
TL;DR
Frameworks provide an illusion of expediency, solving common issues, and handling common processes. However, that illusion is shattered the moment that you try to go beyond the “frame” of the framework. It is the “one-size-fits-all” illusion that leads to the building of a monolithic application that is disconcerting.
This is not a post bashing any specific framework. However, as our technology is advancing in the speed that is at times hard to keep up with, we do need to take the time and step back and ask the question “are we going in the right direction?”
The Rise of the Monoliths
After reading Jimmy Breck-McKey’s post on “The State of JavaScript in 2015” (which as of the date of this post, January of 2016, it is still very relevant), I was inspired to rethink my attitude and reliance on frameworks.
The Model-View-Controller (MVC) pattern is something with which we are all familiar.
Model–view–controller (MVC) is a software architectural pattern mostly for implementing user interfaces (but not only for user interfaces). It divides a given software application into three interconnected parts, so as to separate internal representations of information from the ways that information is presented to or accepted from the user.
Before the prevalence of Ajax (Asynchronous JavaScript and XML), the separation of the Model, View, and Controller of the application accomplished two major tasks:
- It introduced some sanity to the complex applications that were being built.
- It provided another level of abstraction to be created for each segment and therefore introducing some efficiencies to the code.
With the increased use of Ajax, the MVC pattern was also applied to the front end. As the complexity of the front end increased, the separation of concerns in the front end became more and more important.
With the increase of the front end technology, we had the opportunity to remedy our past mistakes. However, by and large, we failed in accomplishing in improving from our past mistakes and we simply transferred some of our existing flaws from the server to the client. While we made monolithic applications on the server in the past, now we make monolithic applications on the client side.
My Framework === My Interpretation of JavaScript
Part of the problem is with the flexibility and malleability of JavaScript. Although these are the exact reasons why we love JavaScript, we are responsible to shape this flexible tool into a product that is not only useful to our immediate need but also can be used by others.
With great powers comes great responsibilities
One of the reasons that the JavaScript community has so many frameworks, I believe that these frameworks are one’s interpretation of how JavaScript should be written and how it should handle the common MVC tasks.
AngularJS is Java’s interpretation of JavaScript. EmberJS is Ruby’s interpretation. KnockoutJS is .NET’s version. Some framework’s are an individual’s or a team’s interpretation of how JavaScript should be written. This post is not a judgement on any of these frameworks. Most are great and have been the backbone (no pun intended) of some great web applications. Nevertheless, there are some aspects of frameworks that, in my humble opinion, are steering our community in the wrong direction.
Magic
There is a certain amount of “Magic” that comes with each framework. These are the processes that are accomplished in the bowels of the framework, in areas of the code that only the brave dare to explore. This so-called magic is not the problem, it is the reliance on it that causes issues. Developers have come to depend on the framework to do the work and therefore relieved themselves of the responsibility of learning about the tool that they are using.
Some developers have claimed “there is no need to know EVERYTHING about a framework, I don’t need to know how the engine works in order to drive the car”. While this statement is true, the moment we go beyond the demo instances of the framework and delve into a more customized instance, we have to become more aware and comprehend the framework at a deeper level. There is also the rise of “leaky abstractions”. This is when the framework misbehaves and does not do what we want or expected it should. Your quest through the internets i.e. Google, Stackoverflow, and forums have not resulted in any solutions. Now you will have to look into the implementation of the framework. To follow our analogy, we have gone from the driver to becoming the mechanic.
The magic also has some other side effects. Aside from providing a crutch for some developers, it has also created some unrealistic expectations for some product managers. I have had some product managers in the past ask me to “just bring in <insert framework here> and <insert an UI library here> and you should be able to build it quickly”. Oh, if it was that easy!
I think we must dispel the notion that “Accio <insert framework here>!!” is applicable.
Heavyweight
Frameworks have the attribute of “all or nothing”. This means that most frameworks come with a series of tools, whether you decide to use them or not. Normally this will not be a huge problem however with the need to support multiple devices and the variety of bandwidth that is available to us, the weight of what we put in our applications becomes significantly important.
AngularJS (1.x) is ~143KB, AngularJS (2.0) is 566KB (766KB with RxJS). EmberJS is ~435KB (EmberJS relies heavily on HandlebarJS ~156KB and jQuery ~32KB). ReactJS (v 0.14.5) + React DOM ~133KB.ReactJS (v 0.14.5) + React DOM + Redux ~139KB (source). Although there are some techniques like minification and gZipping that can help with some of the size/weight issues but it does not take away from “all or nothing” aspect of frameworks.
So when we “just bring in <insert framework here> and <insert an UI library here> and you should be able to build it quickly”, we are downloading the equivalent of the blue prints for a skyscraper only to build a two story building.
Do it my way
Many frameworks are “opinionated”. This means that by adopting the framework, you will have to write the code as the framework dictates. AngularJS for example is HTML-centric requiring the starting point to be HTML with JavaScript injected into it. EmberJS on the other hand believes in convention over configuration.
These opinionated frameworks have some good advantages i.e. well structured code, homogenous code, easy on boarding of new resources, and an up to date toolset. However, there is one major disadvantage and that is that adoption of these frameworks is a one way street that has a very costly u-turn. Going from the initial adopted framework to another framework can be very expensive in time and resource.
Libraries > Frameworks
In 2003, I started working on a project at Staples which we migrated their business-to-business web application, http://www.stapleslink.com (now named http://www.staplesadvantage.com), from net.commerce to WebSphere Commerce Server (WCS). After the migration was completed and once we were in maintenance mode, subsequent upgrades of WCS resulted in an extensive project that required a lot of time and resources. These were the side effects of using a monolithic application/framework. Its specialized structure and opinionated infrastructure were the reasons behind the slow development, resulting in some massive technical debt.
I have not worked in such a closed and restrictive technology infrastructure since 2009. I have enjoyed using and learning from the open source community ever since. However in 2014, the Angular team made the announcement regarding the drastic changes to the 2.0 version of the AngularJS framework with a cumbersome direct migration plan from the 1.x version. Aside from the anger that rose from this announcement, a lot of my previous experiences and challenges with maintaining a monolithic application also rose to the surface. I saw a lot of similarities between the WCS monolithic application and the front end monolithic application.
Small Libraries to the rescue
As experience has shown us, a monolithic application should be avoided. The “all or nothing” aspect of some JS frameworks could steer us towards monolithic applications on the client side. This is why I believe moving towards small libraries is a better approach.
By using small libraries – components with a dedicated purpose and a small surface area – it becomes possible to pick and mix, to swap parts of our front end stack out if and when they are superceded. New projects can replace only the parts that matter, whilst core functionality whose designs are settled – routing APIs, say – can stay exactly the same between the years.
Libraries stop being an all-or-nothing proposition. What if you like Angular’s inversion of control containers, but hate its data binding? No problem – you can just choose what you like from NPM and get going right away. You can move your legacy projects (read: the ones that make your employer money) to new technologies incrementally, rather than rewriting everything, providing you stick to good practices and wrap those libraries carefully.
Jimmy Breck-McKey “The State of JavaScript in 2015”
Looking at AngularJS, we get the following with each download:
- Angular.js (core AngularJS code)
- ngAnimate
- ngAria
- ngCookies
- ngLocale
- ngMessageFormat
- ngMessages
- ngMock
- ngResource
- ngRoute
- ngSanitize
- ngScenario
- ngTouch
Whether we need it or not, we will be getting these features with AngularJS. If we do not have touch support, we are still getting it. ngCookies will be handle the Angular way, whether we like it or not.
However this framework can be broken down into its core piece with all other supporting processes represented as stand alone libraries.
The beauty of this approach is that the developer can decide to use the core framework and all its supporting libraries or replace any of the libraries as needed.
This approach will reduce the inflexibility that comes with some of these frameworks and opens the door to the creation of more robust and specialized libraries that can be injected in the application as needed.
ReactJS is moving in the right direction
ReactJS took the correct approach of creating a library targeting the View, the “V” in MVC. With this approach, ReactJS can be inserted where it is needed, stand-alone or in conjunction with another framework like AngularJS. Going a step further, combining ReactJS with the Flux pattern makes the client DOM creation and interaction a much more intuitive process.
This intuitive approach could be the reason for the quick and vast adoption of ReactJS among developers. Satiating our craving for small libraries working together to build the final product.
Final Thoughts
Recently, I watched a TED talk by Young-Ha Kim, a Korean novelist, titled “Be an Artist, Right Now!” In this talk, he explains that Roland Barthes once said of one of Gustave Flaubert’s novels:
Flaubert did not write a novel, he merely connected one sentence after another. The eros between the sentences, that is the essence of Flaubert’s novel.
I believe that development and code is art. We are merely trying to communicate our art one sentence (or function) at a time and merely connecting one after another.
As we approach a project, the starting point/starting paragraph sets the tone of the novel. A prime example of this is Franz Kafka’s first paragraph from his novel “Metamorphosis”:
As Gregor Samsa awoke one morning from uneasy dreams he found himself transformed in his bed into a gigantic insect. He was lying on his hard, as it were armor-plated, back and when he lifted his head a little he could see his dome-like brown belly divided into stiff arched segments on top of which the bed quilt could hardly keep in position and was about to slide off completely. His numerous legs, which were pitifully thin compared to the rest of his bulk, waved helplessly before his eyes.
It is very bold to start a novel with this paragraph. All other sentences and paragraphs that follow the initial paragraph work to maintain its integrity while building upon it.
The product/application that we are building is our final novel, let’s make sure we put the right words that lead to the best sentence which will justify the starting paragraph and create an awesome novel/application in the end.
Here is the full TED talk by Young-Ha Kim: