Christian M. Mackeprang

Web development and computer programming

Being a versatile hacker is becoming more important than knowing frameworks

Back around 2013, the term Full Stack developer started to come up in job descriptions and blog posts. Companies were realizing that hiring developers with expertise in only one language just wasn’t enough anymore. A web developer that can handle a variety of tasks and environments is considerably more useful, and was starting to become the norm.

In spite of this, knowledge about web architecture itself did not become widespread. Many developers have been building websites without having a good grasp of how things work behind the scenes. Web forms, caching, the HTTP protocol, Apache. All of these were secondary good-to-haves.

How e-learning affects the job market

Perhaps as a consequence of the online learning boom that had started a few years earlier, the self-taught web developer knows surprisingly little about the web’s underlying technology. Language-oriented courses cannot cover the complete web stack, and students will end up clueless about what an htaccess file does, or how to restart a Unix daemon, or how the different types of POST encoding work.

What is a full stack developer supposed to know, anyway? Job descriptions frequently mention combinations of frontend and backend technologies such as JavaScript and Node, PHP and jQuery, Angular and Spring, and many others. In reality there is a significant amount of information outside those realms that would improve someone’s ability to build a website, and gone are the days when you could stick with what you know and make a career out of a single technology.

The future of web developmentIf sticking to your guns won’t suffice anymore, then what can we do, and how can we keep up with the exponential multiplication of web libraries? There is so much software being released today, that the number of possible combinations between technologies is increasing very rapidly. This combinatorial explosion will drive software development into a more ad-hoc territory. Your chances of knowing how to integrate two random libraries X and Y are ever diminishing, and any help that googling can provide is diminishing at the same rate. The window is about to close, and a time will soon come when we’ll be required to figure these tough problems out on the spot, every time. Not something for the lazy ones among us.

Hackers: the antifragile programmers

I was introduced to this very interesting concept in an article by programming rockstar John Carmack. It’s described in the following quote from the Antifragile book:

“Just as human bones get stronger when subjected to stress and tension, and rumors or riots intensify when someone tries to repress them, many things in life benefit from stress, disorder, volatility, and turmoil. What Taleb has identified and calls “antifragile” is that category of things that not only gain from chaos but need it in order to survive and flourish.”

This idea reflects the attitude shared by those that used to be called hackers. Today the word has a negative connotation, but in the early days, it referred to a person with a certain attitude towards technology. As defined by the jargon file, a hacker is: A person who enjoys exploring the details of programmable systems and how to stretch their capabilities, as opposed to most users, who prefer to learn only the minimum necessary.”

Antifragile - Things that gain from disorderThere was a time when looking things up on Stack Overflow whenever you had a problem just wasn’t an option, and many pieces of software had unreadable documentation, if they had any at all. I remember trying to fix a sound card issue as a kid, and reading the card’s manual, only to find assembly code listings there, with interrupt codes and all. That is the environment where hackers thrived, and that’s what we are going back to, sooner or later. If your first instinct when dealing with a complex issue that affects multiple technologies is to start with a Google search, you should reconsider your working habits.

Granted, being too curious can many times lead you down the wrong path, especially in the corporate environment where time is always short. As an example, it can be very enlightening to write test code for the basic use cases when learning about a new library, but coders looking to impress the boss will take the more pragmatic approach of copying the examples from the documentation, fully unaware of how they work. Giving value as a developer requires a certain amount of skill in time management and in setting expectations, as to allow you to seek the knowledge you need and to save the company money in the long term.

Rethinking the roles

How do you find the hackers? You need to find someone with a particular mindset, the particular curiosity and persistence that I’ve described. This has nothing to do with analytical intelligence, or with being able to memorize a particular set of academic algorithms, so whiteboard coding is out, and Fermi estimation problems don’t look too promising, either. Ask a candidate what he likes to do on his spare time, or what fun projects he worked on as a hobby, and you might be onto something. I have met many programmers that don’t write code in their spare time, and that can sometimes be a factor that tells you that they just don’t enjoy it. Look for clues which reveal their personality.

If you’re a developer, you might be worried that you don’t have that kind of drive or curiosity yourself, so what can you do about it?

Here are some pointers:

  • Whenever you have to google some error message or problem, read all the answers. Get as much context as possible on your problem, and do not be satisfied just with having come across a solution.
  • Learn about the technology, but also about the trade-offs that were made during its design and development.
  • Ask yourself what it would take for you to consider yourself a “complete” developer, and write down a path for you to get there.
  • Do what other people don’t like doing, go where they don’t want to go, and often enough you will be enlightened by the experience.

Software development is growing fast. Learning to code is easier than ever, and soon enough we will be in a survival of the fittest environment. But the guy that makes it is not going to be the guy that first learned about the cool new framework. It’s going to be the guy that asked himself what’s new about it, and what’s different this time. If you want to stay up to date with technology stacks, then stop worrying so much about being up to date, and start hacking.

Note: this article first appeared on TechBeacon.

The other kind of JavaScript fatigue

People have been talking about JavaScript fatigue lately, referring to how we’re continuously having to learn about libraries that don’t usually last very long.

I think this discussion evidences how good programmers cannot be lazy people. You have to get a liking for learning new things. Its not that big of a deal, being forced into it: at worst, you’ll become better at identifying good libraries and clean software architecture. Embrace change, and it will make you a better developer.

There is another kind of JavaScript fatigue which doesn’t have as many positive elements to it, and it hasn’t received as much attention. I want to talk about it because I believe it is talking a toll on the JS ecosystem in particular.

Richard Stallman envisioned free software as an environment where people shared their code and other people would improve on it and this would gradually drive progress in the software world in more ways than a closed source environment ever could. I think there are some requirements for such an ecosystem to work properly. A certain balance has to be maintained.

The Cathedral and the Bazaar, which should be a required reading for any open source developer, also hinted at this problem when saying that good programmers know what to write, but great ones know what to rewrite (and reuse).

JavaScript as a language does not have the correct focus that is necessary for that to happen. It is simply far too easy to create a new library or package, and since anyone can do it in a few seconds now, this generates a lot of noise. The language has even evolved to make it as easy as possible to wrap a mess of DOM-manipulating stateful code in a couple of export lines and ship the module to the world.

It is just too easy now to share poor code

Think about the process that you undergo when you want to find a package that solves your problem. You search GitHub, or the npm registry, see what is popular for that, take a look at comparisons between the top candidates, maybe check which ones have unit tests, good code size, reasonable architecture, some minimal documentation, responsive project leaders… it can take a hours, even days, to decide.

The forgotten edge cases

Recently I needed a library to build query strings, just a small one so that I wouldn’t have to include jQuery just for that. After a couple of hours of research, I had found several candidates, but it quickly became evident that even though they were working and updated libraries, none of them was able to handle nested objects and arrays properly, in the way that jQuery could.

If you’re familiar with the 80/20 rule: edge cases are the 20 of the job that takes 80% of the time, and unfortunately most programmers are not going to put in the effort if most of the benefit of releasing their library has already been garnered. Writing complete and bug-free programs is challenging. Sharing poor code is not. Slap a cool animation on your Readme file and everyone will assume your project is awesome.

There are upwards of 200,000 JS projects out there, with language features that focus on increasing that number, and tooling that makes it even easier still. It’s easy to share bad code, and hard to identify and improve it.

Oh, so you’ve spent a couple of days fixing that bug on the library you downloaded? Great job, and I hope you remembered to manually check how active the project is, and if they accept PRs, and if a pending PR doesn’t already fix the bug. Project maintainers don’t have enough tools to make their jobs easy and, unfortunately, the tools that they have are often complex and off-putting.

Consider how difficult it is to keep track of which forks are interesting, even though making a new fork only takes the click of a button.

In truth, some tools have been created which aim to facilitate writing good code, such as linters, code checkers, and so on, but they are not nearly as numerous, and building tools to parse ASTs can be tough. It’s an uphill battle.

An ode to productivity

Programmers love being productive. Once you learn that a couple of lines of code can save you hours of work, you might fall into a trap of believing that productivity is the end goal and any library or framework that makes you solve problems faster must be great. In fact, many people believe this, and tools that simplify your work will often become fads with many people swearing by them.

This can go so far as to reach project managers and recruiters and get them to actively seek people who have experience with the current trendy framework, because all the top tech companies are using it, and their developers swear by it, so clearly it must be good.

This drive towards productivity is the cause for the existence of an increasing number of build tools, code generation tools, and services which aim to make shipping as easy as possible, and nobody will question if you should be shipping your package at all.

Top result from SO disregards the most common edge case

The fragmented nature of large open source ecosystems has become evident since the advent of Android. It’s a far-reaching issue and it is also self-reinforcing because languages with smaller communities such as Go and Nim don’t yet suffer from it, and that makes them more appealing, leading to fragmentation on an even larger scale as developers rally to greener pastures.

Fragmentation is like a virus which is driven by the human passion for creation, and we need to join forces and actively fight it if we are ever going to stop it.

Remember Google’s Polymer? Angular 1? Express? Perhaps the organizations and individuals which cause these abrupt termination events should carry a stigma. After all, misleading thousands of people does not generate a positive attitude toward open source, and can lead to bitterness and more fragmentation.

Instead of nurturing narcissistic language ambassadors that drop their projects like they change fedora hats every time they get a new idea, let’s create more tools to improve code quality and foster a sense of community. Human progress is not going to happen by default. That was not the case with clean energy, or with quality education, and it will not be different with open source fragmentation. These problems require active monitoring and organized effort.

The 3 Effects I’ve Noticed During Software Craftsmanship

Are there unbreakable laws ruling the process of software development? I asked myself this question while reflecting on a recent project, and the answer leads to many conclusions, some already known and some more revealing.

Scientific laws reflect reality and cannot be broken. They have strong implications onto how we build things. For instance, there is no point in building a car with vertical propulsion once you’ve observed that the law of gravity will prevent your car from drifting into space anyway. But software lives in the logical world. Does it really follow any laws?

Use the right tool for the job

I’ve heard this old saying many times over the years. We programmers have a lot of rules of thumb to guide us, but this one, in particular, has always felt almost universal to me.

It makes sense that you should not trust a single framework or library to work well for every project, and yet this rule seems to go largely ignored by the many fads we see in software development, miracle libraries that will fit any problem you might have, and even being marketed as such. Angular’s own website calls it the “Superheroic framework”.

This is a cultural problem that has been with us for a long time. “Vim vs Emacs”, “FreeBSD vs Linux”, “React vs Angular”. These are often seen as personal choices when they are actually technical decisions. And it doesn’t even end with developers: an enterprise environment will many times prefer fast solutions over sound architectures, forcing developers to favor fast prototyping tools such as Angular regardless of how well they fit a project because they seem to offer more productivity.


There are always advantages and disadvantages, and that’s why we’re reminded to use the right tool for the job. Every technical decision comes with tradeoffs. Not even just in software: any kind of craft, such as architecture or mechanical engineering, deals with decisions and tradeoffs.

This observation, in fact, looks a lot like a more general version of Newton’s third law, which states that for every action there is an equal and opposite reaction. Is it possible to generalize the other two laws as well? And how can we take advantage of them? Let’s look into it.

The fixed context in every problem

Under fixed circumstances, every solution will behave the same way, unless it has been modified.

Have you seen yourself hitting reload or re-running your program when you saw a bug, in the hopes that it went away, secretly knowing that the problem was still there? Don’t do that!

Main takeaways

  • Report every observed bug immediately. This might be your last chance of seeing it, and it might end up causing serious issues when users run into that particular edge case later on.
  • Write a unit test for the bug right away. Making a code change might fix one problem and break something else, so it’s important to run tests for previous bugs when fixing new ones.
  • Other developers should be notified of new bugs as soon as possible, as they might affect the code they’re working on as well. If you see a new bug report, don’t stash it. Read it now.

Impact of each change in software

The impact of a technical decision is directly proportional to the size of the project and to how much of it is affected.

For instance, if you modify a lot of code, there will likely be a strong impact on the codebase. For a larger codebase, even a small change could have a large impact.

Main takeaway

  • Be wary of updating dependencies to new major versions. A lot of code will have been changed. Whether the tests catch new problems or not will depend on the library’s design, its separation of concerns, and many other factors.
  • Use libraries with good code coverage. It’s no guarantee, but it will help.
  • Have plenty of tests in place before doing any refactoring.
  • Be paranoid if there are no bugs after a refactoring.

Trade-offs in software development

Every technical decision comes with an implied tradeoff.

Have a clear vision of what the job is, and then use the right tool for the job. I’ve already talked a bit about this one.

Main takeaways

  • There is no “best” anything in software. Figure out what you need and what each choice provides before selecting one.
  • Have a habit of reading about the tools you use and the ones you don’t as well, and how they work internally. This will give you valuable insight when making decisions.
  • Some tools focus on fast development, others deal better with complex data. In web frameworks, Angular would be an example of the first case, and React would be one in the second case.
  • A language that has more libraries is not necessarily better. Recently I had to search for a query-string-building library in JS and not a single one I found would handle nested objects properly the way jQuery does. Languages that make it easy to write libraries will make it time-consuming to choose the right one. This can lead to analysis paralysis.
  • Always consider mature libraries even if they are unpopular. They will often cover more edge cases.


I tried to write this with as much practical advice as possible, so if you’re looking for the TLDR, just go back and take a look at the “how to” sections.

This was a fun analogy and I believe it can lead to many more interesting conclusions than I’ve been able to gather myself so far, so I’ll be looking for comments on HN and Reddit!

Writing good code: how to reduce the cognitive load of your code

Low bug count, good performance, easy modification. Good code is high-impact, and is perhaps the main reason behind the existence of the proverbial 10x developer. And yet, despite it’s importance, it eludes new developers. Literature on the subject usually amounts to disconnected collections of tips. How can a new developer just memorize all that stuff? “Code Complete“, the greatest exponent in this matter, is 960 pages long!

Read More

How to use your full brain when writing code

On “Your Brain At Work“, Dr. David Rock gives a quick introduction to the current state of neuroscience and goes on to give a great deal of advice on how to handle the perils of office life, which most of us developers can probably relate to. In this post, will attempt to take the main ideas from this book and apply them to common software development situations.

Your CPU at work

It turns out that the brain does work somewhat like a CPU. Think of it as a processor that can only handle a limited number of concurrent tasks, but has a really large amount of storage. Let’s see how this analogy can help us develop software better.


As a general rule, you should work on no more than one or two short tasks at once. The brain gets overloaded more easily than you might think.

Your mental CPU has a limited stack, with enough space for 3 or 4 items at the most. Just like an OS switching between programs, when you work on more than one thing, your brain has to repeatedly unload relevant information for one task and load things for another one. We can’t do this as fast as a CPU, and certainly nowhere near as often, so take it easy and focus on one thing.

When you switch tasks, your mind has to figure out what you were thinking about previously

Muscle memory

Repetitive training in a task will eventually make your brain run it on its “default network”. This is like the brain’s muscle memory or a CPU’s internal cache. Once you repeat a task enough times, it will become almost effortless.

It’s important to note that even when you’re mentally exhausted, you can still do tasks you’ve got a lot of practice with.

You can take advantage of this process by reviewing things you do once in a while, and training yourself on that a bit every day. There are code challenge websites which help with this, but from what I’ve seen, they are usually focused on rather useless algorithms, like sorting, which you can find in a library most of the time, and memorizing them will offer little benefit.

A more useful training task might be writing an SQL query, or the code for a website’s controller, or string handling, or practicing regular expressions, or even command line tools such as grep or awk.

I suggest that, when starting a new project which will be using a new framework, you take some time every day to go through each one of the tutorials. Eventually, you will be able to concern yourself with just your project’s code. The rest, the glue, you will be able to do blind.

It can be tempting to use code generation tools in this case, such as Yeoman. They can be useful, but if you use them while learning, you just won’t know the code nearly as well as if you had built everything yourself.


I have found that having a strong vocabulary on a particular subject can greatly increase the speed at which you process ideas on it. It makes sense since language is our main tool when interpreting thoughts and events.

As an example, it is indeed far easier to think “referential transparency” or “pure function” than to think “those functions that always return the same value and don’t have side-effects”.

For building a strong vocabulary, there is the obvious habit of reading a lot, which I think at this point most developers already know that they have to. Tools like Pocket and Feedly come in handy.

I like to complement this with memorization of the most difficult concepts, especially things I don’t run into very often while reading. You can use Anki for this (or any other spaced-repetition software). Load it up with lots of interesting definitions. Be creative: anything from databases, Big O formulas, C library functions, anything that might turn out to be useful.

Some definitions I've been studying recently

Some definitions I’ve been studying recently

The key takeaway from this is that you don’t know that you need something until you know that it exists so, for instance, the benefit of memorizing the C standard library is not just to remember parameter orders, but also to have more tools at your disposal by knowing about more functions when you run into new problems.

Wrapping it up

  1. Streamline your work by splitting it into small tasks
  2. Avoid multitasking
  3. Practice coding problems every day, beyond just your project’s tasks
  4. Memorize

Additional reading

If you’re interested in this, I strongly recommend that you give Dr. Rock’s book a shot. It goes into a lot more detail and is certainly more authoritative and eloquent than me. Don’t miss it!

Page 1 of 2

Powered by WordPress & Theme by Anders Norén