<T>, foobar, and other sins of building excessive naming abstractions
Nov 2, 2021
Programming is abstract enough in its own right, and yet sometimes we choose to make it even more convoluted. Let's take it down a notch by thinking about how we name entities.
By no means, I don't want to preach about how you should write your code. I am guilty of having written cryptic variable names in the past, and I will probably do so in the future. Therefore, I can understand people can have different opinions on the subject.
I just happen to spend some time now and then explaining programming concepts to beginners. While doing so, I noticed web resources tend to make the learning experience unnecessarily tangled. Let me explain what I mean by that.
Useful links:
1. Variable names
We will fire it up by dealing with the biggest cliché of programming naming conventions: foobar. I don't have anything against it in particular; it's simply a perfect example of an offender in a case I am trying to make.
Wikipedia says that foobars have been used to name entities such as variables, functions, and commands whose exact identity is unimportant and serve only to demonstrate a concept.
Therefore, using foobar should be a conscious choice, made when we want to create an environment fitting for any context. We don't want to talk about dogs and apples when we want to ensure the reader that the concept, that is being presented, is general.
Here we have an example of how to change a dynamic object property in JavaScript:
const foo = {x: "yz",[bar]: baz,};
And here we have the same use-case, but this time presented in a slightly more accessible way:
const dog = {name: "Scooby-Doo",[key]: value,};
Unfortunately, foobars have engraved themselves in our brains so hard, we tend to introduce them even when presenting beginner concepts. I believe it happens so naturally because Computer Science is, for obvious reasons, heavily influenced by academics.
During my time at Wrocław University of Science and Technology, often I would have a hard time learning because instead of putting the subject in an accessible context, the teachers decided to keep up with the scientific notation and vocabulary at all costs.
The web today is full of people lacking the Computer Science background, which is what makes it so beautifully diverse. By limiting our usage of foobars, we make the programming community more inclusive.
2. Function parameters
As I mentioned, I spend some time introducing a very sharp young man to web development. It is a process I recommend everyone to participate in, for reasons that would go far beyond what I planned this article to be. One of them is that I get to revise my programming knowledge and make sure it is something more than a sum of knee-jerk-made observations.
When I started to learn programming, it was sufficient to have the intuition of what to pass to JavaScript method and to suspect what the outcome should be. It is not enough when I get to explain these concepts to a beginner. "Just do that and don't ask" doesn't cut it.
That is why I became a regular guest of various web development resources, and I noticed that often they go against some principles that we are used to in a commercial environment. The revelation came upon me when I was explaining .sort()
array method.
I have a little riddle for you:
const numbers = [9, 4, 2, 5];numbers.sort((a, b) => console.log(a, b));
What do you expect to see in the first iteration?
a) 9 4
b) 4 9
Well, not sure if this will come as a surprise for you, but the answer is b). I, however, thought the opposite, which may explain why I always get the .sort()
function wrong. It doesn't help that its compare function documentation often looks like this:
function compare(a, b) {if (a < b) {return -1;}if (b > a) {return 1;}return 0;}
The presence of 1
, -1
, and 0
is already abstract enough, but with extra confusion described in the paragraph above, I hope you are starting to see why I always get it wrong. Wouldn't naming it next
and prev
help a little?
Problematic not only for beginners
It is not the only use-case, though. Even while being very serious about limiting the responsibility of a function to a minimum, you can still get lost in it, especially if the function parameters are named cryptically. I will try to make my case in a pretty common scenario: a nested, looped, unnamed arrow function:
// ...tests.forEach((t) => {questions.forEach((q) => {q.answers.forEach((a) => {// ...// ...// ...// wait, what the hell is "t", again?});});});
3. TypeScript generic parameters
I believe that the idea of types should be brought up more often to beginners so that the process of moving to TypeScript is as natural as possible. I consider TypeScript the way of writing dependable web applications, so the less we have to fight the residues of frequent usage of loosely typed vanilla JS, the better.
There is often a specific hurdle in the process of learning TypeScript that is notoriously difficult to go around: the generics. It is a language feature that is as abstract as they get - it enables you to create a reusable type that accepts another type as an argument.
type APIResponse<Data> = {links: {self: string;};data: Data;};type UserAPIResponse = APIResponse<{ userId: string; email: string }>;// {// links: {// self: string;// };// data: {// userId: string;// email: string;// }// }
The idea of writing code in a more general way in order to reuse it in a different context, is nothing new, even to beginner programmers. However, there is one bit that makes learning this concept in TypeScript more difficult than it should: a specific naming convention for generic parameters.
Beware of <T>
!
What is it? It's an idea of naming a generic parameter with <T>
that, I guarantee, single-handedly ruined TypeScript for many students, at least for some time. You think you are going full steam with your TS development and then, all of a sudden, you see nothing but T
s everywhere. I am not sure where the fixation came from, but I suspect the reason was what we diagnosed in the paragraphs above: the urge to build excessive abstractions.
You may hear: in a feature that is even called generics, to highlight its contextless nature, you shouldn't have to rack your brain thinking of a better word for something that could essentially be nothing specific. I say: we can definitely do better than <T>
which was proven by the authors of TypeScript docs, where, at least in the "generics" section, you will find no <T>
s.
The anti-<T>
revolution doesn't end here, though. There are still thousands of them creeping in the source code of your favorite libraries, community-made tutorials, and various publications. If you are on board with me, you don't rest until we get rid of them all. Let's make the beautiful world of TypeScript a bit more accessible!
While I made my opinion clear, I want to emphasize this: I don't think we should get rid of abstract naming conventions entirely. Even though every once in a while, they may hinder one's attempt to learn a more advanced subject, not everything can be contained in an accessible context. I am simply calling for caution while introducing them because it's easy to abstract the problem a <T>
ad too much.
These three will shock you 😲: