Long names are too long

Hello, Habr! I present to you the translation of the article "Long Names Are Long" by Bob Nystrom.

One of the smart things Google does is strict code review. Each change, before you are allowed to make it to the main branch, is considered in at least two directions. First, someone on the team does a routine check to make sure the code does what it should.

But then the second step occurs, when the readability of the code is checked . This ensures that other developers will be able to support this code in the future. Is this code easy to understand and maintain? Does this code match the style and idioms of the language? Is the code well documented?

The use of the Dart language on Google is gradually gaining momentum, and I dealt a lot with such code review. For a language developer, this is a very exciting process. I get a first-hand view of how people use Dart, which is really useful for its development. I have a clearer idea of ​​which errors are common and which functions are heavily used. I feel like an ethnographer, a diary about the life of the natives.

But, in any case, this is not the case. Damn him, it's not even Darts. What I want to talk about is what I see in many codes, and what drives me crazy: overly long names .

Yes, the names may be too short. In those days when C demanded that only external identifiers be unique up to the first six characters; when autocompletion has not yet been invented; when every keystroke was like climbing uphill through the snow - this was a problem. I am glad that now we live in a futuristic utopia, where keyboard farts, like p, idxcrpmand x3, are rare.

But the pendulum swung too far in the other direction. We do not have to be Hemingway, we also do not need to be Tennessee Williams. Overly long names also harm the clarity of the code in which they are used. Very long variable names overshadow the operations you perform on them. Code becomes difficult to visually scan. To meet the requirements for code width, additional line breaks appear that interrupt the logical flow of code. Long method names hide their equally important argument lists. Long variables are annoying from reuse, which leads to stretching chains of methods or cascades.

I saw variable names longer than 60 characters. You can put a haiku or koan there (and probably enlighten the reader more than the name you choose). But fear not, I am here to help.

Choosing a Good Name

Any name in programming has two goals:

  • The name should be clear : you need to know what it refers to.
  • The name must be accurate : you need to know what it does not apply to.

Once the name has achieved these goals, any additional characters are dead weight. Here are some guidelines that I use when I name things in my code:

1. Avoid words that are explicitly specified in a variable or parameter type

Если ваш язык имеет статическую систему типов, то пользователи обычно знают тип переменной. Как правило, методы бывают достаточно короткими, поэтому посмотрев даже на локальную переменную, где тип нельзя предположить сразy, или при code review, или в каком-либо месте, куда статический анализ кода не может попасть — редко потребуется чуть больше, чем просмотр нескольких строк выше, чтобы определить тип переменной.

Учитывая это, излишне указывать тип в имени переменной. Мы только отказались от Венгерской нотации. Отпусти и забудь:

// Плохо:
String nameString;
DockableModelessWindow dockableModelessWindow;
// Хорошо:
String name;
DockableModelessWindow window;

In particular for collections, it is almost always better to use a plural noun describing the content than a singular noun describing a collection . If the reader cares more about what is in the collection, then the title should reflect that.

// Плохо:
List holidayDateList;
Map employeeRoleHashMap;
// Хорошо:
List holidays;
Map employeeRoles;

This also applies to method names. The name of the method does not need to describe its parameters or their types - the list of parameters will do it for you.

// Плохо:
mergeTableCells(List cells)
sortEventsUsingComparator(List events,
    Comparator comparator)
// Хорошо:
merge(List cells)
sort(List events, Comparator comparator)

This results in calls being read better than this:

sortEventsUsingComparator(events, comparator);

Is it just me, or is there an echo-echo here?

2. Avoid words that do not disambiguate the name

Some people tend to push everything they know about something into the name of a variable. Remember that the name is an identifier : it indicates the place where it is defined. This is not an exhaustive catalog of everything that the reader may want to know about the object. Definition will make it better. The name will only direct him there.

When I see the name as recentlyUpdatedAnnualSalesBid, I ask myself:

  • Are there any updated annual sales orders that are not the latest?
  • Are there any recent annual sales requests that have not been updated?
  • Are there any recently updated annual non-sales applications?
  • Are there recently updated annual sales data that are not bids?

If the answer is “no” to at least one of these questions, then this usually indicates an extra word in the name.

// Плохо:
// Хорошо:

Of course, you may well go too far. The abbreviation of the first example to bidmay be too vague. But if in doubt, leave it like that. You can always add an additional classification later if the name is the cause of the conflict or is inaccurate. However, it is unlikely that you will return later to trim all this excess fat.

3. Avoid words that are clear from the context.

I can use the word “I” in this paragraph because you know that this text is from Bob Nystrom. I don’t need to constantly repeat “Bob Nystrom” here (despite the temptation of Bob Nystrom to strengthen Bob Nystrom in this way). The code works exactly the same. A method or field occurs in the context of a class. A variable occurs in the context of a method. Take this context for granted and do not repeat it.

// Плохо:
class AnnualHolidaySale {
  int _annualSaleRebate;
  void promoteHolidaySale() { ... }
// Хорошо:
class AnnualHolidaySale {
  int _rebate;
  void promote() { ... }

In practice, this means that the deeper the name is embedded, the more surrounding context it has. As a result, it turns out that this name will be shorter. As a result, you can see a pattern: identifiers that are in a narrower area have shorter names.

4. Avoid words that mean nothing.

I often see this mistake in the gaming industry. Some developers succumb to the temptation and inflate the names of their variables, adding words from “serious business”. They believe that this makes their code more important and, accordingly, makes them more important.

In most cases, these words do not carry any meaningful information for the developer. Typically, suspicions fall on words such as: data, state, amount, value, manager, engine, object, entityand instance.

A good name paints a picture in the mind of the reader. Calling anything a “manager," we don’t give the reader any information about what this object should do. Does it do a performance assessment calculation? Appoints promotion to their employees?

Ask yourself: “Will this name mean the same if I take that word away?” If yes, then the word does not matter - drive out from the island.

Applying the manual to ... waffles

To give you an idea of ​​how these rules work in practice, here is an example that violates all of them. This contrived example is very similar to real code, which quite often comes across to me on code review.

class DeliciousBelgianWaffleObject {
  void garnishDeliciousBelgianWaffleWithStrawberryList(
      List strawberryList) { ... }

Thanks to the type of parameter, we know that the method accepts a list of strawberries (# 1). Let's cut this info out of a name:

class DeliciousBelgianWaffleObject {
    void garnishDeliciousBelgianWaffle(
        List strawberries) { ... }

If there are no tasteless Belgian waffles or wafers of any other nationalities in the program, then we can safely discard all adjectives (# 2):

class WaffleObject {
  void garnishWaffle(List strawberries) { ... }

This method is inside WaffleObject, so from the context we know what exactly it is going to decorate (# 3):

class WaffleObject {
  void garnish(List strawberries) { ... }

Obviously this is an object. Everything is an object in object-oriented programming (# 4):

class Waffle {
  void garnish(List strawberries) { ... }

Now much better.

I think these are pretty simple recommendations. You have the right to think that it is useless to worry about such trifles. But I believe that naming is one of the most fundamental tasks that we perform when programming. Names are the structure that we impose on the shapeless sea of ​​bits, which is the computer.

Also popular now: