# Naming in a Codebase: An Architectural Matter

> Why naming is not merely a style choice, but a design decision in its own right — patterns I have observed over the years.

- Published: 2022-10-02
- Category: Languages
- Tags: OOP
- Reading time: 3 min read
- Source: https://www.muhammetsafak.com.tr/en/blog/naming-in-a-codebase-an-architectural-matter/
- Language: en-US
- Author: Muhammet Şafak

---
One of the most debated topics in code reviews is names. It was something I noticed while [putting SOLID's single responsibility principle into practice](/en/blog/putting-solid-into-practice-in-php-single-responsibility-principle/): if you can't name a class properly, you haven't drawn its responsibility properly either. "Let's find a better name for this variable", "this method name sets the wrong expectation." These conversations can feel like a stylistic preference — as if someone is just being a perfectionist. But I think the vast majority of these discussions are really about something else: design.

When a name is hard to come up with, the object or method's purpose is usually unclear. A naming problem is, in fact, a design problem.

## A bad name is the surface of bad design

Consider this method signature:

```php
public function process(array $data): array
```

What does `process` do? What does `$data` contain? What does the return value look like? We have no idea. We have to open the code and read it.

Now think about what happens when you try to fix the name. "Process order data"? But there's user validation inside it too. "Save form"? But it doesn't write to the database — it only transforms. "Transform form data into an order model"? That's better, but you end up with something like `validateAndTransformOrderData` — which means the name itself is already raising a warning: this method is doing too much.

If you can't find a name, the object or method probably does not have a single responsibility.

## How to tell a name is strong

A good name has a few key properties:

**It communicates intent, not implementation.** Not `getUsersByActiveStatus`, but `findActiveUsers`. Not `calculateAndReturnTotal`, but `total()`. Tell the caller what it does, not how it does it.

**It creates no surprises.** When you call `save()`, what do you expect? For data to be saved. If that method also sends an email or writes a log entry — the name didn't prepare you. That's a breach of trust; a small one, but they accumulate and erode confidence in the codebase.

**It speaks the language of the domain.** In a fintech application, `amount` and `total` can mean different things. In an e-commerce system, `order` and `cart` are not the same. When names come from the domain's language, the code becomes easier to discuss with someone who understands that domain.

## Problems I frequently see in class names

**Manager, Handler, Helper, Util:** These are red flags. These names say "I'm not entirely sure what this class does." What does `UserManager` do? Everything. What does `PaymentHelper` do? Something. These classes bloat over time because anyone can throw anything into them.

```php
// Vague
class PaymentHelper
{
    public function process($data) {}
    public function validate($data) {}
    public function format($amount) {}
    public function log($payment) {}
}

// Clearer — each class has one responsibility
class PaymentProcessor
{
    public function charge(Money $amount, PaymentMethod $method): PaymentResult {}
}

class PaymentValidator
{
    public function validate(PaymentRequest $request): ValidationResult {}
}
```

**Verb-heavy class names:** Class names like `CreateOrder`, `ProcessPayment`, or `SendEmail` are typically an action pattern or command pattern implementation. These are fine in their proper context; but if all your class names follow the verb+noun form, you may just be splitting a large procedural codebase into smaller pieces. Object-oriented design is not always that.

## Consistency between a method's name and signature

When a method's name and its signature don't align, that too is a design signal:

```php
// The name says "find" but it throws an exception — this is "find or explode"
public function findUser(int $id): User
{
    $user = $this->repository->find($id);
    if (!$user) {
        throw new UserNotFoundException($id);
    }
    return $user;
}

// More explicit names
public function findUser(int $id): ?User  // can return null
public function getUser(int $id): User    // throws if not found — getX semantics
```

This distinction seems minor, but it shapes the expectations of whoever consumes the API. A caller of `findUser` will write a null check; a caller of `getUser` will think about try-catch.

## A name is a record of a decision

When you rename something, you sometimes realize you've done more than just rename it. Maybe you split a class. Maybe you moved a method. Maybe you added an abstraction layer. The name acted as a mirror that showed you your design.

That's why I don't see naming as a "style" discussion. A naming discussion is most often a design discussion — and having it early is far cheaper than having it months after the code was written.

Good names turn a codebase into something that explains itself. That is one of the quiet but lasting ingredients of sustainable software.
