Two's Complement - Questionable Comments
Episode Date: September 18, 2023Ben and Matt comment on different types of comments in code. Join our hosts and they explore both good and bad types of comments, from the essential to the inexcusable. Matt explains how to bump the f...ailure counter to 99. Ben suggests violence against cats.
Transcript
Discussion (0)
I'm Matt Godbolt.
And I'm Ben Rady.
And this is Two's Compliment, a programming podcast.
Hey, Ben.
Hey, Matt.
How are you doing?
I'm doing good.
Great to hear.
I've been looking at code recently, so...
You don't say.
I mean, I guess that's a significant part of my job these days,
as I've realised that I don't write as much code as I would like,
and I look at a lot of code.
And in particular as well, we have a number of folks who apply to work with us,
and we ask them to do a nice little test.
I think it's nice it's nicer than the some of the hacker ranky type stuff that's around out there that's you know
reverse a string in place kind of stuff but anyway it's a significant amount of code that folks write
for us and one of the things i'm always interested in is the why people are uh write code in a
particular way there's you know engineering is a trade- know, engineering is a trade-off. It's always a trade-off, right?
It's not, it's more of an art than a science,
I think, in a lot of cases.
And deliberately, some of the things
that I ask folks to write have many choices
and I don't necessarily tell them what the trade-offs are.
And so it's always interesting
when they then submit something to see
and ask them why they made particular choices.
And sometimes those people will write giant comments above the code to explain the decisions that they made because they were
trying to express intent to me the reader and that's that's great and it just got me thinking
you know i don't do that in my code when i'm writing code because you know presumably there's
context around the people who are going to be reading my code have context but it got me thinking how what is a good comment what is a bad comment what what is a bad comment right yeah why
why do we write comments do we need them are they important the compiler certainly or the interpreter
doesn't see them so they can't be that important i mean yeah i mean i guess with with some things
you know like the type scripty type things that can get, you get like linters that will read the comments and then they go, hey, you know that thing you said there's a string?
It isn't a string.
But in general, comments are for humans, not computers.
Yeah.
Yeah.
There is probably a whole category of like machine parsable comments.
Doxygen things.
You know, yeah.
Doc test. Yeah. Oh, doc test is a great one. Yeahygen things. Yeah. Doc test.
Yeah. Oh, doc test is a great one.
Right. Yeah.
That might be a little outside of the scope
of what you're talking about here. No, I don't know
actually. I think it really, it's another thing.
That's a good comment because it's a test and therefore
is expressing
something that a computer can check for me, which is
important, but that's not the only reason I write
comments, obviously. So what's your thoughts on what makes a good comment? I mean, which is important. But that's not the only reason I write comments, obviously.
So what's your thoughts on what makes a good comment?
I mean, I'm in the same boat, I think, as you,
is generally I don't comment my code.
If I find myself, and I say generally,
because there are comments in my code, for sure.
But I don't make it a general practice to comment, you know,
every method or every class or anything like that.
And I generally find that comments represent a sort of deficit in the code that sometimes can be overcome by just writing better code and sometimes can't, either because there literally isn't a way to do it or I'm just not smart enough to do it.
Right. The comment becomes an apology for the either complicated looking code that seems
to be doing things it ought not to or is otherwise unintuitive. And so you have the
comment explaining why, look, before you do this, before you edit this code, be aware that there's
some spooky action at a distance stuff
going on here and although it looks like you could replace it with a simple call to the standard
libraries blah blah you can't because of x that's a comment that is like an apology that says my i
couldn't think of a cleverer way or a more intelligent way of doing this but then the
things that the comments that i sorry i'm stealing from you immediately here but like yeah you've you've you've made me made me think that yeah the the the comment that says um apply interest rate and
then the next line is payment times equals 1.13 that's not helping anybody when i could say
const auto sorry plus plus e interest rate equals 1.13 auto value including interest equals
and you know oh suddenly i've just given names to variables that are human readable and express the
intention and now the comment goes away which i think you know you and i agree on on that i think
that's that's one thing that one can do and that's i think what you're alluding to when you say if
you can think of a way of writing it in a way that exposes intent,
then you can get away with a comment,
get away without a comment very often.
Yeah, the best way to write code
is in a way where both the computer
and the human can understand it, right?
Instead of having to separate those two concerns.
Because as we all know, in all things programming,
creating unnecessary separation
leads to things getting out of sync.
And we know that no one has ever seen a comment that is out of sync with the code that it is immediately above, right?
So, yeah, trying to unify that is a great way to make changes.
Honestly, that's actually one of the things that you mentioned that only the other day I caught myself reading a GitHub pull request and the code had been updated and the comment was
big enough that it was above the fold of where the diff came in in the github pull request and
i didn't realize that there was even a mention of like something that was part of the code and so
of course i accepted it it's like this is fine this is looks completely reasonable to me you've
changed the code in that way and then on a viewing, when you're looking at the file in totality, you realize that the comment should have been updated as well.
And you just couldn't have been told from that. So there's a certain amount of context around it.
Yeah. And that is it's it's funny because it's just another form of the same problem that programmers are very aware of is like, OK, we're going to we're going to do that interest rate calculation in two parts of the same problem that programmers are very aware of. We're going to do that interest
rate calculation in two parts of the code.
We're going to have the interest rate calculation here and the interest
rate calculation here. You change one of
them and you don't change the other one.
You've now introduced a bug.
It's like, yes, you unify those things. That's how you fix
that problem. Don't repeat yourself.
It's the same thing with the information and comments.
Exactly.
It can sometimes feel a little pedantic, honestly. It's sort of like, okay, well, I will name this function, you know, calculate yearly loan interest instead of like, you know, calcint. Right. But you're missing an opportunity to name things to express more information
in basically the same number of lines of code when you do that.
And one of the signs that I need to do that when I'm programming
is if I feel the need to put that comment in there.
Exactly.
Maybe I should find a better way.
Right, right.
And I mean, from a sort of C++ specific, or maybe not even C++ specific type of thing, but like another way that I find myself writing those sort of apology comments is in the explanation of like the interdependency between, say, parameters to a function. in y as well and so like there's a thing that says precondition either x must be truthy or y
must be truthy but not both uh and you're like well and so you write that in the comment and
then maybe you even write like the assertion in the first line of the code that does that kind
of thing you're like could i express my api so that it's actually impossible to to pass both
parameters right could i just write two functions one that takes an x one
that takes a y and one that doesn't take either and then maybe internally i'll implement them in
the same function because of whatever reason but like the thing that i exposed to the outside world
doesn't even let you make that mistake anymore so the fact that you had to kind of apologize
and explain to somebody that this is not possible goes away uh when they don't have the choice
anymore and you know similarly with values and things you know uh if you've got like this value this is not possible, goes away when they don't have the choice anymore.
And similarly with values and things, if you've got like,
this value must be greater than zero.
In C++, there are edge cases where you say if it's signed or unsigned and it doesn't work as well as you would like it to.
But you can make types that are strong enough to hold those preconditions in them.
For example, we have things like quantity classes,
like a quantity of shares that can be traded,
and zero is not a valid quantity to be traded,
neither is a negative number,
and we can have a strong type around that.
And then I know that if something takes a quantity as a parameter,
I don't have to explain that to anybody,
that the quantity must be greater than zero,
because I can't give it a quantity must be greater than zero because I can't
give it a quantity that is less than zero it would have exploded in somewhere else right and that's
part of the contract of quantity um so there's some things that you can do like that again those
are sort of c++ ish but I'm sure other languages have ways of doing similar things and yeah yeah
yeah I mean it's it's some of that is again like you know when I'm writing these kinds of things
and I feel like there are sort of different categories of code apologies here, comment apologies, and we could dive into those.
But when I'm writing those things, it is sometimes, I mean, obviously, it's very hard to tell the difference as a programmer between there's no way to do this, and I don't know how to do this.
Right.
Right? Like, sometimes you know, sometimes you have this sort of intuitive sense of like, I think there's a way to do this, but I just don't know how to do this. Right. Right? Like, sometimes you know.
Sometimes you have this sort of intuitive sense of, like,
I think there's a way to do this, but I just don't know what it is.
But oftentimes, it's just like, yeah, I don't know.
Right?
And so when you're sort of doing the one of, like, okay,
I know there's a language feature that could categorically prevent this from being possible.
And I am choosing for one reason or another to not use it.
Either because it might introduce a performance problem
or because you're just not familiar with the different edge cases
and you feel like you might be pulling a regular expression and just trading one problem for another set of problems or all the various
reasons why you might choose not to do it you might want to put a comment in there saying be
like i think there's a way to do this using blah blah but i'm choosing not to do this because of
x right um but there's also just the like this is terrible and i hate it but i don't know how
to make this any better that's a different
yeah so as you say it's a different type of apology there right right it's it's just like
i'm sorry i'm not a perfect programmer this is all i have to give right um and and those i think
are those are interesting you were telling me a story the other day actually about uh something
like this where like there was a counter in the code what was this exactly do you
remember I can't quite remember myself but yeah we were on the train and we I was describing a
story where I'd seen someone say there was like a comment that says it looks like you can do x or y
but if you attempt to try and replace x with y or do whatever then once you've discovered it's
impossible come back here and bump the counter and it do whatever then once you've discovered it's impossible come back here
and bump the counter and it's the current value you know like 98 whatever and so like 97 previous
times someone had gone there must be a way of doing this and then they've gone around and found
some like compiler bug or find some like you know oh no that thing requires this and then they come
back and begrudgingly so can you imagine sending that pull request where all you're doing is bumping the counter?
From 98 to 99. I give up.
He's so ever who can pull this function from the stone
can be king, right?
Oh, yes.
That's it, yeah.
And I do wonder what that was now.
But, I mean, I've seen things like that before.
But one thing I would say about those apology comments,
especially the ones that have more of that second feel,
and maybe this segues into some other reason
where I put comments in the code,
are to-dos, like genuine to-dos.
And I think we may have discussed some of these things before,
but generally, you know,
each project may have a different discipline around to-dos.
I've worked on projects where to-dos are fine in branches,
but you can't merge them into main. And that's like, you know, oh, we can't go to production while there's a to-do
in the code base. I've also worked on projects and the one that I'm currently on now where
to-dos are a placeholder for this needs to be better, but in order to unlock some functionality,
it's really important. And in order to sort of put a stake in the ground and say, this is some
debt that I'm willfully accruing. And i know we've talked about debt and credit card debt or technical debt various types
of debt but like you know colloquially this could be improved you put a to-do in the code and for me
the important part is to then make a github issue to track it or add it to a general thing and i put
in a list and obviously that's that there you are repeating yourself right um but there i've got a number in the to-do that references the the github
issue and then i try manually and certainly now i'm sort of on a project management side of things
i tag it as a to-do and then there's a place to go to find all the debt and obviously git grep
to-do will find them all as well and it's something that you kind of go like i'm putting my head up
it's not just me brushing it under the carpet in a way.
It's no, no, there's a way of finding all of these
and then coming back to them and saying like,
hey, I wonder if we can actually do that thing now.
Yeah, I think those kinds of comments,
it's like there's a million ways to skin that cat.
Don't skin cats.
No.
I keep saying, you're using idioms.
What are these idioms?
There's a million ways to solve
that problem uh you're an idiot i'm sorry uh no i love that uh the the you can solve that problem
in so many different ways and and the main thing for me is just having consensus among all of the
people who are working on it it's like like, you know, whatever you pick,
to-do means this, fix-me means that.
We're going to have links to issues.
We're going to have just issue number.
Whatever you do, just do it consistently
and make sure that everyone is doing the same thing
because there's nothing worse than having code littered
with these sort of like, well, one day we'll make this good type promises
that you know are just hollow that's it that is the they're unactionable you can't go back to them
right there's and you know that you'll come back to it one day and the crash in production and
debug it down to the line that says someday we should probably fix this thing i doubt this will
ever happen in production though so for now i'm leaving it and you're like oh oh dear right right
right the thing that raises the air for the impossible case and you're like well it turns out
not impossible uh yeah totally but yeah all of those things i feel like however you want to
track those because the key thing there i personally i find a lot of value
in drawing a strong differentiation between what i would call technical debt and just a lack of
capability i see those as two very different things technical debt is more of the sort of
thing we were talking about before the former of like i know there's a better way to do it i'm not
i'm just choosing not to do this and it's not a question of like enhancing the capabilities of the system
but it's just like i'm just writing bad code and really you should just not be doing that period
but if you are and you put a sort of an apology in there and explain explain yourself like you
know there are maybe some situations in which it makes sense to do that very tactically so long as
you have the strong discipline to come back and fix them quickly, which is a
whole other thing.
Separate thing, yeah.
Right.
But the sort of lack of capabilities of...
There are certain types of input data that we could potentially receive here that we can't handle
right and do yeah handle cases you know packets of this type you know snapshot packets or whatever
right okay yeah and we just don't handle that right now you i wouldn't think of that in most
cases i wouldn't think of that as debt so much as just like that's just not a capability that
you've built yet right now the debt might be like okay we don't handle these packets and instead of raising a nice clear error
that says like we don't handle this type and it just warns logger.warn and you're like oh why is
my file 200 gigabytes and it's like yeah exactly or it's like you know it ignores it or it drops
it or it just pretends like it's a different type. Like that is death. That's a death.
You should not be doing that.
But the lack of capabilities is,
but it's another good reason to put a to-do in the code
and say like, hey, if only to reduce the scope
of a pull request, perhaps,
where you're sort of like saying like,
hey, I'm adding the functionality to even handle packets
and I handle heartbeat packets
and I handle, you know, echo packets,
but there's all of the other ones I don't do
because that's a significant amount of work that may even be in a separate pr that i'm separately god i haven't
wired them together yet but to do all of the rest of these things and that can be part of the pr
yeah exactly that makes it manageable yeah so that's a different that's a very different kind
of comment from from the the explanatory sort of because those kinds of comments let you make
smaller prs and i think everyone kind of agrees that it's of comments let you make smaller PRs.
And I think everyone kind of agrees that it's like
the smaller your PRs can be,
the more atomic your changes can be,
the easier it is on your reviewers,
the less risk there is to roll those things out.
And so whether you track those things in a GitHub issue
that is linked in the code,
or whether you just put it in a comment in a thing,
again, there's a million different ways to do that, but pick one and do it and be consistent about it you know what i mean
yeah yeah yeah so so those are good comments you know they're there but they sort of almost uh
reflect a certain amount of project management or change management uh information in the code
right but i think so one of the questions we asked is what makes a bad comment and to me the the
obviously comments that are out of date or wrong are inherently bad and they're worse than no
comment at all that's objectively those are terrible comments you know something that says
and now we sort the array and then you look down you're like it doesn't sort the array anywhere
in this function whatsoever i have no idea what it's talking about right but then for me the other thing that sort of uh winds me up in and again this is context
dependent because again when folks are submitting code exogenously and they have to explain
everything that's the only mechanism that they've got which is how we started this conversation
i am much more sympathetic to the explanation of the of the and everything about it here's
the discursive nature of it.
Cause that's the only yardstick folks have got to,
to let me know what they were thinking.
Right.
Even though that's partly why if people get the,
if they write decent code and it,
and it passes our test,
then,
you know,
we'll probably have a conversation about it in person.
And then they can tell me about it in person,
but that's,
that's not the point.
But in,
in a production code base where you're, you on a team of of people um that have already have
agreed a sort of level of understanding about what the systems will allow you don't have to
continually explain well when i say this word i mean this other system is in this you know i don't
need that in every comment because you should know those things but the worst thing to see then is
the the essentially just a restatement of the code, but beneath it,
you know,
add to,
you know,
like our interest rate calculation from before it's like,
and now we do this thing.
And then there's a block of code.
And then we do this other thing.
And there's a block of code.
Now I have written that for like more complicated things,
but I think where the complication comes in,
right?
So I had a very performant,
well,
supposedly very performant piece of code and i
that i rewrote and it went from the obvious and straightforward way of doing everything
to the well you wouldn't really want to do it any this way for real but like i know that i need to
go incrementally in memory in order to you know stick to certain cache line things that i know
and are important.
And this is not the obvious way of phrasing it.
But again, this means that the branch prediction is done in a particular way.
And this is a constant time.
And then this thing, all those kinds of things, right?
And so there I busted out the whole thing into stages of a loop.
And each part of the loop did have a small explanation of what each bit was going underneath
it.
And I felt that was more justified.'s it's on that knife edge um if it wasn't
so performance sensitive and it wasn't so um tangled because of the fact that i had willfully
essentially inlined what would have been many different functions into one loop to make it so
that i could make these assumptions and pass things around by value and all that kind of stuff then
the obvious solution in general purpose code
is if you have a little comment that says,
this next block of code does X, Y, and Z,
is you extract it into a function
and you call the function that.
Right, yeah.
Which comes back to our kind of, yeah.
And very often, so I think it's Tony Van Aerd has,
I think it was him, there was a C++ talk and they were talking about like,
how many times do you need to repeat a piece of code
before you extract it into a function?
And, you know, there were various hands going, you know,
well, the third time that you duplicate the piece of code,
you should, you know, make a function in it.
You know, when is it okay to copy that code around?
And his point was like, sometimes zero times of duplication sometimes it's a piece
of code that stands by itself and even though it's not used by anything else in the entire program
it's useful to give it a name and define the things that it can and can't see what's in scope
for it and the parameters that it needs to take that are transient and then the things that are
stateful that are inside the object maybe it lives in or it's a free function or anything like that
and i'm like that's a great way of also giving a name to a piece of code you know like part
first we x then we y then we z becomes do x do y do z right right yeah it's like why do you put
paragraphs in prose to make them easier to read right it's It's the same basic idea. It is.
I mean, there's an argument there that says,
you know, in the pro sense,
the paragraphs definitely make it easy to read,
which is kind of what you're capturing
when you start putting extra spacing
and then you put a block of comments
in front of each thing.
You're kind of paragraphing it up there.
Except we have a better way to do that, right?
Yeah.
And now the argument against that is that
now you can't see the implementation
of each of those line after line.
You see a function call and another function call
and another function call.
But if the name, as an abstraction of what it's doing is accurate enough
then you've what you've got is the the pricey of what you're doing step by step and of course you
can go any decent ide will will let you go to the definition or in some cases you mouse over the
the name of the function then it'll expand it out and show you well this is what that function is
by the way and if it's only a few lines so you, well, this is what that function is, by the way.
And if it's only a few lines, then that's great.
So I feel we have the tools and technology to do this.
Yeah, and also every line of code that you wrote is also that, right?
You don't even know what the system calls are implemented like, right?
I mean, in C++, you've overloaded every operator known to mankind, and you don't even know
that 1 plus i is doing what you think it is doing right right yeah exactly so like you have to operate at some level of
abstraction you have to pick a level of abstraction right uh you might as well pick a good one that's
it's easy to understand and easy to read right right um one of the other places so you mentioned
you know uh you know maybe blocking things like out like this out for performance reasons and kind of putting those things in there.
And certainly I can imagine some scenarios,
depending on what your compiler is doing for you,
where, you know, extracting those things out into functions
might have a material impact on the performance itself
or might make it harder to kind of pull some of the-
Right, right.
I mean, let's just get,
compilers are really smart about doing this,
but sometimes it's not feasible for them and you want to give them a hand, but yeah. Yeah, right. I mean, let's just get, compilers are really smart about doing this, but sometimes it's not feasible for them and you want to give them a hand. But yeah. There are situations where you have multi-threaded code, and the way that those threads might interact with each other
is very non-obvious.
And a few choice comments to the reader to say,
like, hey, make sure that you acquire this lock,
and I've done my due diligence to try to design that
into the API as much as I can,
but sometimes you actually have to change the API,
and when you do, make sure that you acquire this lock,
because if you don't, then that's going to create
very, very subtle bugs, which will not show up in the unit tests and might not even show up in any sort of system or smoke test until something catastrophic happens.
That's a really good point.
And you make a very good point as well about the fact that, you know, sometimes that is can be designed out of the API.
And I think certainly there are some annotations i think in like some java
annotations perhaps um certainly there's like the synchronized keyword no no i thought there
were annotations that you could actually apply to something so like the at protects and then
some list of parameters maybe just for static code analysis is that not something or i've seen it
maybe i've seen it in some language maybe it wasn't java but like i know c++ in theory there are a set of keywords or magical sacred comments that sort of allow static analysis to check these
things in which case that's even better right you can sort of encode yeah i mean there's still the
why though that's that's i think that ultimately all of the good comments that aren't procedural
um like you know to do's that we discussed all of the best kind of comments are
the why the thing that you really can't get the intent from this is like it exists outside of the
fabric of the code is the why on earth we would do it this way or why on earth you need to do this or
why this is even something that is anyone would want to do right right um not necessarily the how
because the how with the appropriate amount of scaffolding in the names of things and with, you know, just actually just reading the code.
In theory, any human given enough time should be able to extract the how it's working and indeed what the what it's doing more specifically.
But why?
Who knows?
Right?
Yeah, yeah, yeah.
That's a place that you should you should
comments can be super valuable in that case for for sure uh one other kind of bad comment that i
uh was going to mention is when the comment is code when you've just commented out code and then
left it in the code and then committed it oh my gosh why is this here like we have source control for this
what why did you leave this here yeah yeah there's no reason to do that i i've seen that a lot with
folks who aren't software engineers first and foremost or junior folks who haven't yet learned
to trust their tools and they're like yeah i keep toggling backwards and forwards between these two things. And I'm like, okay, first of all, if it's something that you don't,
you keep around just because there was that one time you needed it,
then either you can stash it, git stash it,
and then it doesn't need to be commented around,
so it doesn't need to be checked in.
Or if it's important enough that it does need to be checked in,
make a command line flag to run it in that mode,
if you can do it in that kind of thing. That's another thing I seen it's like oh i just want to keep around hang hang on to the
intermediate files that this tool generates you know it makes a temporary directory writes a whole
bunch of stuff and it does some processing with it and it outputs a single thing and then it's
really convenient to be able to look at the innards sometimes when it's gone wrong or more
likely when it's gone right but you want to see why it went right and so it had deleted you're
like well stop commenting out the line
that says delete the thing at the end.
Make it a command line flag.
Right.
Or, you know, I've seen people hard code in
in the middle of their code.
They've got the thing that refers
to their like home directory
that they've commented out and said,
yeah, it's really convenient to be able
to output the thing at this point here.
And like, oh, don't check it in.
Yeah.
No, please, please don't. So in yeah no please please don't but so
so yeah i like commenting out large gobs of code because you're not sure about whether you might
need it or not i mean you could lean on your source control and if you think you're going to
need it more often than not then just find a way to incorporate it so that it gets compiled along
the rest of the code it gets refactored automatically right rather than just sitting
in a comment and you know rotting away in a way that no one's going to find.
And maybe it's a useful function for somebody else, too.
Hey, if you thought it was useful to do this, maybe someone else will as well.
Yeah, there's a bunch of things like that.
And I really, I do think that the most dysfunctional form of this is the sort of commented out utility main or method that people will selectively uncomment and like you know put their
home directory in or whatever like not only does that create sort of you know accidental unnecessary
noise when you like you know change the home directory and you for you commit the change
just because it wrote along with all your other things but also like you know there is a risk with
these things like if you're using them for like real operational tasks that they get out of sync with the code in ways that won't fail cleanly right like you would hope
that if it got out of sync with the code and it was a compiled language you know you'd uncomment
it and you'd get some red squiggly lines or the compiler would give you an error but especially
in more dynamic languages it's entirely possible to just run and do something that you absolutely
did not expect it to do at all because the code has
changed in the last six months and those
functions you're calling don't work like that anymore.
That's an interesting one.
I think that's a really
almost no excuse.
You should
never have commented out
code. I could almost
forgive two back-to-back
commits where you like put some
code in there and then you have another follow-on commit that deletes it just so it's like all right
what's in version history now if i ever do it again it'll be there i mean you can make you can
put it in a branch that never gets to main although you know again still there it's there's a million
ways to do that right but please please please do not just comment the code out and stick it in
there and expect for it to live on forever.
So that actually reminds me of another comment type that is valuable.
And it's a comment that you should never see ever in a checked in piece of code. And it is the comment that says, do not commit.
Oh, yeah.
And it's really, really, really.
So I was thinking again about the home directory type thing.
Like, despite all my protestations to the contrary,
of course,
pragmatically up against the gun,
sometimes I am going to make some bespoke changes to the code just to exhibit a
particular bug or to make something happen that just needs to be done right
there and then.
And while testing it or in the PR or whatever,
you definitely don't want that to make it into
into production so the having a pre-commit hook and everyone should have a decent set of
pre-commit hooks there's no there's some there are plenty of choices out there for pre-commit
hooks and managing them in a sensible way my favorite is pre-commit i think is the name of
the thing pre-commit yeah and it's a name of the thing, pre-commit. Yeah, that's what I've been using too. Yeah, it's a little Python thing that is very principled
about how little plugins for each of the things that you want it to do.
It's cool.
But there's Husky, I think, in JavaScript land,
and I'm sure there's millions of others.
But anyway, have a pre-commit hook that says,
hey, don't let people check in stuff that says do not commit.
And then it's fairly, fairly safe to then train people to say, if you are making the kind of horrific, you know, bull production equals true somewhere in the middle of your code base.
Right, yeah.
Immediately put a comment on the same line that says do not commit.
And then you know that you are being protected from the catastrophic check-in that will will cause all sorts of issues
and of course obviously it's incumbent on reviewers to make sure that these things don't make it
through but in the ebb and flow of things i mean we've all been there where you've reviewed a pr
and said yeah this looks basically good to me can you just test this thing and make sure that that's
comments aligned here or whatever and then it's good and then you've approved the pr and then of course the person's gone away and
they've done what you know some quick chest tests before you know made a little change and they've
tested it and they thought well i better check that thing and they they make that kind of change
and then they go oh everything's fine they check it in and you're like oh i did not and unless you
have the thing that makes you approve them every single time you know including the exact specific
version then then there's a chance of of sneaking it not even sneaking i mean accidentally
getting something and everyone with a good faith was like oh sugar i didn't mean to do that but if
you put do not commit you're in a good way yeah yeah no i love those and honestly that the project
that i'm working on right now uh we haven't added that and i kind of want it we've gotten away with
not having it because we do the thing,
I think we talked about this in a prior episode,
where we have to-do comments, and they mean very specific things,
and they can't be merged to main.
There's a check that prevents that.
But there's nothing that would prevent someone from doing,
like you say, the sort of production equals true,
and you maybe run that on your local machine
for a very bespoke focused experimental test.
And then you forget about it and then you check it in.
And now all of a sudden the thing that's running in the branch environment is accessing production data right now.
Hopefully we've got our Terraform set up to where it couldn't actually change any production data.
But I don't want to figure out if that actually works by doing that.
That's yeah
there are some tests let's not test the seat belts by running into a brick wall right
that doesn't sound like a good idea yes speak yeah as we both have uh teenage new drivers
that's a bit top of mind for me at the moment yeah right right right right right yeah no so so yeah that's that's i i can't think
of any other type of comment that i've oh no let's talk a little bit about uh documentation
comments because i i recently had a a fairly uh interesting conversation with somebody
on my team because they were putting uh comments sort of Doxygen-style comments in front of stuff.
And I'm like, I don't know.
And again, they tend to have a flavor,
especially when there's things are,
when the linter rules, if you're used to them,
say, oh, you need to document every parameter.
But you know that very often
you want to document the function
because you want to have like a one-liner
that's human-readable.
And that seems laudable still.
Okay, maybe.
Again, I would like to think that a name would hopefully carry that information but this person was thought
there was value in it and i'm like okay i maybe i'll go with this but then the sort of at param
uh you know bob the bob to act on you know the function is called you know act on bob and it
takes a pram bob and you say this is the bob to act on and it returns the acted upon
bob and you're like you know that's not helping me that's not useful that's noise it's now six or
seven lines above the function that are explaining to me obvious things um the point that they were
making was that you know you mouse over and their ide gives them a very nice explanation of everything
and highlights and links all the types and things in a nice way when it's a doxygen thing and so i'm i'm warm to it and in particular part of the code base that
they're working on has like a slightly more external visitor sorry external user kind of
facing aspect to it and i'm like well okay it's not the worst thing in the world to have some
documentation around something but um as you can hear my, I'm still on the fence about it for all the reasons that it almost, on purpose, duplicates the code.
But it duplicates it so that maybe someone who is not as intimately bound up with the code and everything to do with it can understand what that function is doing and can read a documentation that says, you know, this is how to, I don't know, frob the frobnicator.
This will come as not a shock to our listener
in the slightest,
but if you gave me the choice
between getting docs with a library
and getting the test for that library,
I'm going to choose test the 10 times out of 10.
Yes.
Because I will find them much more useful
and much more informative,
and especially if I can edit them and rerun them,
that will be extremely valuable.
I do understand, and I can relate to this sort of like,
it's nice to have that sort of IDE pop-up that shows you that information.
And I would say, like, if you really wrote your doc strings
or whatever documentation system you're using to do this,
if you really wrote that with the reader in mind and you really wrote it in the context of this is what's going to pop
up when I hit control space or hover over this thing and I want the reader in that specific
context to have this information, I wouldn't be opposed to that at all. In fact, I could maybe
even see that as being useful. But I think, unfortunately, most of the tooling around this,
you sort of create the start of the doc string,
and then your ID sort of fills out the template of the whole thing.
That's right, yeah.
And then it's like you either have to go
and then change all of those settings
and then share all those settings among everyone on your teams.
They're all using the same template for all of these things
to make sure that it's not unnecessarily polluting your code
with Bob parameter equals Bob. Or you have to do other things to sort of strip that out.
And it just seems like a whole bunch of effort to take something that is marginally valuable
and make it like slightly less annoying. Right. So I don't know. I mean, if it were me,
I would just lean toward, can we not? But if I had someone that was like, no, no, I really want to commit to this.
And yes, I've changed all the ID settings and I've checked those configs in.
And here's how you load them into your ID.
And we're just going to do this.
I wouldn't fight against that.
Yeah, it sounds like we're of a similar mind there.
And I'll be honest with you, in particular Do doxygen my heart always drops every time i click
on the documentation for something you know an external thing and i could open source project
and it takes me to a document a doxygen route uh like the boost boost documentations which is
obviously one of the bigger libraries for c++ and a lot of the c++ standard features were first
implemented in this boost library and then kind of adopted as part of the language so things like shared point is so a lot a lot of good heritage there and but um it's a huge library and
it's it has a lot of complicated um functionality and the documentation is hit and miss some of them
you click on something and it goes to a big explanation page about like hey you want to use
asynchronous io this is a primer on what we mean by asynchronous this is how threads work this is
how our abstract and you're like this is great i want all this stuff other times you just get to
the the head of um a documentation tree that was generated entirely by reading the code and
generating the doxygen stuff and it's all function name uh you know from exactly as we described
right and it's just that on the other end i'm like well, well, I could guess that from the name of the thing.
I'm trying to work out how to use it.
Can I have an example, please?
Can I see how things fit together?
What is, you say that this is the Bob to pass,
but what is a Bob?
And you click on the Bob and it says,
this is the Bob class.
I know it's the Bob class.
Thank you.
I can read code, but it's frustrating.
And yeah, documentation, I guess,
is a whole other episode, I would suggest.
Yeah.
And I mean, I would say, you know, one of the, you know, coming back to comments, like
one of the good comments that you can have is if you have that type of documentation,
either for a third party thing that you're using, or maybe even something that you've
built yourself that is maybe just hosted in a different place, having like a link to that
type of documentation in the code sort of at the point where you need it is super useful.
And I really appreciate most IDEs and editors and everything will just open your browser
when you click on those things.
On those things, yeah.
And it's great to have.
But yeah, one of my first jobs out of school was working in a company that sold graphics
libraries, C++, Java, and
C Sharp graphics libraries. And part of what we would deliver to customers is, like, generated
documentation, right? Both, like, generated docs in the form of, like, here's how you
use this library, and we would do, you know, things with, like, the documentation system
that we were using to create graphs and charts
and diagrams and all these other things.
But also just the method and class-level documentation.
And I never recall anyone ever complaining
about that class-level and method-level documentation,
which tells me that they almost certainly never read it.
Because let me tell you you it was not the best
that's funny yeah yeah documentation documentation is difficult and i mean just to sort of finish up
on that that's one of the places where we started talking about like if you can put tests inside
your comments above the thing that's one place where i found that very valuable is the python
style doc test where i can
write the explanation of like this is how to use my class right above my class definition and then
i can actually put the what you would type into a repl and what the repl would mention back to you
and first of all that's readable inside the generated documentation and secondly it's actually
checked and make sure that it still works,
which means that if I rename something
and forget to update the documentation,
often, at least the codey part of it will go wrong
and I'll be told, and that's what I want.
So let me ask you,
what would you call a sequence of conversation pieces,
as we've just been discussing, about comments?
Would that be a collection of those?
Would that be a commentary?
Yes.
Maybe the title of this episode should be Comments on Comments.
Yeah.
Maybe it will.
I leave that to you to come up with the name of the episode,
but we can brainstorm it.
I'm going to have to think about this one now.
All right.
Well, dear listener, you will get...
So many pun potential here.
I can't pass up on this one.
This is a good one.
This is me throwing a gauntlet down in front of you.
So whatever this ends up being called,
you'll know that Ben was responsible for it.
Yeah.
I am the head of the Department of puns here at Who's Compliment
that is correct
well I guess that's about all the time we've got
today for this
it's been fun as always
yeah this is a good one
I'll catch up with you later in the week
yep
bye to do later in the week yep bye you've been listening to two's compliment a programming
podcast by ben rady and matt godbold find the show transcripts and notes at www.twoscomplement.org
contact us on mastodon we are at twos compliment at hackyderm.io. Our theme music is by Inverse Phase.