[From sandbox] Long names are too long

[From sandbox] Long names are too long


Hello, Habr! I present to you the translation of the article "Long Names 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 ways. First, someone on the team does a routine check to make sure the code does what it should.


But then the second stage 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 it easy to understand and maintain this code? Does this code match the style and idioms of the language? Is the code well documented?


Using the language Dart in Google is gradually gaining momentum, and I have been doing a lot like code review. For a language developer, this is a very exciting process. I get first-hand an idea 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 used extensively. I feel like an ethnographer, leading a diary about the life of natives.


But, in any case, that's not the point. Damn him, it's not even Darts. What I go 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. At a time when C required only external identifiers to be unique up to the first six characters; when autocomplete has not yet been invented; when every keystroke was like going uphill through the snow, that was a problem. I am glad that now we live in a futuristic utopia, where keyboard farting, like p , idxcrpm and x3 , are rare.


But the pendulum has swung too far in the other direction. We don't have to be Hemingway, we also don't need to be Tennessee Williams. Unnecessarily 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. The code becomes difficult to visually scan. To meet the requirements for the width of the code, there are additional line breaks 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 the stretching of chains of methods or cascades.


I've seen variable names longer than 60 characters. You can put a haiku or koan in there (and probably enlighten the reader more than the chosen name). But fear not, I'm here to help.


Choosing a good name


Any name in programming has two goals:


  • The name must be clear : you need to know what it refers to.
  • The name must be exact : you need to know what it does not refer to.

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


1. Avoid words that are explicitly defined in the type of a variable or parameter


If your language has a static type system, users usually know the type of the variable. As a rule, methods are fairly short, so even looking at a local variable, where the type cannot be assumed right away, or with a code review, or in some place where static code analysis cannot get in - rarely need a little more than viewing a few lines. above to determine the type of variable.


Given this, it is unnecessary to specify the type in the variable name. We just gave up Hungarian notation . Let go and forget :


 //Poor:
 String nameString;
 DockableModelessWindow dockableModelessWindow;
//Good:
 String name;
 DockableModelessWindow window;  

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


 //Poor:
 List & lt; DateTime & gt;  holidayDateList;
 Map & lt; Employee, Role & gt;  employeeRoleHashMap;
//Good:
 List & lt; DateTime & gt;  holidays;
 Map & lt; Employee, Role & gt;  employeeRoles;  

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


 //Poor:
 mergeTableCells (List & lt; TableCell & gt; cells)
 sortEventsUsingComparator (List & lt; Event & gt; events,
  Comparator & lt; Event & gt;  comparator)
//Good:
 merge (List & lt; TableCell & gt; cells)
 sort (List & lt; Event & gt; events, Comparator & lt; Event & gt; comparator)  

This causes calls to read better than this:


  mergeTableCells (tableCells);
 sortEventsUsingComparator (events, comparator);  

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


2. Avoid words that do not remove ambiguity in the name


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


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


  • Are there updated annual sales orders that are not recent?
  • Are there recent sales bids that have not been updated?
  • Are there recently updated non-sales annual bids?
  • 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.


 //Poor:
 finalBattleMostDangerousBossMonster;
 weaklingFirstEncounterMonster;
//Good:
 boss;
 firstMonster;  

Of course, you may well go too far. Reducing the first example to bid may be too vague. But if in doubt, leave it that way. You can always add an additional classification later if the name turns out to be the cause of a collision 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 do not need to constantly repeat here "Bob Nystrom" (despite the temptation of Bob Nystrom to increase Bob Nystrom in this way). The code works in exactly the same way. A method or field is found in the context of a class. The variable is found in the context of the method. Take this context for granted and do not repeat it.


 //Poor:
 class AnnualHolidaySale {
  int _annualSaleRebate;
  void promoteHolidaySale () {...}
 }
//Good:
 class AnnualHolidaySale {
  int _rebate;
  void promote () {...}
 }  

In practice, this means that the deeper the name is nested, the more ambient context it has. The result is that this name will be shorter. As a result, one can notice a pattern: identifiers that are in a narrower domain have shorter names.


4. Avoid words that mean nothing


I often see this error in the gaming industry. Some developers give in to temptation and inflate the names of their variables by 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. Usually suspicions fall on such words as: data , state , amount , value , manager , engine , object , entity and instance .


A good name paints some picture in the mind of the reader. By calling something "manager", we do not convey to the reader any information about what this object should do. Does he do the calculation of performance estimates? Assigns promotion to their employees?


Ask yourself the question: "Will this name mean the same thing if I remove this word?". If so, then the word does not matter - expel from the island.


Applying a guide to ... waffles


To give you an idea of ​​how these rules work in practice, here is an example that breaks 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 & lt; Strawberry & gt;  strawberryList) {...}
 }  

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


  class DeliciousBelgianWaffleObject {
  void garnishDeliciousBelgianWaffle (
  List & lt; Strawberry & gt;  strawberries) {...}
 }  

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


  class WaffleObject {
  void garnishWaffle (List & lt; Strawberry & gt; 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 & lt; Strawberry & gt; strawberries) {...}
 }  

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


  class Waffle {
  void garnish (List & lt; Strawberry & gt; strawberries) {...}
 }  

Now much better.


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

Source text: [From sandbox] Long names are too long