Learn concepts, not frameworks
Software development is a complex task and today it is characterized by the use of third-party libraries and frameworks. Unfortunately learning to use them may not be the best way to improve as a programmer. So what to do instead?
Introduction
A while ago I worked together with a colleague on a JavaScript project and noticed that most of his code was pure vanilla JS, instead of using a library or a framework. I asked him why he did that, and he told me a surprising answer.
I’m pretty new to JavaScript, and I’m trying to understand the concepts of the language.
I asked him what that exactly means, and he responded, that everytime he learns a new technology he tries to learn new concepts and understand the way of thinking that underlies. This would be much more important than knowing an awesome framework.
The simplicity and truth of his answer changed the way I think about programming forever.
What are concepts?
To me concepts are all things that show similarities in multiple technologies. There are small concepts, that can be explained in a few words, e.g. loops, there are big ones that fill whole books and include subconcepts, e.g. Object-Oriented Programming (OOP) and there are some in between.
What’s wrong with learning a framework?
Nothing in general. Frameworks and libraries save time and energy, if you understood the core concepts of the language, they are written in. Especially if you work in a team and need to be productive, using frameworks will likely improve your workflow. However, there are some things, that you should be aware of. Frameworks…
- can be hard to learn
- tend to get outdated
- are often very specific and opinionated
So a lot of the knowledge you gain, cannot be transferred in either way. The problem with that is, that too specific knowledge is less helpful in the long run. So if frameworks are not the best thing to improve, how about learning a new programming language?
Learning a new language in less than 4 weeks?
Experienced software developers learn a new language in less than 4 weeks, right? Despite that is not entirely true, it gets to the heart of the matter. Why is an experienced developer able to learn a new language in a few weeks, while it takes beginners months or years? Often the answer is experience and practise, but I also met developers, that have been working in the business for more than 10 years and were not able to achieve that. So it seems that experience and practise is not the whole truth… What about passion? Some of these guys were absolutely passionate about what they were doing, and it did not help much…
I personally think, that concepts play a big role here. Mastering different concepts accelerates the learning process of other languages significantly. So, if someone strictly refuses to learn them, experience and practise or passion may only be of little help. The question is, how to find out, what a concept is and whether you should learn it.
Simple concepts tend to be obvious, right?
Let’s say you give a total beginner the task of outputting the numbers from 1 to 5. A person that is not aware of a concept called loop, would maybe happily write the following:
console.log(1);
console.log(2);
console.log(3);
console.log(4);
console.log(5);
While the code is formally correct, there is obviously a more elegant way to solve this problem.
for(let i=1;i<=5;i++) {
console.log(i);
}
Now, if you really understand the THINKING of JavaScript and the concept of Function Chaining, you could also come up with something like this:
Array(5).fill().forEach((_,i) => console.log(i+1));
While the for
loop is obvious to most developers, the function chaining approach maybe not.
More sophisticated concepts
Loops are present in nearly all languages but there are more sophisticated concepts, that fewer languages provide. Pure PHP
, JavaScript
or Python
developers may never have used Generics because of dynamic typing, but although they are supported in C#
, Java
or TypeScript
it is possible to completely work without (although you probably shouldn’t). In fact many Java
or C#
apps I’ve seen did not include this concept in any way. It has also been one of the most wanted features
for Go
, so something has to be important about it. Tutorials about Generics often use enumerable or lists as opener. In JavaScript for example generics are not required because of dynamic type determination. An array is allowed to contain different types:
["1", [], {}, 2, null, undefined]
In C#
this is not easily possible - or at least not recommended (code smell). You are limited to one single type, or you have to use a common boxing type like object
:
var oddNumbers = new int[] { 1, 3, 5, 7, 9 };
# without generics this will work, but its slow and a code smell in most cases
var oddNumbers = new ArrayList();
oddNumbers.Add(1);
oddNumbers.Add("3");
oddNumbers.Add(new TestClass());
To use the same implementation for list helper functions (e.g. add(...)
, filter(...)
or map(...)
) for different types, you could take advantage of generics. These instruct the compiler to prepare the code for a specific type:
# generics prevent adding other types than int
var oddNumbers = new List<int>();
oddNumbers.Add(1);
This results in faster runtime, and most IDEs support type checking and linting out of the box. Of course Generics are much more powerful than that, but it would go beyond the scope of this article to explain them in detail… you should just get the idea.
Overarching concepts (e.g. compile-time vs runtime)
There are also overarching concepts, that apply to nearly all languages. They are especially helpful to define non-functional software criteria, like Performance and Security. One example is compile-time vs runtime. Compile-time is the time the source code is converted into an executable. Runtime is the time the executable started running.
Why is this concept so important? Well, understanding that things that can be done or checked at compile time no longer need to be done or checked during runtime will probably change your mind about compiled and strongly typed programming languages. Rust
for example is a compiled language packed with concepts and features, and the compile-time checks are very good. Writing code, that successfully compiles is pretty unlikely to crash or show side effects in production.
If you’re thinking that this concept is not important for interpreted languages like JavaScript
, you probably will be surprised. While most of the modern JavaScript frameworks parse frontend templates and render at runtime, Svelte
does a big part of this at compile time, which means the resulting code it is smaller and faster by design…
You see that understanding this concept might be pretty helpful, even if you don’t expect it to be.
Concepts of a new language and the way of thinking
If you learn a language and try to get in touch with its concepts, you surely should take a good look at the documentation. Most languages tell you what they are all about, why they use specific concepts and often why they are not using others. However, even if the documentation is very good, there is often a lack of good examples.
Remember, what I said about frameworks? There is a big difference in only USING them, and UNDERSTANDING their inner workings and code. That’s why I think there is a hidden gem in all well established frameworks… reading the code of a framework and trying to reproduce the features in your own way will pretty likely lead to a good understanding of the underlying core code concepts.
Did you ever take a look at the code of Vue.js (JavaScript), Laravel (PHP) or Spring boot (Java)? As a beginner, you should maybe start with smaller ones, but I’d bet you learn a lot while reading and understanding the code of frameworks…
Transferring concepts to other languages
Sometimes it is also interesting to transfer a concept you know to a new language you are currently working with. This is especially true for overarching concepts. A real world example: When I started to use C#
, I used Exceptions for most of my error handling - even if it was not really appropriate, I did not now a concept that fitted better. Then I read an article about the awesome error handling in Rust
and since I’m not a fan of Exceptions I thought: What would happen if I try to port these concepts to C#
? This idea led me to OperationResult
- seems that someone else already had this idea. Using this library not only led to more appropriate error handling in some of my use cases, but reading its source code made me aware of other interesting concepts in C#
:
using static
struct
implicit operator
For me, it was totally worth the transfer…
Which concepts are good to know?
Well, probably all of them… before the conclusion I would like to give you some input for the search engine of your choice. Here is a list of things, that may be worth knowing about - without any claim to completeness, there are many more:
Basics
- Types
- Variables / Constants
- Comments
- Operators
- Control flow
- Loops
- Destructuring
- Arrays / Lists
- Enums
- Functions
- Lambda expressions / Closures
- OOP (the whole thing, including classes, interfaces, scope, etc.)
Overarching concepts
- Compile time vs runtime
- Error handling
- Caching
- Date, Time and Timezones
- Float vs. Decimal
- Reactive programming
- Aspect oriented programming
Tooling (often related to overarching concepts)
- Debugger
- Profiler
- Benchmark
- Compiler / Transpiler / Interpreter
- Package managers
- Linters / Formatters
- Unit-Testing / Code coverage
- Acceptance testing
Language Specific
- Regular expressions
- Generics
- Macros
- Exceptions
- Reflection
- Annotations / Attributes
- Async / await
- Events / Delegates / Responder chain
- Namespaces / Packages / Modules
- Traits
- Structs
- Multithreading / Go Routines
- Interfaces
- Iterators
- Channels
- Borrow checker
- Nil / Null / Zero-Value
- Pattern matching
Conclusion
Concepts are good to learn, even if they don’t fit your needs or may lead to overengineering. That is part of the software lifecycle.
Programming languages are tools and if you don’t like its concepts or thinking, it may be subjective. Rants may be fun to read and may also contain some truth, but most of the time, they are not helpful (JavaScript
and PHP
often become victims of a rant).
Trying to be professional about opinions and subjective quality estimations regarding programming languages is one of the skills, I’m still working on. So maybe this article helps you find the right tool for the job by just knowing about what a specific language is all about and what alternatives are out there.