The first fully client side application I built was the Codepen equivalent for PHP. It was for a college assignment where each of us had to help our classmates learn a few simple things about a language we were interested in.
I built a sandbox in a web based UI where you hit a run command to execute PHP rather than having everyone get an entire dev environment setup. My “lesson” ended up being way more productive.
The first job I landed out of college was around the time Backbone and Angular were gaining popularity. Our shop went with Angular. I remember feeling a surge in productivity as we built our greenfield product.
But this was a big app with a ton of complex business logic. Things started getting more difficult to implement the further along we got. It was easy to describe the logic to each other, but coding it became progressively harder as the app grew.
There’s a hilarious expression that came out of Bell Labs in the 80’s called the 90-90 rule. Not to be confused with the 90-10 rule. The 90-90 rule states “The first 90 percent of the code accounts for the first 90 percent of the development time. The remaining 10 percent of the code accounts for the other 90 percent of the development time.”
It felt like we were experiencing the 90-90 rule first hand. I’ve also experienced this phenomenon for almost every other project I’ve worked on in this industry since. The one thing all of those jobs had in common? A heavy usage and dependency on web frameworks.
I’m not going to blame causation for the phenomenon entirely on frameworks, but in my experiences it felt like they had been a large contributing factor. The issue with frameworks is that they get you going fast for building the foundation and the MVP. That first 90% is the most velocity your team is going to show in the lifetime of the project while using the framework.
Then you need to start adding in the business logic and realize there are architectural issues with your foundation that will make adding these features very hard. In engineering this happens all the time. The normal reaction would be let’s refactor or rebuild this piece of foundation to support these new structures. But with frameworks sometimes that’s just not possible.
With frameworks, sometimes that foundation is part of the library itself. And this is a big problem if you want to continue making steady, predictable progress on your project. You’ll implement a clever hack to get around the framework and support the new feature, but the difficulty only compounds. Now your clever hack is being used to hold up two things, then three things. Eventually parts of the application start to feel like a game of Jenga.
If you’re trying to go fast and delivering the first 90% to your customers meets business needs, maybe rapid progress makes sense. But if this is a project that’s going to span several years and is expected to deliver a consistent backlog of features - using a framework might start to really slow you down at that 2 year mark.
At this point engineers usually kick up a fuss about needing a “rewrite” and make a pilgrimage to the next promised land - ironically a new framework - and the cycle continues.
At enterprise companies with projects that span many years you will eventually see a custom framework emerge for something. That’s because their foundation will be incrementally engineered over time to support business needs first.
Hopping from framework to framework gets eliminated as an option very quickly at enterprise companies because they’ve learned it doesn't work. So when an enterprise company notices an open source framework stops supporting the needs of the business, a very senior engineer comes in and builds something custom that will.
So what is the lowest common denominator in functionality that all of these frameworks share, both open source and custom? The answer is state management.
State management instantiates and destroys a collection of components and services. Nothing else. Many frameworks go further than this to enforce patterns for how you manage data, write components, declare your routing etc.
What I have yet to see is a mainstream framework that only offers state management and is flexible enough to meet the growing needs of both startups and enterprises.
I’ve been building GibbonJS organically over many years. During each project I would tweak the framework to be a little more flexible so I could satisfy the business requirements. Over time the framework grew smaller, not bigger. I kept chipping away at features to get back flexibility until all that remained was state management.
GibbonJS is starting to feel finished because I haven't run into a use case for while where the framework wasn’t flexible enough for it. With GibbonJS the friction I would normally feel at the two year mark on a project is gone.
I think the flexibility comes at the cost of initial velocity and overall maintenance, but for the projects I tend to work on it's better than hitting walls you can't work around, or settling on some really ugly solutions.