Simplicity (II)

Once in a while, I have to fix small issues in very old projects. Some of my client sites from more than a decade ago are still around. One could argue that they probably should have been re-launched three times since. But it's also quite nice to enter the time machine.

There are two eras of those projects: pre-built-process and and post-build-process. Whenever there's no package.json I know it's going to be a good day. Whenever there's one, Pandora is coming along the way with her fucking box.

When you ever had to fix just a few lines of CSS and it took two hours to get an ancient version of Gulp up and running, you know what I'm talking about.

Yes, I know, there's Docker and if you are a real professional you would put everything in containers. But don't ever tell me that this is making your life as easy as editing a plain HTML or CSS file.

We've come a long way as web developers. We have wonderful tools that help us optimize, prettify, test, deploy and scale our work in seconds and it's great.

Working on Kirby, we use quite a lot of those tools. We rely heavily on Git and Github, we use the Vue cli with Webpack in the background to build our Panel, PHPcs and ESlint to enforce the same coding style throughout the team, PHPUnit, Jest and with Travis CI to test our code, to analyze our test coverage. We auto-deploy our site whenever changes are pushed to master. etc. etc.

When everything works, it feels like magic. When something breaks, it's hell.

The amount of time and knowledge that you need to have to setup such tools and services and to keep them up and running is insane.

Yes, they save a lot of time once they are working. If you don't touch them they are probably stable for a while. But I never learned to love them in all those years. It's more like a love-hate relationship, slightly tilted to hate.

There are a few major issues I have with modern web dev tooling:

Dependency Hell A - Code

I can never get over the fact that the most "simple" build process setup comes with 120 petabyte of node_modules. No matter if you want to "just" convert your Sass to CSS or optimize some images.

I have a simple rule of thumb when it comes to programming:

less code === less potential issues

This rule of thumb controls my own feelings towards a solution. It shouldn't take 120 MB of code to uglify some JS. But maybe I'm wrong.

In practice, this dependency hell has bitten me so often already that my life expectancy probably sank by 2-3 years. You want to build a JS file? Please update Webpack first. Oh, that new version of Webpack is no longer compatible with your Node version. Oh, your new Node version is no longer compatible with that other dependency. Oh, now you have 233 detected security issues in all your node_modules but you can't fix them because that would break something completely unrelated.

It's a UX nightmare and I haven't found a single exception yet. Vue Cli or Parcel are the most positive examples, where positive means: not as horrible as the rest.

This dependency hell is also the reason why old projects are almost like sealed capsules. You can hardly let a project lie around for more than a year, because afterwards it's probably broken.

Dependency Hell B - Services

How do you make money in a world of open-source projects? SaaS! It all starts nice and simple: Github free plan, Algolia free plan, Travis CI free plan, ZeitHQ free plan, Netlify free plan, Azure free plan, Firebase free plan, etc. etc.

But all of them share the same goal. They want to lure you in and then convert you to their paid plans. That's the only way for them to make money. The free plans are sponsored by their investors or the high margins of their paid plans.

When you start using services like Firebase it becomes instantly clear that you lock yourself in. The more time you invest, the harder it gets to move away from them one day. The more painful it gets if they ever shut down.

Other services are more subtle. With Github you only realize the dependency if you build your community there and it starts to grow. If you leave, you basically loose the community. With Github Actions they now try to add another layer of customer glue.

With services like Algolia it gets massively painful if you grow out of the free plan or jump to the next tier.

Netlify and Zeit have the same issue and also try to bind you with their attractive additional features that are exclusive to them.

The more you bind a project to a certain service, the harder it can backfire later. The longevity of a project is suddenly in the hand of another player and you have to play by their rules. When they decide to change the way their service works, you have to adjust to that.

The comfort that they provide comes at a high price. All those services look simple on the outside, but they all come with complex related issues and potential risks.

We love to talk about simplicity. "Simple" is probably one of the most overused words in our industry. Not only in documentation.

Is something really "simple" if you have to be an experienced developer before being able to use it?

Is something really "simple" if the best case scenario works great, but whenever it fails you are stuck for hours?

Is something really "simple" when you are cosily wrapped in an over-engineered blanket that comes at a high price once you need to unwrap yourself?

Talking about simplicity, I made the comparison on Twitter between a headphone jack and a bluetooth connection.

Modern web dev tools and services are like AirPods. It's fantastic to get rid of the cable. The experience is far better 95% of the times. But they also have connection issues from time to time, they are massively over-engineered, expensive and you can easily loose them.

Bluetooth headphones are likely the future. But I still have more love for a set of standard headphone with a regular cable and headphone jack that has been working reliably for decades.

I just have to put this over-used quote by Antoine de Saint-Exupery here again:

Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away.

Yes, we have new possibilities to solve problems. But sometimes it might make sense to take a step back and ask ourselves if something that has already been solved needs to be solved again – but more complex this time.

As always, such questions are very personal. It depends. If you are in a team, your priorities are completely different than for someone who works alone. Big teams have different problems than small teams. Your project might not need to be around for years or decades etc.

It's important though to reflect on what we are doing. It's as important to reflect what affects the user. They don't care about our issues behind the curtains.

When we talk about the time that modern tools save us, we also need to be honest. How much time do they save us today and how much time might they cost us later?

I personally try to take such time-machine rides as lessons.

We face the same problems with Kirby. We try to keep it "simple" but is it really simple? What are the true obstacles for beginners. What are the pain points for our users when something breaks? How can we take care of such situations and make sure nobody gets stuck for hours? And what happens when you need to maintain a Kirby site in 5 or 10 years from now? Can we somehow help to make this easy? Is it even made to last that long? How can we avoid that our users are locked in? Etc.

All those questions are important to me, because they are the qualities that I appreciate in software myself.

I wrote about simplicity in a similar fashion five years ago. That's why this article is called Simplicity (II). This topic never really gets old to me as it seems :)