Do Not Learn Frameworks. Learn the Architecture.

I had an interesting conversation some time ago. A colleague of mine stood up for Angular and said that it fastened web development. I’ve developed complex web services for more than 10 years, used to work for Microsoft, and also Spotware Systems in Cyprus. As for now, I create an application for a strartup from the Silicon Valley. All in all, I follow the trends. But I felt like a dinosaur, as I saw no sense in using frontend frameworks, and it turned out to be mainstream. It was 2014, and I plunged into the world of Angular, Knockout and Backbone. If you want to find out what came out of it and why I stopped using them and recommend you to do the same, welcome under the cut.

We all know that Angular has a lot of problems, and debugging is one of the main ones. When undocumented errors occur, only stackoverflow can save us. But we should also find what has happened and, most importantly, where. Backbone and Knockout also have drawbacks. However, a lot of people use them, as their advantages are more important. To be honest, they see no alternative. Although, there is one, but we forgot about it.

Remember the old principle that each module should perform just one function? In case it performs two or more functions, we should divide it into parts. There are plenty of available sources to find out why so and why we should stick to it. Anyway, all the existing frameworks violate this principle. Moreover, a “framework” itself approach violates it. A framework keeps us within certain limits and makes us follow best practices. Only best practices keep developing and a small group of developers simply cannot know what practices suit better for a small promo page, as well as for a management panel with a complex logic of data administration, or a media website with high performance requirements. But a framework disciplines you only if you’re new to programming. My advice is to use best practices and keep frameworks away from work. Let me explain what I mean.

It seems that a framework is something big and difficult to reproduce. But it’s just a set of standard patterns. For instance, the observer pattern is used in Backbone models, as well as in Angular and Knockout data binding, and it produces quite a «Wow!» But it’s just a well-known pattern that we can implement in JavaScript in 30 lines of code, or download one of the thousands of ready-made options (by the way, they’re all the same and differ only in the method name, as the pattern principle is the same). Other components of frameworks are built in a similar way. Understanding the principle, we can often write zero lines of code. For example, when we implement MVP within the limits of a small component, we can mentally divide that these methods are the controller, and these attributes are the model, etc.

An example from practice: I had a job interview for a company in Spain, where I had to finish a test within an hour, in the live-coding mode. The task was to create a single page application for documentation. I performed the task in JavaScript, using module libraries only. I even had time to write tests. They couldn’t understand how I implemented routing, as well as complex interactive elements, and plenty of other things, without using frameworks. They are the guys who have been in the industry for 10 years, just like me, but they studied specific solutions rather than principles.

Studying frameworks, you have to relearn, moving to new solutions that appear all the time, and a part of your experience will be erased. But when you learn principles — they stay. To create classes, I use a library written 5 years ago, the implementation of the observer written around the same time. Each of them performs just one function, and performs it well. I never wanted to change one component to another one, as is the case with frameworks, because the «observer» is the «observer». It is a pattern, not code. Patterns can be combined depending on the task, but they do not change. Another old principle is that code can be supplemented, but not changed. It’s no problem to find its proof on the Internet, or in the books by the Gang of Four. Following this logic, if a framework or a library has a second, third, or tenth version, some functions are removed, others are changed, which makes such product defective. The only good reason for the code change is the adaptation for new browsers, but public methods should not in any way change.

Programming becomes a victim of marketing. They promise us a magic button that will solve all of our problems. As a result, people get used to applying it and cannot decompose complex things, separate the wheat from the chaff. Do I use frameworks? Only when it’s not required to maintain a product in future. But it’s a complete suicide to use them in a service that will live and grow for at least a year or two. During this time, you will write more code, than that of the entire framework, and face its limitations more than once. The time you will spend on writing workarounds and improving things for yourself would be more than enough to implement plenty of necessary components instead of the slow framework. You are not inventing the wheel. In fact, you do use libraries, but combine them depending on the situation, and not in a predefined way. Frameworks can also work with extensions, someone may say. But what if I want to fetch Backbone models according to my API, or not fetch them at all? Or maybe I want to get them from the localStorage? What if there’s a complex logic of updates, depending on the date and flags, and we should send a pool of the same model to another server after the fetch? You never know. Should we use Backbone in such situations? There will be only 5% of its functionality. The rest will be workarounds and custom logic. At the same time, understanding the architectural principles, it’s not difficult to create a solution that will be the best for this very task, and make it resistant to requirement changes, make it flexible.

It is known that most of the time a programmer does not type, but thinks, and thinking in design patterns is useful for efficiency. I usually read public methods of new libraries when I look for interesting architectural solutions. If the implementation is not clear, I can look at the code, but, as a rule, ideas are the most important part here. For instance, we can implement promises within 10 minutes, but what’s the effect? That’s exactly why I’m telling you not to learn frameworks, but the architecture.

P.S.: The article is intentionally provocative. Of course, frameworks have certain advantages, but still, they cultivate ignorance. It’s a shame when someone can not solve a problem without a framework and gets stuck in work for days and weeks. In fact, it’s really simple if we pay attention to the right things, to architectural solutions. That’s what I was trying to tell you about. Hope this article will be useful for beginners, and the described approach will make them cool programmers in the future.

Comments

I agree with you a lot, except there is one problem. Most developers are not as good at architecture as you. You end up needing a framework because you don’t want to repeat yourself. So you invent your own framework and it sucks. Or your boss invents a framework and it sucks.

Sure a framework will eventually die because it can’t keep up with best practices. But chances are it will live a lot longer than your creation because one person or one team will have an even harder time keeping up. At least an open framework has constant feedback from the world.

So I agree learn the principles because they will last but use a framework because it will be easier for other people to come on and learn. Also use those principles to contribute back to the framework and make it better.

Alex, you are skipping over the fact that most programmers who rely on frameworks don’t necessarily rely on them because they think it’s a better solution than to roll out a custom framework specific to that problem space. But rather because they do not have the skill or knowledge to roll that out, or if they do more times than not, it sucks.

They are effectively piggybacking on some of the great minds that have created those mainstream frameworks. I think the problem is creating a framework for every problem space.

One solution could be to create a framework that has the option to pull together a modular set of architectures and components that best fit your needs?

1) junior should never use any framework but try to learn how to make one.
The market is currently overwhelmed with junior developers who don’t even know the basics of programming, what to speak of writing clean JS.

2) frameworks answers some needs, not ALL MY needs.

3) most low level micro-libs don’t require more than a bunch of commit every 6 months.
If you don’t believe me, just check any good micro-libs code, there’s not much changes over the time.

I performed the task in JavaScript, using module libraries only. I even had time to write tests. They couldn’t understand how I implemented routing, as well as complex interactive elements, and plenty of other things, without using frameworksCan you share the source.

This article pretty much wants you to be a «real man» and do everything from scratch. The real world doesn’t work this way.

Let’s face it, everybody has their own coding styles and design style. Crap in someone’s eyes will be gold for someone else. Frameworks help everybody by enforcing best practices everybody needs to adhere to, so a developer can pick up another developer’s unfinished work in a jiffy. (wow, I sound old for using that term) Rolling out your own «framework» may work if the project’s just you, you and you, but anything outside of hobby projects will see multiple developers trying to work on the same thing. Save everybody’s time by adhering to a standard that everybody knows already.

While programmers should have architecture design knowledge under their belt, I’d rather not invent the wheel. If you have to shoehorn your problem into a solution, you’re doing it wrong. This should be the article’s real focus, but the author wrote it as if frameworks are evil.

I’m not only agree, but even try this in practice, with extension to the language used instead. I’m using my highly customized vim with snippets, that works among languages I use — particularly golang, ruby, javascript and clojure. All those languages have the same structure in some vay — they all have functions, structures and interfaces, all have for, switch, if-else blocks, all have boolean, number and string types, composite types like arrays and maps, all have map-reduce functions, all have import headers blocks. And the most interesting part is that they all implement gof patterns in some way (ruby/clojure may vary a lot actually — there’s a special theme for functional-programming patterns for those who interested). So I end up writing snippets that have equal names for all the languages for language structure itself and for basic patterns. Now, yes, there are some distinctions between languages (say clojure may vary from golang alot), and for each language I have additional snippets as well, but the basic one are the same. Its not only increases speed of prototyping solution in different language in times, but also increases understanding the differences in programs and language-styles in solutions between language you use.

I actually want to make smth similar to web frameworks I use now — for example express.js and rails: route defining, model creating, controller creating and so on.

Great article.
You hit the point. I am working on Ember.js framework for almost 8 months, now I am familiar with it. But in case ember doesn’t support something, I will change my logic and do it in a dirty way. Never bothered what it does under the hood.
Surely after reading this post, I will try to dig the design of frameworks.

Good stuff.
Studying frameworks, you have to relearn, moving to new solutions that appear all the time, and a part of your experience will be erased. But when you learn principles — they stay.
What do you exactly mean by learn the principles? Do you mean to say learn GOF design patterns??

Nice article.
Alex, I am a beginner, have been trying to pick up coding for over 3 months. I always see these frameworks that look good at the first glance, but if I try to deviate from the given way, I always get totally stuck.
Do you have any advices where to learn coding from and how to avoid all this clutter?
Thx

I’ve used frameworks since Rails in 2006 — I remember spending quite a bit of time before that debating how to build a database access layer for our .NET apps, tools like Rails, Meteor remove that layer of the debate from the team.

I wouldn’t want to be the developer who inherits your code, Alex. Not saying it’s bad, just that it would take a lot of time to understand, and if I don’t agree with some of the architecture, I’d imagine it’d be hard to change, since it wasn’t built with modularity in mind like frameworks with package systems do.

Are you kidding? Frameworks are bad? Frameworks are a collection of patterns and practices for common problems and tasks that developers don’t want to write again and again and again. They enable experienced developers to develop faster without reinventing the wheel and they help junior developers create applications far beyond they’re experience would normally permit. I agree they are no substitute for understanding the underlying patterns, but that is no reason not to use them. I understand the patterns and could assemble my own collection of modules… Or I could just pick a framework that covers 90% of a projects needs and write modules to cover the other 10%. And show me a framework (other than ember.js) that doesn’t let you pick and choose what modules get included.

Great article. I definitely agree with the idea of investing more time in learning architectural patterns, but the irony here is that you CAN learn architecture through existing frameworks. While it’s important to learn vanilla architectural patterns, they become more apparent in HOW they could be used when assessing new frameworks and making the correlation between the low-level pattern and the high-level use case. I think it’s important that we keep a balanced palette of our knowledge so that we can be creative problem solvers and approach our thinking with a range of references.

Most of us work with strings one way or another. There’s no way to avoid them — when writing code, you’re doomed to concatinate strings every day, split them into parts and access certain characters by index. We are used to the fact that strings are fixed-length arrays of characters, which leads to certain limitations when working with them. For instance, we cannot quickly concatenate two strings. To do this, we will at first need to allocate the required amount of memory, and then copy there the data from the concatenated strings.