DEV Community

Saulo Dias
Saulo Dias

Posted on • Updated on

Naming Patterns Matter

One of the things no programming course explicitly teaches about is naming patterns. This happens because there is no such thing as a universal standard when it comes to naming conventions.

Of course some languages will have some well known general guidelines, PEP-8 for Python, while other languages will have some general guidelines which are not set in stone but usually produce good practical results.

For example, with TypeScript:

  • Classes, and Interfaces/Types must be in PascalCase;
  • Exported strings/constants should be in UPPERCASE_SNAKE_CASE;
  • Methods and functions should be in camelCase();
  • And so on...

However, when it comes to naming conventions it may vary from project to project, and things can get messy when a developer has "tunnel vision".

In this case, what I mean by having tunnel vision is not paying attention to what I call "implicit standards".

Explicit standards are easy to validade. You can use a linter or other tools to highlight code smells and stuff like that, and reinforce such standards. However, implicit standards can be identified if you look at how people did things before you touched the code.

For example:

class User {
  private _firstName: string;
  private _height: number;
  private _lastName: string;
  private _userBirthdate: Date;
  private _weight: number;

  constructor(firstName: string, lastName: string, height: number, weight: number, userBirthdate: Date) {
    this._firstName = firstName;
    this._height = height;
    this._lastName = lastName;
    this._userBirthdate = userBirthdate;
    this._weight = weight;
  }

  getFirstName(): string {
    return this._firstName;
  }

  getHeight(): number {
    return this._height;
  }

  getLastName(): string {
    return this._lastName;
  }

  getUserBirthdate(): Date {
    return this._userBirthdate;
  }

  getWeight(): number {
    return this._weight;
  }
}

Enter fullscreen mode Exit fullscreen mode

At first glance, there doesn't seem to be any problem regarding cases and such, but if you look closely you'll realize no other method except for the getUserBirthDate has the word "User" in its name. This might not be an issue in terms of functionality but this is what I meant by implicit standards.

The namespace (User) is already explicit since those methods can only be accessed from an instance of User. Therefore the correct pattern in this context would be getBirthdate, and the same goes for the corresponding private property and for the constructor parameter.

Another example:

// utils-formatters.ts

export const dateFormatter = (value: Date) => {
  // TODO: do something with value and return it
}

export const formatBoolean = (value: boolean) => {
  // TODO: do something with value and return it
}

export const numberFormatter = (value: number) => {
  // TODO: do something with value and return it
}

export const textFormatter = (value: string) => {
  // TODO: do something with value and return it
}
Enter fullscreen mode Exit fullscreen mode

Did you notice the pattern and what is wrong here? All of those custom functions are formatters for different data types. However, the one to handle booleans stands out because it doesn't look like the other ones. Again, the arrow functions are all in camel case, but that one disregards the pattern set by the other ones which is data type + Formatter. This is something difficult to reinforce with linters and other automation tools.

In a nutshell, it is the developer's job to code looking around, and paying attention to how things have been done before. One may argue that the current pattern is not readable or good, and this can be discussed and changed within your project/team, where you can deprecate an old, bad pattern, and reinforce and start a migration to a new one without breaking existing functionality. Either way, consistency is more important than a developer's preference.

Discussion (0)