The rules of good taste are from Linus Torvalds. Making code faster, easier and more intuitive

Original author: Bian Barto
  • Transfer
“Taste is the ability to judge the beautiful”
I. Kant

Dirk Hondel, one of the founders of Linux, once said of Linux creator Linus Torvalds: “Linus is not only a brilliant programmer: he has good taste. Torvalds finds simple and reasonable ways to solve problems, knows how to "put everything on the shelves." He makes complicated things simple. In my opinion, this is the main difference between an excellent programmer and just good. ”

image

In a recent interview , around the 14th minute, Linus Torvalds touched on the topic of “good taste in programming”. Good taste? The host asked him to dwell on this in more detail, and Linus, who did not come empty-handed, showed a couple of slides.

First, an example of a bad taste in programming was demonstrated, so that against its background it would be better to see the advantages of higher-quality code.


An example of bad taste in programming

This is a function written in C that removes objects from a linked list. It consists of 10 lines of code.

Linus drew attention to the if control at the bottom of the function. It was with this fragment that he was particularly unhappy.

I paused the video and carefully examined the slide. I recently wrote something like this. In fact, Linus said I have a bad taste. After swallowing a grudge, I continued to watch the video.

I have already come across what Linus explained to the audience. Namely, the point was that when removing objects from a linked list, two cases should be considered. The first is when the object is somewhere in the middle of the list. The second is for the object at the top of the list. This approach forces the use of the if construct and leads to the writing of tasteless code.

But, if Linus himself recognizes the need to use a conditional statement, why doesn’t this approach suit him?

Then he showed the audience a second slide. This was an example of the same function, but this time written with taste.


An example of good taste in programming

The same thing that was done in ten lines of code in the previous example now fits into four.
But the length of the program text itself is not particularly important. The approach that led to the appearance of the conditional operator at the end of the first example is important. In the new code, additional conditions do not need to be checked. The code has been redesigned so that the same approach is used to remove an element from the middle of the list and to delete the first element.

Linus explained the new code, said that the most important thing is to eliminate the borderline case, after which the conversation switched to another topic.

Reflections on a good taste in programming


For some time I reflected on an example. Linus was right. The second snippet is much better. If it were a test to distinguish between good and bad taste in programming, I would fail this test. The thought that you can do without this unfortunate condition never crossed my mind. And I wrote this more than once, as I often work with linked lists.

Perhaps the main value of the above example is not even that it demonstrates a good way to remove items from a linked list. The main thing here is that this example makes you think that the code that you wrote, the implementation of small algorithms scattered throughout the program, can be improved in ways that you never knew existed.

It was on this idea that I paid special attention when I decided to revise the texts of my fresh project. Perhaps this is fate, but my program is also written in C.

As far as I understand, the focus of the question about good taste in programming is the elimination of borderline cases that tend to appear in code as conditional statements. A good taste in programming is thus expressed in reducing the number of conditions that have to be checked.
I want to talk about one successful example of improving my code.

Initialize the edges of the mesh with taste.


The following is an algorithm that I have written to initialize the elements along the edges of the grid, which is presented in the form of multi-dimensional array: grid[rows][cols].

The purpose of this code was only to initialize the values ​​for the elements that are located at the edges - that is, I was interested in the top and bottom rows, and the right and left columns.

In order to do this, I, in the original version of the program, went through a loop for each element of the grid, and using the conditional operator, checked whether it is on the edge. Here's how it looked:

for (r = 0; r < GRID_SIZE; ++r) {
	for (c = 0; c < GRID_SIZE; ++c) {
		// Верхний край
		if (r == 0)
			grid[r][c] = 0;
		// Левый край
		if (c == 0)
			grid[r][c] = 0;
		// Правый край
		if (c == GRID_SIZE - 1)
			grid[r][c] = 0;
		// Нижний край
		if (r == GRID_SIZE - 1)
			grid[r][c] = 0;
	}
}

Although everything worked as it should, it was clear that the code was far from perfect. Namely, here are the main problems of this fragment:

  1. The code is too complicated. Using four conditional statements in two nested loops looks awkward.

  2. The code is ineffective. Provided that the GRID_SIZE variable is set to 64, the body of the inner loop will execute 4096 times only to find 256 elements at the edges.

Linus would probably agree that this code cannot be attributed to samples of good taste.

Having tinkered with the program for some time, I was able to reduce the complexity of the algorithm, the implementation of which now contained only one for loop, which contained four conditions. This was a small improvement in terms of reducing the complexity of the code structure, but a serious one in performance. Now only 256 loop passes are performed, one for each element located on the edge. This is how the same fragment looked after improvement.

for (i = 0; i < GRID_SIZE * 4; ++i) {
	// Верхний край
	if (i < GRID_SIZE)
		grid[0][i] = 0;
	// Правый край
	else if (i < GRID_SIZE * 2)
		grid[i - GRID_SIZE][GRID_SIZE - 1] = 0;
	// Левый край
	else if (i < GRID_SIZE * 3)
		grid[i - (GRID_SIZE * 2)][0] = 0;
	// Нижний край
	else
		grid[GRID_SIZE - 1][i - (GRID_SIZE * 3)] = 0;
}

Got better? Yes. But it all looks just disgusting. This code is not one that can be understood at a glance. This alone made me move on.

I continued to experiment, I wondered if it was possible to improve something else. The answer was unequivocal: "Yes, you can." And what I finally came to was so amazingly simple and elegant that, frankly, I could not believe that in order to think this through, I had to spend so much time.

Here is what I got. There is only one loop and no conditional statements. Moreover, the body of the cycle is executed only 64 times. This option is much simpler and more productive than the first.

for (i = 0; i < GRID_SIZE; ++i) {
	// Верхний край
	grid[0][i] = 0;
	// Нижний край
	grid[GRID_SIZE - 1][i] = 0;
	// Левый край
	grid[i][0] = 0;
	// Правый край
	grid[i][GRID_SIZE - 1] = 0;
}

In this code, four different boundary elements are initialized in each iteration of the loop. The code is simple and very efficient in terms of performance. Its easy to read. This option can not be compared with the first or even the second.

As a result, I was absolutely satisfied with the results.

Do I have a taste for programming?


And so, now I'm a programmer whose code meets the rules of good taste?

I would like to hope that this is the case, but not because I was able to redo the unsuccessful fragment of my program, which I showed above, and others, which I did not include in the article. The thing is that the manifestation of a good taste in programming is something more than a piece of text. Linus himself said that the example he cited was too small to properly illustrate his point of view.

I believe that Linus meant that developers with a “good taste for programming” are different from others in that they take the time to understand what they are creating before they start writing code.

They define the boundaries of the components that they work with and how these components interact. They strive to make sure that everything mixes well with each other, try to achieve the elegance of the code and the process of its execution.

The result of this approach is similar to the code that Linus cited, and mine too, only on a different, larger scale.

And how can you apply the concept of “good taste” in your projects?

Also popular now: