Everyone I’ve worked with agrees that naming matters. Almost nobody spends any time on it. The name gets picked while the code is half written and then it sticks, because renaming feels like fuss once the thing works.
The check I use in review is to read the function name and the parameters and say in one sentence what the call does. If I can do that without opening the body, fine. If I can’t, either the name is bad or the function is doing two jobs and no single name will cover it. In my experience it’s the second more often than you’d think, so I run this before I look at length or complexity. It finds the same problem earlier.
The best names are the ones the product owner already uses. The worst describe the machinery: process, handle, manager, helper, data. Each is a placeholder for a noun nobody has bothered to find yet. The type should agree with the name too. A parameter called id typed as string takes anything. Call it userId with a UserId type and the call site, the signature and the compiler all say the same thing.
The fair objection is width, and code that borrows abbreviations from the paper it implements. Width is an editor problem. For code that follows a paper, cite the paper next to the module and the abbreviation is the honest name for its readers. For ordinary application code I’d hold the line.
Agents have made me stricter about this. They abbreviate out of habit and it’s easy to wave through proc because the prompt said processing. A developer who meets that later opens the body and works it out. An agent takes the name at face value and builds on it, so one lazy name becomes the vocabulary for everything around it.
I write these up at https://prickles.org/tenet/intention-revealing-names/F2 if the longer version is any use.


This is a bit reductive. Scope and visibility matter. A private function called by precisely two implementers within the same package doesn’t need to do heavy lifting on naming. It can be short; in fact I’d argue that it should be. Contributors working on the package can scan the code more quickly and will already know what is happening in that scope. Same for variable names.
On the contrary, publicly consumed functions called across maybe hundreds of scopes should be crystal clear in the name, maybe even largely implying the contract.
But even those probably have exceptions. So while I agree that names should be thoughtfully considered, one shouldn’t take the “name and parameters should tell all” axiomatically. It’s not so simple.
A method in an interface (or a function in a trait or equivalent) should be unequivocal, as it’s literally a contract.
I think there’s nuance in the private scope, especially in variable names, but I’d still expect the name to be fairly explanatory. Maybe not
EnsureUserCreated(UserDto userData), but stillEnsureCreated(UserDto user).For a narrow enough scope, I don’t see that as clearer than
created(u user).