Yeah, sorry for the bold title, but sometimes I get tired of software developers expecting they figure out the secrets of the universe. And let’s be honest: at some time in my career, I was one of them. Sometimes by accident, sometimes… not. Anyway.

First, a little disclaimer: this post is not targeted at anyone in special, and I’ll not mention anyone here – just quotes, slightly modified. Anyway, although I love my profession, sometimes it feels like we’re this programmer guy from XKCD:

I'm here to solve it with Algorithms, then six months latter: wow, this problem is really hard (Megan: You don't say?)

There are LOTS of things that bother me at this programmer mentality, so I’ll separate this post into multiple sections. If you’re reading this and feels like it’s a personal attack against you, please don’t – I’m not really attacking anyone, just trying to change a toxic mentality that poisons our abilities to be better professionals, people, and human beings.

“Not a real programmer”

The first one is classic: people define what a “programmer” is, based on their own experiences and expertise, and dismiss people that don’t fall into their categories. Wikipedia, for example, defines Computer Programming as:

Computer programming is the process of designing and building an executable computer program to accomplish a specific computing result or to perform a particular task

As for the “Computer program part”, Wikipedia defines as:

In imperative programming, a computer program is a sequence of instructions in a programming language that a computer can execute or interpret. In declarative programming, a computer program is a set of instructions.

So it’s hard to find a good definition on what programming is, but if we try to merge the two explanations from Wikipedia, we get that, to program a computer, you have to design an executable “sequence of instructions” or “a set of instructions” so that you can accomplish a specific result or perform a particular task.

For example, aligning an element in the screen. Or calculate a specific result over a bunch of numbers. Yes, I’m specifically talking about HTML+CSS and Spreadsheets programs – things that most people dismiss as “not real programming”, even considering that there are games written with pure HTML+CSS and also in pure Excel only. Heck, even Powerpoint is Turing-complete so the whole discussion is kinda pointless – the idea is, if you can “accomplish a specific result or perform a particular task”, it is programming.

Frontend as a second-class citizen

It’s amazing when people consider frontend developers “less” than backend. Sure, maybe the security implications, the damage, and the risks of a backend code are higher but this only proves something: Frontend is really hard.

I mean, you can bypass most security issues, you can change the code, interact with bizarre ways, you have state but then you refresh the browser, and now you don’t, but you need to keep logged-in and at the same page so you kinda do, but not all state that you had before… imagine the insanity of working on a project when anyone can change the code at will, while the program is running, without you being aware of, sometimes even because of a browser extension.

But it gets worse: the only programming language you can use is Javascript (or something that compiles to it), so you are restricted to the async model of JS – you can’t block, you can’t multithread, and you can’t use things that are not supported for Javascript (also, different browsers have different JS implementations too).

Finally, let’s talk about CSS. Most people say that is not that hard, but let’s pose a challenge: suppose you have three elements at the screen: a title, a menu (the three slashes, or “sandwich menu” as they say), a title and a link. On big screens, you want the menu to be on the left, the title to be just after the menu, and the link to be right aligned. When the user resizes the view, you want to keep the menu at the left, the title to be centered, and the link to be at the line below, centered too. If the user resizes even more, the title should move to the line below, and the sandwich menu will occupy a whole line. It’s nearly impossible to get it right without some “CSS Framework”, and even then is pretty hard…

We are the only ones that have this problem

For the lack of better wording, there are situations that makes whole ecosystems bad – is when people “invent” a way to do things instead of using what is used for other languages. It’s hard to explain without real cases, so I’ll have to mention them here: Monkey-Patching and method_missing in Ruby, the whole “Compiler Pipeline” in Javascript, the annotation and reflection abuse in Java, and DSLs written with macros in LISP-like languages are all good examples.

The question is: do you really think your problem is so unique, that nobody had to solve this before? Let’s look at my new nightmare: React-Native. In React-Native, people publish NPM packages in “source” format, with the extension .js. So it means that, to be able to even use some libraries, you have to transpile them… which is incredibly complicated if you need to use ClojureScript, or any language that compiles to Javascript and integrates with NPM. Because these .js files that you require are not valid Javascript, so you can’t require them. All of this… for what reason?

What’s even worse is that, even if you do transpile them, it still will not work. And the reason is that they have Metro on the play – another bundler that will detect if you are running on Android or on iOS and include the right file on the pipeline, besides doing more things too. And all that… for what reason, exactly? Can’t we just do an if(isAndroid()} { return useAndroidImplementation() } like everybody else is doing? Is it really necessary to have two different bundlers? Finally, this is even worse for tests – you can’t require('react-native') on your test code, because, first, the files are not JS, and second, because all the necessary files are not even there… so the answer was to write a test runner that can mock require. Yes, that’s right – they mock the package resolution system!

For Ruby, monkey-patching. We have multiple things we could be using: Factory Methods, Factory Objects, Inheritance, pure functions, etc… so why even use Monkey Patch? Why even have it? Most people agree that’s not a good practice, but they keep using it because “it solves problems that we could not solve otherwise”.

Really?

Bold claims

There’s the classic my language have so I don’t need to do . Replace <X> and <Y> with anything, and you’ll probable see how anyone have heard something like this in the past, or surely will hear in the future; or the bold claim that “if you do it right, then this limitation/decision is not an issue”:

  • We have sane static typing, so we don’t need too many tests (Haskell, F#, and other ML-based languages)
  • We have a powerful REPL, so we don’t need that many tests (Clojure)
  • We don’t have exceptions, so if it compiles, it’ll run correctly (ELM)
  • We have immutability by default, so we have fewer bugs (most FP-based languages)
  • It’s not that hard to free memory that you allocated (C, C++, ObjC)
  • The language is too slow, so it’s useless (most native languages)
  • No other tool does that in this way (lots of examples to even mention)

So, first to address the elephant in the room: there are no evidences that a specific language feature makes for better code. People mention static typing, but most results are inconclusive, pointing that it’s hard to point a language that makes for less bugs and even them the change is too little; as for practices, there are some studies that point that TDD does lead to less bugs and better quality, but both assume that the studies have issues. More about this later.

As for Clojure, yes, the REPL is powerful. And I know some commercial products that were written by very talented Clojure developers that have few tests, and insane bugs, and in fact I did worked with some of them; ELM is proven to give runtime exceptions even without using “ports” or “native” code; and C/C++ code have, every day, new vulnerabilities related to their relaxation on how the language works with memory. As for Objective C… well, it is rapidly being replaced by Swift, so this may speak for something.

And we probably don’t really need to speak about “slow” vs “fast” languages, right? I mean, we have multiple examples of slow languages outperforming faster ones, specially Javascript, and we also have multiple insanely good projects being made in Ruby, PHP, Python…

Type Systems

I think the most problematic thing about type systems is: I talked a lot with lots of intelligent people, way more versed in both type systems and all the algebra that’s behind complex static types, category theory, etc. And the trouble is: they do recognize that all type systems are incomplete, meaning that they will reject valid programs or accept invalid programs. In fact, that’s a property about typing in programming languages, and even then, they argued that “there’s undeniably evidence that static typing leads to less bugs”.

So, they trust science, academic studies, etc until it conflicts with their gut feeling. Then, the studies are all wrong. And let’s not forget that, most of the time, people use terms for static typing that are not right, are not academically accepted, and most of the time are demeaning: “weak typed” (weak is worse than strong), “unityped” (again, if you have one vs multiple, that must be worse), “untyped” (again, you don’t have something vs you do have). Sure, some of these terms appear on academic papers, and that may be an excuse; but then, most of the time I tried to reason about using static/dynamic typing, that’s currently the most accepted distinction, again people went for “that’s how I call, so…”

And before, people use the same argument over and over again, about “people only use a Java/C/C# based type system that’s inferior” – it sounds incredibly similar when people discuss politics, arguing that “we never had a real <insert your politic orientation here>“.

I know better

Of course, I saved the worse for last: this covers also NIH (Not Invented Here) syndrome (when a company reinvents a tool/language/idea even though there are wonderful alternatives that do work, and then starts pushing it as the way to do the thing). This poisons multiple companies, both small and big, and unfortunately most of the time, the older, stable code gets forgotten because it was a personal project of someone; most of the time, newcomers only know about the newer, more limited, more opinionated library.

Other moments is when a library is officially “blessed” by the community, and it gets used everywhere, even where/when it’s not supposed to. It’s really tiring when you have to use the same arguments over and over again on why did you not choose that library.

Worse yet is when, on a discussion, people say “you’ll have to prove me that…” – it sounds incredibly arrogant, like “I’m the right one, you’re not, so you need to work harder to prove me wrong”. I got into multiple arguments over this one on my decisions to use promesa instead of core.async, and I believe only three people decided to test both instead of arguing why I should change to core.async, and ony one did, in fact, benchmark both…

Finally, there’s the case when a developer single-handedly decides that his way of doing things is the right one, and their way is the wrong. This includes multiple situations, and makes working with that developer unbearable (you can’t argue, because he’s always right and the others are always wrong too). This case is the most tiring, and also the most complicated to self diagnose too: I even wrote about it, on an incredible experience about being wrong by doing the right thing, when I was doing it.

The fact is: sometimes, there’s no right or wrong – there are just choices. And when there IS a right and a wrong, if you’re working on a group, the group must agree on something, and it’s quite impossible for everyone to agree on the exact same ideas. So, even if it’s not the best choice for the project, sometimes a choice must be made, even when it’s not the best one – otherwise, even if the group is using the best tool for that job, only one person will really be happy doing it.

Yes, sorry: you are not the only person in the universe. Deal with it, swallow your pride, and go on. You’ll be happier, and you’ll also make other people happy too!