The Art of Naming Things in Code: Ditch Single-Letter Variables and `utils` Classes
The Art of Naming Things in Code: Ditch Single-Letter Variables and utils Classes While finding the absolute perfect name can be tricky, you can solve 80% of your clean-code naming struggles by simply eliminating well-
The Art of Naming Things in Code: Ditch Single-Letter Variables and
utilsClasses
While finding the absolute perfect name can be tricky, you can solve 80% of your clean-code naming struggles by simply eliminating well-known anti-patterns. Naming is not just an aesthetic choice; how you name your variables and classes directly reflects your understanding of domain boundaries and system architecture.
Here are four essential rules for naming things in codeβand how to refactor anti-patterns into clean, maintainable design.
1. Ditch Single-Letter Variables and Cryptic Abbreviations
Single-letter variables (like x, y, i, u, d) originated when computer science was tightly bound to mathematics. Mathematicians value brevity and concise notation because a mathematical equation is a static formula meant to be read on paper.
Software, on the other hand, is read and modified thousands of times more often than it is written.
Why Abbreviations No Longer Make Sense
Historically, abbreviations served two practical constraints:
- Saving physical keystrokes on primitive keyboards.
- Fitting code within old 80-column terminal screens.
Today, modern IDEs provide instant auto-completion, and widescreen monitors offer abundant horizontal space. There is no longer any operational reason to save a few characters at the expense of readability.
// β Bad: Cryptic and forces the reader to guess intent
const per = calculate(u, d);
// β
Clean: Explicit, readable, and self-documenting
const periodDays = calculatePeriod(user, durationDays);
2. Stop Embedding Types and Prefixes in Names
In legacy codebases, developers frequently relied on Hungarian Notationβprefixing variable names with their data types (such as strName or iCount). This practice arose before C and C++ had strong, pervasive static type systems, forcing developers to manually track types in variable names.
Modern statically typed languages render type prefixes completely redundant. Your compiler and IDE already know the typeβadding it to the variable name only creates clutter.
Interface (I) and Base (Base) Prefixes
-
The
IPrefix for Interfaces: AddingIto interfaces (e.g.,IObjectAnimator) provides no value to the caller. Consumers of your API care about the methods and behaviors exposed, not whether the underlying type happens to be an interface, an abstract class, or a concrete class. -
The
BasePrefix for Parent Classes: When creating a base class for an existing entity (such as a truck), developers often resort toBaseTruck. If you struggle to name a base class, give the general domain name (Truck) to the parent class, and specialize child classes with descriptive names (such asTrailerTruckorPickupTruck).
3. Make Units of Measurement Explicit
Raw numeric values without units are a frequent source of subtle bugs. If a function accepts a delay parameter, naming it delay leaves the developer guessing whether it expects milliseconds, seconds, or minutes.
Always embed the unit directly into the variable name unless you are using dedicated value objects.
// β Ambiguous: Is delay in milliseconds or seconds?
function setTimer(delay: number) { ... }
// β
Explicit: Unit is clear from the parameter name
function setTimer(delaySeconds: number) { ... }
The Better Alternative: Dedicated Time Types
In languages with strong type systems (such as C++, C#, or Rust), prefer dedicated duration types like TimeSpan or std::chrono::duration. These types encapsulate the unit entirely, preventing unit-mismatch bugs at compile time. You extract the raw numeric value only when needed (e.g., .totalSeconds()). In dynamic languages like Python or JavaScript, embedding the unit into the variable name remains essential.
4. utils and helper Classes: A Architecture Red Flag
When you struggle to name a class and resort to dumping unrelated functions into a catch-all utils or helper class, it is rarely a naming problemβit is a code architecture flaw.
Standard libraries in modern programming languages do not have generic utils classes. Instead, they organize functionality into cohesive, descriptively named modules and classes.
How to Eliminate utils Classes Through Refactoring
Consider a video-processing application with a VideoUtils class containing several unrelated helper functions. You can refactor and completely eliminate VideoUtils in three steps:
-
Move single-entity operations into the domain model: Methods operating directly on a single video's data belong as methods inside the
Videoclass itself. -
Create domain collection classes: Methods that filter or manipulate lists of videos belong inside a specialized
VideoCollectionclass. -
Extract cross-cutting concerns into specialized classes:
- Move pagination logic into a standalone
Paging<T>class. - Move cookie handling into a dedicated
Cookieclass.
- Move pagination logic into a standalone
// β Anti-Pattern: A bloated utils class with mixed responsibilities
class VideoUtils {
static getVideoTitle(video: Video) { ... }
static filterTopVideos(videos: Video[]) { ... }
static paginateVideo(videos: Video[], page: number) { ... }
static setCookie(name: string, value: string) { ... }
}
// β
Clean Architecture: Responsibilities distributed to cohesive classes
class Video {
getTitle(): string { ... }
}
class VideoCollection {
filterTop(): Video[] { ... }
}
class Paging<T> {
paginate(items: T[], page: number): T[] { ... }
}
class Cookie {
static set(name: string, value: string): void { ... }
}
Once all responsibilities are reassigned to their proper homes, VideoUtils becomes completely empty and can be safely deleted.
Summary
Naming things in software engineering is ultimately about domain design. Avoid single-letter variables and redundant prefixes, clarify measurement units, and whenever you feel tempted to create a utils class, pause and refactor your class boundaries instead.
Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes β full credit and traffic to the original publisher.