Fundamentals 12 min read

Effective Object Naming: Avoiding “-er”/“-or” Suffixes, God Classes, and Building Intelligent Domain Objects

This article explains why thoughtful object naming—avoiding generic “er”/“or” suffixes and vague Service/Helper classes—improves code readability, maintainability, and AI‑assisted development, and demonstrates better designs with concrete C# examples that model real‑world business roles and adaptive behavior.

Java Captain
Java Captain
Java Captain
Effective Object Naming: Avoiding “-er”/“-or” Suffixes, God Classes, and Building Intelligent Domain Objects

Introduction

In many projects, teams tend to adopt a "feature‑stacking" approach: as soon as a requirement arrives, they add logic or functions without spending time on design, especially on object naming. This seemingly fast way often harms code readability and thus maintainability.

A good object name is not just about making code look tidy; it influences how humans and AI perceive the system, shaping future maintenance, extension, and refactoring decisions. In other words, appropriate naming determines both current elegance and the mental pathways for future changes.

Below we explore several examples that show how proper naming can let objects truly reflect business meaning and autonomous decision‑making instead of being passive executors.

1. Avoid Object Names Ending with "er" or "or"

Imagine you walk into a restaurant and tell the chef: "First add oil, then stir‑fry on high heat, then add seasoning." The corresponding code would look like this:

class FoodMaker {
    public Dish Cook(List
cookingSteps) {
        foreach (var step in cookingSteps) {
            ExecuteStep(step);
        }
        return new Dish();
    }
}

// client code
var maker = new FoodMaker();
var steps = new List
{
    new Step("放油"),
    new Step("大火爆炒"),
    new Step("加调料")
};
var dish = maker.Cook(steps);

The name FoodMaker suggests a simple executor and lacks professional autonomy, burdening the caller with low‑level details.

A more realistic design is to let the chef decide how to prepare the dish based on expertise:

class Chef {
    public Dish PrepareKungPaoChicken() {
        // Chef knows how to prepare this dish
        return new KungPaoChicken();
    }
}

// client code
var chef = new Chef();
var dish = chef.PrepareKungPaoChicken();

The Chef name conveys expertise and autonomy, allowing the client to simply state the desired dish.

Many objects ending with “-er” or “-or” (e.g., Manager , Processor , Controller , Validator ) tend to become process‑oriented collections rather than true business entities. Renaming them to reflect professional roles raises their "self‑awareness" and improves abstraction and maintainability.

2. Suffixes Like "Service", "Helper", "Utility" Often Lead to God Classes

With AI‑assisted programming tools becoming common, clear naming is crucial in large projects. Vague or overly abstract names increase cognitive load for team members and for AI, which may produce misleading completions. An example of a bad design:

Bad Example: RestaurantService Handles Everything

public class RestaurantService {
    // Manages cooking, delivery, finance, etc.
    public void cookDish(String dishName) { }
    public void deliverFood(String address) { }
    public void scheduleStaff(String staffName, String shift) { }
    public void handleBilling() { }
}

Problems:

Too broad – violates the Single Responsibility Principle.

Misleads AI tools into assuming any restaurant‑related logic resides here.

Hard to maintain and extend because all functionalities are tightly coupled.

A better design splits responsibilities according to real‑world roles:

// Focus on cooking logic
public class Kitchen {
    public void cookDish(String dishName) { /* ... */ }
}

// Focus on delivery
public class Delivery {
    public void deliverFood(String address) { /* ... */ }
}

// Focus on staff scheduling
public class StaffScheduling {
    public void schedule(String staffName, String shift) { /* ... */ }
}

// Focus on billing
public class Billing {
    public void settleAccounts() { /* ... */ }
}

Benefits:

Clear responsibilities for each class.

Easier for humans and AI to infer functionality from the name.

Facilitates independent extension of each module.

Matches real‑world separation of kitchen, delivery, HR, and finance.

3. Object Naming and "Intelligent" Behavior: Adapting to Environmental Changes

In real life, if a required ingredient (e.g., peanuts) runs out, a professional chef substitutes it without asking the customer to change the order. Similarly, a well‑named object should adapt internally when external conditions change, keeping the client interface stable.

Process‑Oriented Example

public class CookingProcess {
    public Dish cook(String dishName) {
        // Fixed steps regardless of ingredient availability
        return new Dish(dishName);
    }
}

Limitations:

The caller must handle missing ingredients.

Every requirement change forces modifications to the method or calling code.

Improved Example: Chef as a Professional Who Adapts

The Chef class decides internally whether peanuts are in stock and substitutes alternatives if needed:

public class Chef {
    // Simulated stock status, could come from DB or config
    private boolean peanutsInStock = false;

    public Dish prepareDish(String dishName) {
        if ("宫保鸡丁".equals(dishName)) {
            if (!peanutsInStock) {
                // Use cashews or other nuts as substitute
            }
            // Normal preparation otherwise
        }
        // Other cooking logic
        return new Dish(dishName);
    }
}

Advantages:

All decision‑making resides inside Chef , improving cohesion.

Client code remains unchanged regardless of stock status.

Future adaptations (e.g., other ingredient shortages) only require changes inside Chef .

Client Call Example (Unchanged)

public class Main {
    public static void main(String[] args) {
        Chef chef = new Chef();
        // Client only specifies the desired dish
        Dish dish = chef.prepareDish("宫保鸡丁");
        // Even if peanuts are out of stock, Chef handles it internally
    }
}

Regardless of peanut availability, the client invocation stays the same: a smart Chef performs the necessary adaptation.

Conclusion: Naming Is Design

Object naming is often treated as a cosmetic issue, yet it deeply affects business understanding and system thinking. By avoiding vague suffixes like "-er", "Service", or "Utility" and letting names reflect true professional roles, teams gain the following benefits:

Reduced misunderstandings—new members and AI tools quickly grasp intent.

Higher cohesion—logic boundaries become clear, reducing ripple effects of changes.

Easier extensibility—each object behaves like an independent module.

Better alignment with business—communication with product teams becomes more efficient.

In software engineering, naming is rarely emphasized, but it subtly shapes how we think while coding. Treating objects as entities with dignity and autonomous decision‑making leads to highly cohesive, extensible systems that truly reflect business essence.

software architecturesoftware designclean codeCode readabilityAI-assisted programmingobject naming
Java Captain
Written by

Java Captain

Focused on Java technologies: SSM, the Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading; occasionally covers DevOps tools like Jenkins, Nexus, Docker, ELK; shares practical tech insights and is dedicated to full‑stack Java development.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.