Live data from Hacker News

Applying the Linus Torvalds “Good Taste” Coding Requirement

medium.com

141–150 of 302 posts

Re: Applying the Linus Torvalds “Good Taste” Coding Requirement

#141
post #128

Linus' "good" version has a McCabe cyclomatic complexity of 2, whereas the "bad" version has a value of 3. So, objectively, one could argue there is improvement there (albeit small). Validation of the "good" version will be easier (e.g. code coverage testing) with fewer paths through the code. Additionally, a lower cyclomatic complexity typically implies less stress on the developer's working memory while reading cod…

I thought the same.

On the other hand it took me a bit of time to figure out what's going on.

But I'm not C dev, so that could be the issue here.

Re: Applying the Linus Torvalds “Good Taste” Coding Requirement

#142

I don't know how to reconcile Linus's track record is of indisputable brilliance and success (I use Linux and Git on a daily basis and am eternally grateful for both), with the fact that I would absolutely DESPISE working with a peer with the kinds of attitudes and opinions on coding that Linus has. I think the problem I have is that a lot of people use Linus's examples and stories as justification for their own subo…

I get what you are saying and I agree somewhat, but there are also some lessons to be learned from Linus and things to consider. I especially agree that many lesser talented people use his behavior as a justification for their own. I disagree that at least some of his lessons or behavior is detrimental.

A good realization in life that many of us have is, "Most people are wrong about most things most of the time." This feels sometimes like it applies by an order of magnitude to programming. I think Linus has a style that deals with this reality head-on and it certainly is not for everyone.

One needs to perhaps not be exactly like Linus, but draw some insight from what he does. First, he is bluntly honest with people and there is virtue there. You can argue there is a polite way to be honest, yet sometimes I wonder if I have found it. For huge parts of my career I made my life harder or even self-sabotaged myself by being overly polite to people. I was always assuming (and often still do) that I am wrong and they are right. Further, I give people the benefit of the doubt, try to help them save face in front of others even when wrong, and hear them out before making judgements. It sounds solid and is many ways a healthy attitude for life in general as well as programming.

The problem that arises is that people are people. It is true that people will take advantage of you. It is true sometimes if you give them an inch, they will take ten. It is true stupid people often get ahead. More often the answer is simply people don't get the message.

You can sit and do a code review with someone, ask them politely to do something, send an email, have a lunch chat, whatever, and the message still does not get across with most programmers. You can say that is bad communication or "my fault," but actually I am speaking more about what I observe rather as a whole than my own personal experience. I have had the privilege of working with best friends for small parts of my career, and even then this was an issue. I can't imagine people with better textbook communication than we did, but maybe what we needed was more Linus-style communication. Sometimes the advice or knowledge is beyond colleagues, and they'll even say, "Yeah, oops, I know you said to do X, but I did Y, my bad." That doesn't help you in project and getting things done, especially if it means minimum someone spends time to fix mistakes they know they should have never made.

If you are direct or even a bit abrasive, there is no ambiguity. I grew up in two different cultures side-by-side and traveled the world at various points, living abroad for periods too. Without providing too much PII, I will say that my experience with American culture is that it is very polite, understanding, apologetic (Canadians get this rep.), relatively open, and welcoming. People in American workplaces are on the one hand uptight, more wound up, extremely dishonest, very opportunistic, melodramatic, and a host of other negative traits. On the other hand, Americans are very precise, thoughtful, at least feign listening to you, clever, and methodical. Compare that to another culture that I'd describe as masters of improv, extremely practical, open, honest, and yet sloppy, self-centered, arrogant, overconfident, and disorganized. Neither culture is better than the other, and like Linus, his style just represents one view point of dealing with programmers that is not really better or worse than most others that work.

I will say that in the second culture I mention, things get done faster for certain types of work. The openness aspect also really matches a part of what Linus does. People tell you exactly what they think of you. Sometimes it's really hurtful such as telling you that you look "fatter" one day vs. another. They don't think of it as malicious though because from their perspective, they think something is wrong and they are trying to help. By pointing out you look like you are gaining weight, you might be surprised to know what is really going on is they think you might be sick and want to take care of you. They think you might be eating bad and want to feed you better food. Sometimes, sure, they are just being dicks.

One can think of what Linus says as just a philosophy that won't work for everyone. Someone telling you exactly what you did wrong and not trying to be diplomatic, cute, or passive aggressive about it ensures the message is clear. It helps you in that you may never make that mistake again. There is no ambiguity hopefully and you either do what he says or decide all of it is not worth your time. Playing games, working people with you do not like, pretending to be nice, and blindly following cultural idiosyncrasies are not things I personally enjoy. Some people need those layers of protection or to live a life with those things, and that's fine I guess and equally OK if I decide not to for myself.

I personally cannot work in an environment like most of corporate America anymore or even startups. I need people to be "real" with me, and to learn non-obvious things. I need to be constantly improving, not patted on the back and stabbed in the back by that same person. I want to be stabbed in the front. Of course I realize for many people that might be soul crushing and too much.

The problem I think is that people are misinterpreting what is going on here. Using curse words at everyone for the sake of cursing or yelling for the sake of yelling is not the message. Nor is one true style of coding. To me, his message in part is "Be honest, be direct, be specific, and be clear." He has one clear direction for most of his projects and expects people to follow it or go home. IMO, this is what many software projects need - good, unwavering, solid leadership. It usually doesn't work with a pure democracy because no decisions, at least not the heard ones are made. I look at committees like the W3C and others and see how long it takes to produce output, how much fighting, etc. I look at github issues and see the long threads of people trying to fake politeness. No thanks.

An ignorant tyrant isn't what is needed either. This is where it gets hard. If there was one style for all projects, we'd use it for all projects. Sometimes democracies maybe do work for small projects. Sometimes the real leader is not the person identified in charge. It takes some luck to have what Linus's projects have and the same leader who is good for one type of project is not good for another. I am 100% certain Linus would fail leading many projects.

As for Linus WRT to the software pantheon, you'd be surprised by what I just wrote to note that I don't really care about him. I do not have heroes or believe in hero worship. Moreover, although I use and value Linux, I do not actually like it and I am somewhat unhappy it exists (but happy vs. Windows lets say). I simply use it because it is better for many of my use-cases than what is out there. That won't stop me from pointing out all the legacy warts and wondering if all this time, money, and effort would not have been better spent on a new OS with a new philosophy that did not carry over the ton of anachronisms and design mistakes from Unix and the surrounding community. I do not even consider most of what is in Linux that interesting or innovative, but I am still glad it exists and most of all can easily appreciate the pragmatism of bringing Unix to the home and affordable business world.

Anyway, look at things for what they are and separate that from your personal beliefs, and it will help you learn even more.

Re: Applying the Linus Torvalds “Good Taste” Coding Requirement

#143

Maybe I'm wrong about this but I noticed that the code didn't call free() to the element that has breen removed. That would cause a memory leak. Am I missing something here?

The caller still holds a pointer to the element and can free it. I would argue that delegating the responsibility of freeing the element to the caller is more performant, since that allows the code to reuse that list element and insert it into a different (compatible) list.

That's the kind of performance/ease-of-use trade-off that sounds reasonable in an open source project with strict code reviews (but in very few other places)

Re: Applying the Linus Torvalds “Good Taste” Coding Requirement

#144

I dunno, the first example seems unsatisfying. The original has that ugly condition, the "good" version seems overly clever. And for all the talk of taste and aesthetics, both versions ignore an elephant in the room: defensively dealing with `entry` being absent from the list. Not that I've never abused addresses like this. But having written this multiple times, I currently prefer something like this: remove_list_en…

Screw 'taste', go for obvious . If you're at BigCo and your codes going to be maintained by disinterested drones/ random contractors/etc, obvious code is better. And lack of checking on entry pissed me off too.

I say screw 'taste' and 'obvious' and instead go for it has high coverage unit tests and lots of them.

You can always go back and make it look pretty safely with good tests.

I just love code snobs that think their code is so good they don't need tests.

Re: Applying the Linus Torvalds “Good Taste” Coding Requirement

#146

Earlier quoted context omitted.

It's busier to look at due to the syntax of the language, but if you're comfortable with pointers one could argue that it's conceptually simpler than the first example. And since linked lists are all about pointers, operating on the pointer directly seems logical. That said, for someone unused to the syntax (as I am!), I agree that it is definitely harder to mentally parse. So which is objectively better probably dep…

>So which is objectively better probably depends on your audience. I guess when your audience is kernel developers, this isn't that much of a problem...

not true at all.... kernel developers are not mythical beasts, they're just regular low-level developers. Nothing special.

I've got 20 years experience developing this kind of stuff and to me, its not as simple as it could be, therefore it could be better.

Re: Applying the Linus Torvalds “Good Taste” Coding Requirement

#147
I think the main lesson that's there, is that in edge cases, it is sometimes helpful to work with pointers which point to the structures you're actually working with, instead of considering the structures themselves. This especially seems to work for getting rid of null checks.

This takes some getting used to, but it allows you to write more efficient code. I would do this in kernel development (smart people, high demands on performance), but I would not recommend to write code like this is enterprise software.

When you zoom out a bit, and describe the task with natural language, you can also see that this might be a good idea: "Find the node that is equal to entry, then, if the previous node exists, set the 'next' pointer of the previous node to the 'next' pointer of the current node." sounds a lot more tedious than "Find the pointer that points to entry, and set it to the 'next' pointer of entry.".

This also works for more complicated tasks:

  // removes all instances from the linked list and return the number of entries removed
  int removeentries(valuetoremove, list)
  {
  	removedentries = 0;				// how many entries we've removed
  	prevpt = NULL;					// pointer to previous 
  	entrypt = list.head;			// get pointer to first node
  
  	// walk the list (be careful, head can be a nullpointer)
  	while (entrypt) {
  		if (*entrypt == valuetoremove)
  			if (prevpt) {
  				prevpt->next = entrypt->next;
  				removedentries++;
  			}
  		prevpt = entrypt;			// save current node as prev for next node
  		entrypt = entrypt->next;	// move to next node
  	}
  	return removedentries;
  }
can be re-written to:

  int removeentries(valuetoremove)
  {
  	removedentries = 0;				// how many entries we've removed
  	indirect = &head;				// points to the current node

  	// walk the list
  	while (indirect) {
  		// remove current entry from list if its value equals valuetoremove
  		if (indirect->value == valuetoremove) {
  			*indirect = *indirect->nextpt;
  			removedentries++;
  		}
  		indirect = indirect->nextpt;
  	}
  	return removedentries;
  }

Re: Applying the Linus Torvalds “Good Taste” Coding Requirement

#148
post #34

Speaking of coding niceties, when I started branching out from bash into a 'real' language, Python, I couldn't find a switch statement. A colleague of mine said that Python didn't have one, and that switch statements were a 'code smell'. I didn't really understand that, and asked about those times that you genuinely could use a switch statement, and the answer was "just use a long if-else function". I can't remember…

There are multiple alternatives to switch (or if) statements and I would generally agree switch statements are mostly a code smell. As one posters described, using the fall-through behavior is more what justifies it and the real difference. I know you asked for ELI5, but let me give you some options to think about how you code on a broader level and how to eliminate both if and switch or at least improve them.

If you think of a switch statement as a pattern matching construct, then you will realize there are many, many alternatives in any programming language, including Python. For instance, the dict method works, as can anything that operates a collection-oriented data structure. For example, you could just as easily loop on a list and do this too, but for most lists this would require a worst case of O(n) iterations where n is the size of the list to match, thus a dict is better. A dict would not work if you want fall-through since you would only be matching on a single key usually, unless once again you do lookups of multiple keys (dict still wins). But a list would support this fall-through behavior with minimum effort and a small list would preform alright.

If your usage is lets say more sophisticated than a key lookup, there may be alternative data structures that you can use to achieve similar results (b-tree, red-black tree, skip list, etc.) though that is of course getting further from the usual behaviors of switch statements.

A functional way to go about it would be to reduce or fold on some collection. If you think about the items that don't match, they wouldn't add anything into the final reduction much in the way map/reduce works traditionally. Many times this would just consolidate the entirety of the function you are calling the switch with the result it is producing. Generally, I'd encourage thinking of writing code that operates on data and thus tends to make good reduce of things like reduce, map, filter, etc. as this often simplifies things and in some cases can actually lead to nice performance if done right. It also tends to force you to write things atomically, with less side-effects, and as pure functions. One of the problems people have with if-statements is they end up burying unrelated concerns or bug-inducing side-effects in each if/else or each branch. This code smell is easy to detect by simply pretending you are looking at new functions for each piece of code under an if/else or case and seeing if they are returning the same "type" in general sense of thing, how much there is in common between each piece, and if they are doing 1 or multiple things each. Most of the time, you are really doing the same thing with one slight difference like an input parameter, and you never really needed an if or at the very least, it could be handled differently. If you are doing more than one thing per if, it often means you are doing too much. Furthermore, you should test that if you were to repeatedly pass the same data to each, would you get the same result?

Another way of handling this is to use multi-methods. Note that in truth, it's the same as above because all you are doing depending on your implementation is pattern-matching. It just depends if your behavior is match one or match multiple (fall-through-like). Python can use attributes to do multi-methods among a few other ways. It's been awhile and mostly I'd avoid using them for performance reasons, but it's another option when thinking of more advanced ways to get rid of switch or if constructs.

In general, it's worth noting that in many languages such as Python, though ifs/switch might be ugly, they can often perform pretty well. It is also worth knowing that if/switch are not very good for functional styles sometimes. Making lists or dicts or other constructs is not always free, or slower/faster so it can sometimes just be a balance between performance, clarity, and composition.

Hopefully that gets you thinking and is not too confusing. A bit exhausted so I'm not thinking my best, though I think I am sending you down a track to explore to help you grow.

Re: Applying the Linus Torvalds “Good Taste” Coding Requirement

#149

I dunno, the first example seems unsatisfying. The original has that ugly condition, the "good" version seems overly clever. And for all the talk of taste and aesthetics, both versions ignore an elephant in the room: defensively dealing with `entry` being absent from the list. Not that I've never abused addresses like this. But having written this multiple times, I currently prefer something like this: remove_list_en…

Bog-standard, humdrum enterprise programming != kernel programming

When every branch removed on a mainline path in the kernel saves years of compute time globally and every byte removed in the kernel saves terabytes of memory globally, being clever is absolutely the right thing to do. Removing that one branch takes away an expensive pipeline stall[0]. The version akkartik has above adds a extra branch (and expensive pipeline stall) to _each iteration_ of the loop; Linus would probably not be pleased, to put it mildly, if anyone submitted a patch like that.

And the method Linus shows isn't even particularly clever; it's been a common example for handling linked list insertion in C for decades. All these "Linus is being too clever" postings show is that most programmers aren't cut out to be kernel or embedded programmers.

[0] See https://en.wikipedia.org/wiki/Bubble_(computing) and https://software.intel.com/en-us/articles/avoiding-the-cost-.... And, yes, instruction reordering[1] might be able to fill the slots but you don't get to be where Linus is by relying on that. Plus, Linux runs on processors that don't have OOO, like Intel's Atom and microcontrollers.

[1] https://en.wikipedia.org/wiki/Out-of-order_execution

Re: Applying the Linus Torvalds “Good Taste” Coding Requirement

#150

Earlier quoted context omitted.

>So which is objectively better probably depends on your audience. I guess when your audience is kernel developers, this isn't that much of a problem...

not true at all.... kernel developers are not mythical beasts, they're just regular low-level developers. Nothing special. I've got 20 years experience developing this kind of stuff and to me, its not as simple as it could be, therefore it could be better.

Maybe. But if it is a common idiom in the linux kernel (is it ?), it doesn't mean anything that the first time you encounter it you will take some small amount of time understanding it, because then you'll know about it, and it won't cause any problem in the future.
Post reply on HN