DEV Community

Cover image for The Art of Naming Things in Code: Ditch Single-Letter Variables and `utils` Classes
Rajax
Rajax

Posted on

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-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:

  1. Saving physical keystrokes on primitive keyboards.
  2. 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);
Enter fullscreen mode Exit fullscreen mode

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 I Prefix for Interfaces: Adding I to 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 Base Prefix for Parent Classes: When creating a base class for an existing entity (such as a truck), developers often resort to BaseTruck. 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 as TrailerTruck or PickupTruck).

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) { ... }
Enter fullscreen mode Exit fullscreen mode

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:

  1. Move single-entity operations into the domain model: Methods operating directly on a single video's data belong as methods inside the Video class itself.
  2. Create domain collection classes: Methods that filter or manipulate lists of videos belong inside a specialized VideoCollection class.
  3. Extract cross-cutting concerns into specialized classes:
    • Move pagination logic into a standalone Paging<T> class.
    • Move cookie handling into a dedicated Cookie class.
// ❌ 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 { ... }
}
Enter fullscreen mode Exit fullscreen mode

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.

Top comments (1)

Collapse
 
rajaxcode profile image
Rajax •

✅