27

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.

top 10 comments
sorted by: hot top new old
[-] Metju@lemmy.world 8 points 1 day ago

Me and a friend of mine had a common understanding of what we called "2 lines of defense aganinst F12":

  1. First line: member signature (name, returned type, arguments).
  2. Second: documentation.

If these 2 do not provide sufficient defense against anyone pressing F12 (Go To Definition in IntelliJ-based IDEs) - we have failed.

It's sometimes tough to come up with specific nouns, but it's well worth the effort

[-] theherk@lemmy.world 22 points 1 day ago

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.

[-] nebeker@programming.dev 1 points 1 day ago

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 still EnsureCreated(UserDto user).

[-] theherk@lemmy.world 1 points 1 day ago

For a narrow enough scope, I don’t see that as clearer than created(u user).

[-] tatterdemalion@programming.dev 4 points 1 day ago

I like descriptive names, to a point. I'd rather have a slightly ambiguous name with a more descriptive sentence in the docs that I can see at the call site via LSP than a super long function name.

[-] towerful@programming.dev 4 points 1 day ago

I'd rather have a more ambiguous name that is clarified by context than comments or docs.
create(obj) is useless, but if it is namespaces and properly typed user.create(User user) makes a LOT more sense.
Granted, that is a very narrow example, but it gets the point across: let context carry context, and use it properly.
Something like import {create} from 'user' (and using it with merely create()) is less useful that import * from 'user' (and using it as user.create())

We namespace things to help split up code. Lean on the namespaces when using that code!

[-] whotookkarl@lemmy.dbzer0.com 2 points 1 day ago

The worst names I've seen are too long to be useful, too short to be understood, or tied to some specific vendor or framework or something that never gets changed when that entity is long gone.

[-] lascapi@jlai.lu 3 points 1 day ago* (last edited 1 day ago)

Thanks for sharing your though.

I think also that naming is an underused super power. It's also difficult to do it well at the first try.

[-] TehPers@beehaw.org 1 points 1 day ago* (last edited 1 day ago)

For variables, my favorite name is i. It doesn't tell you what it is without prior knowledge that it's probably an index, it doesn't tell you what it's an index of, it doesn't tell you which direction, if any, the index is moving in, and it's probably not necessary and can be replaced with direct iteration over the collection (like with for..of in JS). And yet it's somehow an extremely popular variable name.

On that note, I have a minor nit about your post, though it's mostly pedantry:

Call it userId with a UserId type and the call site, the signature and the compiler all say the same thing.

I don't really think a variable needs to be redundant with its type. It can just be id with the type UserId unless there are other variables of the same type in that scope. For example, if there's a sellerId, then a userId could make sense for the user who is viewing the product (not necesarily buying it), though viewerId could work there too.

I see this a lot in languages that don't support local shadowing. For example:

const fooStr = getSomeString();
const fooInt = parseInt(fooStr, 10);
const foo = foos[fooInt];

With local shadowing (or local redefinition in the case of a language like Python), you can use the same name if it remains the most descriptive and the old value is being dropped/"moved" anyway:

const fooIndex = getSomeString();
const fooIndex = parseInt(fooIndex, 10);
const foo = foos[fooIndex];

Note: JS doesn't have local shadowing, of course, so the above won't work

[-] prex@aussie.zone 2 points 1 day ago

functionOne, functionTwo....

this post was submitted on 02 Sep 2026
27 points (84.6% liked)

Programming

28345 readers
466 users here now

Welcome to the main community in programming.dev! Feel free to post anything relating to programming here!

Cross posting is strongly encouraged in the instance. If you feel your post or another person's post makes sense in another community cross post into it.

Hope you enjoy the instance!

Rules

Rules

  • Follow the programming.dev instance rules
  • Keep content related to programming in some way
  • If you're posting long videos try to add in some form of tldr for those who don't want to watch videos

Wormhole

Follow the wormhole through a path of communities !webdev@programming.dev



founded 3 years ago
MODERATORS