Live data from Hacker News

Maybe comments should explain 'what' (2017)

hillelwayne.com

171–180 of 212 posts

Re: Maybe comments should explain 'what' (2017)

#171

One thing I learned from programming since the early 2000s, there is no such thing as one size fits all advice. You do what is best for future folks--as I like to call the unfortunate folks who would have to maintain the code I wrote--by providing them helpful hints (be it business rules, assumptions related to code/tech) along with as simply and clearly written code as possible (how do I know if my code is simple an…

I agree with this soo much.

In a very real way, a codebase is a conversation among developers. There's every chance the next guy will be less familiar with the code than you, who just did a deep dive and arrived at some critical, poorly documented line of code. There's an even better chance that person will be you, 6 months from now.

Use opportunities to communicate.

Re: Maybe comments should explain 'what' (2017)

#172

Explain "why not what" is good general advice. My further advice for comments is: even bad comments can be useful (unless they're from LLM output maybe...) therefore when in doubt, write a comment. Write it in your own words. Had to add the last sentence for the circa 2020s developer experience. LLM comments are almost never useful since they're supposed to convey meaningful information to another human coder, anythi…

> even bad comments can be useful Bad comments aren’t just less helpful than possible, they’re often harmful. Once you’ve hit a couple misleading comments in a code base (ie not updated, flatly wrong, or deeply confusing due to term misuse), the calculus swings to actively ignoring those lying lies and reading the code directly. And the kind of mind resorting to prose when struggling to clarify programming frequently…

I hear this argument as an excuse not to write comments (sometimes at all). Maybe I am just lucky but I have never had this issue as you've described in codebases, and if I did, certainly not to that extent where it became a memorable thorn in my side.

If there are no comments, you are reading the code (or some relatively far away document) for all understanding anyway. If there are inaccurate comments, worst case you're in the same boat except maybe proceeding with a bit more caution next comment you come across. I always ask of fellow engineers: why is it unduly difficult to also fix/change the comments as you alter the code they refer to? How and when to use comments is a balancing of trade-offs: potential maintenance burden in the future if next writers are lazy vs. opportunity to share critical context nearest its subject in a place where the reader is most likely to encounter it.

Re: Maybe comments should explain 'what' (2017)

#173
> // translate will replace all instances; only need to run it once

That comment is not helpful, because it's wrong. The translate() function just is some sort of lookup. It doesn't replace anything. It's the stringToReplace.replace() call that replaces all instances.

Re: Maybe comments should explain 'what' (2017)

#174
post #2

I feel like no one serious uses the uncle Bob style of programming anymore (where each line is extracted into its own method). This was a thing for a while but anyone who's tried to fix bugs in a codebase like that knows exactly what this article is talking about. It's a constant frustration of pressing the "go to definition" key over and over, and going back and forth between separate pieces that run in sequence. I…

I can assure you that I am very serious and I do cut things up almost as finely as Uncle Bob suggests. Where others balk at the suggestion that a function or method should never expand past 20 or so lines, I struggle to imagine a way I could ever justify having something that long in my own code.

But I definitely don't go about it the same way. Mr. Martin honestly just doesn't seem very good at implementing his ideas and getting the benefits that he anticipates from them. I think the core of this is that he doesn't appreciate how complex it is to create a class, at all, in the first place. (Especially when it doesn't model anything coherent or intuitive. But as Jeffries' Sudoku experience shows, also when it mistakenly models an object from the problem domain that is not especially relevant to the solution domain.)

The bit about parameters is also nonsense; pulling state from an implicit this-object is clearly worse than having it explicitly passed in, and is only pretending to have reduced dependencies. Similarly, in terms of cleanliness, mutating the this-object's state is worse than mutating a parameter, which of course is worse than returning a value. It's the sort of thing that you do as a concession to optimization, in languages (like, not Haskell family) where you pay a steep cost for repeatedly creating similar objects that have a lot of state information in common but can't actually share it.

As for single-line functions, I've found that usually it's better to inline them on a separate line, and name the result. The name for that value is about as... valuable as a function name would be. But there are always exceptions, I feel.

Re: Maybe comments should explain 'what' (2017)

#176

IMO the example shows exactly that splitting code in smaller pieces is way better than just commenting it. It makes it easier for dev's brain to parse the code e.g. to understand what code really does , while fattier but commented version makes it harder but tries to replace it with information about original coder's intentions. Which is maybe important too but not as important as code itself. Not to forget that it's…

I do not agree; I think the example that is not split is clearer and does not need comments to explain it (the variable names are helpful, although even if local variables use only one letter it still seems like clearly enough; for variables that are not local to that function, it does help to have a more descriptive names to understand them better). Comments and splitting can both be helpful in some circumstances, but neither is helpful for this one.

Re: Maybe comments should explain 'what' (2017)

#177

Earlier quoted context omitted.

Turns out writing a book and getting it published with the title "Clean Code" is great marketing. I have had so many discussions about that style where I tried to argue it wasn't actually simpler and the other side just pointed at the book.

It's like with goto. Goto is useful and readable in quite a few situations but people will write arrow like if/else tree with 8 levels of indentation just to avoid it because someone somewhere said goto is evil.

Funny how my Python code doesn't have those arrow issues. In C code, I understand some standard idioms, but I haven't really ever seen a goto I liked. (Those few people who are trying to outsmart the compiler would make a better impression on me by just showing the assembly.)

IMX, people mainly defend goto in C because of memory management and other forms of resource-acquisition/cleanup problems. But really it comes across to me that they just don't want to pay more function-call overhead (risk the compiler not inlining things). Otherwise you can easily have patterns like:

  int get_resources_and_do_thing() {
      RESOURCE_A* a = acquire_a();
      int result = a ? get_other_resource_and_do_thing(a) : -1;
      cleanup_a(a);
      return result;
  }

  int get_other_resource_and_do_thing(RESOURCE_A* a) {
      RESOURCE_B* b = acquire_b();
      int result = b ? do_thing_with(a, b) : -2;
      cleanup_b(b);
      return result;
  }
(I prefer for handling NULL to be the cleanup function's responsibility, as with `free()`.)

Maybe sometimes you'd inline the two acquisitions; since all the business logic is elsewhere (in `do_thing_with`), the cleanup stuff is simple enough that you don't really benefit from using `goto` to express it.

In the really interesting cases, `do_thing_with` could be a passed-in function pointer:

  int get_resources_and_do(int(*thing_to_do)(RESOURCE_A*, RESOURCE_B*)) {
      RESOURCE_A* a;
      RESOURCE_B* b;
      int result;
      a = acquire_a();
      if (!a) return -1;
      b = acquire_b();
      if (!b) { cleanup_a(a); return -2; }
      result = thing_to_do(a, b);
      cleanup_b(b); cleanup_a(a);
      return result;
  }
And then you only write that pattern once for all the functions that need the resources.

Of course, this is a contrived example, but the common uses I've seen do seem to be fairly similar. Yeah, people sometimes don't like this kind of pattern because `cleanup_a` appears twice — so don't go crazy with it. But I really think that `result = 2; goto a_cleanup;` (and introducing that label) is not better than `cleanup_a(a); return 2;`. Only at three or four steps of resource acquisition does that really save any effort, and that's a code smell anyway.

(And, of course, in C++ you get all the nice RAII idioms instead.)

Re: Maybe comments should explain 'what' (2017)

#178

Earlier quoted context omitted.

It's like with goto. Goto is useful and readable in quite a few situations but people will write arrow like if/else tree with 8 levels of indentation just to avoid it because someone somewhere said goto is evil.

A colleague recently added a linter rule against nested ternary statements. OK, I can see how those can be confusing, and there's probably a reason why that rule is an option. Then replaced a pretty simple one with an anonymous immediately invoked function that contained a switch statement with a return for each case. Um, can I have a linter rule against that?

I guess "anonymous IIFE" is the part that bothers you. If someone is nesting ternary expressions in order to distinguish three or more cases, I think the switch is generally going to be clearer. Writing `foo = ...` in each case, while it might seem redundant, is not really any worse than writing `return ...` in each case, sure. But I might very well use an explicit, separately written function if there's something obvious to call it. Just for the separation of concerns: working through the cases vs. doing something with the result of the case logic.

Re: Maybe comments should explain 'what' (2017)

#179
post #169
post #163

I feel like a complete weirdo when it comes to comments and variable names. I've never worked professionally as a coder, but I've been working with python and a bit of js for like 15 years now. I strongly believe that variable names should be long, and explain what they are, and that comments should be long, and explain what's happening. I have no idea why people want to "save time" to write short comments and short…

"tuple" is entirely redundant with the types, though.

I’m not sure what you mean. You’re not necessarily going to know the type of a variable just by reading a random section of code… especially in Python.

I absolutely going to add the type to the variable name if it’s a complex function. It’s just clearer.

Re: Maybe comments should explain 'what' (2017)

#180

[flagged]

> The Uncle Bob approach of extractNameMatchingTransfersWithinSettlementWindow() doesn't actually help - now I need to know what settlement windows are anyway, and I've lost the context of why 3 days.

When the name is long, it should be more than one function. Finding the transactions within a settlement window seems distinct from matching them up.

The comment about 3 days isn't necessary when "numDays" is a variable in the SettlementWindow class (or other relevant scope). I'd be a lot more comfortable reading code that makes this concept a proper abstraction rather than just seeing a comment about a hard-coded 3 somewhere. Magic values are bad and comments don't demystify anything if they get out of sync with the code.

Post reply on HN