質問

Don't be afraid to make a name long. A long descriptive name is better than a short enigmatic name. A long descriptive name is better than a long descriptive comment.

Robert C. Martin

Did I understand Clean Code right? You put the whole information that you would put into a comment into the class/method/... name. Wouldn't that lead to long names like:

PageReloaderForPagesDisplayingVectorGraphicsThatAreUsedInTheEditorComments
PageReloaderForPagesDisplayingVectorGraphicsThatAreUsedInTheEditorDescriptions
役に立ちましたか?

解決

You have to take everything in Clean Code together. I've read the book more than once. I frequently lend it to new developers on my team.

Yes, Martin does say you should prefer long, descriptive names over comments. However, he also advocates for the Single Responsibility Principle.

I've seen SRP defined a few ways, usually "a class or method should only have one reason to change", or "a class or method should do only one thing".

So, I tell my developers to write very descriptive names. I also frequently tell them that if the name of the method is getting too long, it is probably doing too many things.

If the name of the method is becoming unmanageable, consider if something needs refactoring.

I also tell my team to avoid the Incredibles Pattern. As we learned from Syndrome, "when everybody's special, nobody's special."

If every property or method of you class starts or ends with the same word(s), you can probably omit that word.

Assuming these are both members of one class, would the following make sense?

It looks like you have many PageReloaders, so we make a base class for the things all PageReloaders do.

abstract class PageReloader {
    //page reloader code
}

Next, the name indicates that being "used in the editor" is significant, so there must be other kinds of VectorGraphicsReloaders.

abstract class VectorGraphicsReloader : PageReloader{
    //vector graphics code
}

Finally, we get to the EditorGraphicsReloader, which is a VectorGraphicsReloader that does something specifically for the editor.

class EditorGraphicsReloader : VectorGraphicsReloader{
    //editor code
}

Within one of these class we should have two properties:

public string Comments { get; set; }
public string Description { get; set; }

The class these properties belong to depends on whether they are unique to the editor, vector graphics, or common to all page reloaders.

他のヒント

Yes, you understand Clean Code right, but your examples are quite a bit over the top.

Here is what you start with:

PageReloaderForPagesDisplayingVectorGraphicsThatAreUsedInTheEditorComments 
PageReloaderForPagesDisplayingVectorGraphicsThatAreUsedInTheEditorDescriptions

A "Page Reloader" presumably reloads pages, so the "Pages" part is redundant. This leaves you with:

PageReloaderForDisplayingVectorGraphicsThatAreUsedInTheEditorComments 
PageReloaderForDisplayingVectorGraphicsThatAreUsedInTheEditorDescriptions

Pages are always displaying stuff, so the Displaying part is redundant, too. This leaves you with:

PageReloaderForVectorGraphicsThatAreUsedInTheEditorComments 
PageReloaderForVectorGraphicsThatAreUsedInTheEditorDescriptions

In English, constructs like this-that-is-used-in-that can be reworded as that-this. For example, coloring-that-is-used-for-food is food-coloring. Applying this rule, leaves you with:

PageReloaderForEditorCommentsVectorGraphics 
PageReloaderForEditorDescriptionsVectorGraphics

Also in English, constructs like this-for-that can be reworded as that-this. For example, bottle-for-water can be reworded as water-bottle. Applying this rule, leaves you with:

EditorCommentsVectorGraphicsPageReloader
EditorDescriptionsVectorGraphicsPageReloader

And then of course there may be other shortcuts you can apply.

For example, in your system you probably don't have many kinds of reloaders. You probably only have page reloaders, so this would leave you with:

EditorCommentsVectorGraphicsReloader
EditorDescriptionsVectorGraphicsReloader

Also, when you speak of 'vector' in your system, it may be fairly clear that you are speaking of 'vector graphics', so this would leave you with:

EditorCommentsVectorReloader
EditorDescriptionsVectorReloader

... and I think that these are some pretty good realistically long names.

No, Uncle Bob is not saying that.

There is no part in his book saying that you have to put ALL COMMENTS in the class name, "the whole information" that you mentioned.

Probably you don't need a specific "PageReloader for Pages Displaying Vector Graphics etc etc" and should use the same PageReloader for all kind of pages.

In his book there are a lot of examples of what he exactly means with "replacing short enigmatic names by descriptive meaningful ones".

There is always a balance to be struck. Usually when software pundits speak, they are addressing a commonly understood problem of their time and place.

If names are so non-descript and enigmatic that they require explanation - like using f, g, and h, as the parameters of a method - then in the first place these should be elongated and made more descriptive.

There was a period when it was considered a significant problem for programmers to be habitually using overly-short names (often a random letter), and things would be radically improved simply by using a descriptive word or two.

Nowadays, the opposite problem is often observed. Programmers using unnecessarily verbose names, often a mangling of highly general terminology that is not especially descriptive of anything.

An example of the latter which most recently caught my eye was "ApplicationServices" - I couldn't immediately see how this was more descriptive than "ProgramTools", "CodeStuff" or even "AppSvcs".

"VectorGraphics" could arguably be reduced to "LineArt" without any loss of meaning, but even the abbreviation "VectGfx" would probably be quite enough.

So the principle of making names descriptive should not be read as meaning make names as long as possible. It's about using names that contain a high information density.

An element of that still involves being economical with syllables and characters, and relying on implied knowledge, such as a good command of the English language, and familiarity with general computer concepts.

I agree with this answer https://softwareengineering.stackexchange.com/a/409460/262662 by Mike Nakis, but there's more.

Additionally, you can namespace and group some of this. such as

PageReloaders.EditorCommentsVector
PageReloaders.EditorDescriptionsVector

Then if you had more variables with equally long names, you could (only in short functions/blocks)...

Reloaders = Utilities.Reloaders.PageReloaders;
Reloaders.EdtiorCommentsVector.doSomething(); // small scope only.
// equivalent to...
Utilities.Reloaders.PageReloaders.EdtiorCommentsVector.doSomething();

// And with prettier, so long as the segments are within about 40 characters, it doesn't matter.  As it will look like this:
ReallyLongPath
  .filledWithLongStrings
  .JustToGetTo
  .Utilities
  .Reloaders
  .PageReloaders
  .EditorCommentsVector
  .doSomething();

Update

If I had to actually come up with my own names, based on the original, instead of Naki's answer, I would use the following.

PageReloaders.VectorGraphicsPages.EditorComments
PageReloaders.VectorGraphicsPages.EditorDescriptions

Or maybe

PageReloaders.EditorComments.WithVectorGraphics
PageReloaders.EditorDescriptions.WithVectorGraphics

But honestly, it depends on how much stuff you've got going on. If you really need a different pageReloader for editorComments vs editorDescriptions, or a different pageReloader for vectorGraphics pages vs normal? pages vs plainText pages, then you gotta do what you gotta do. If you don't have that much stuff, like if any page might or might not have vector graphics, just go with PageReloaders.EditorComments. Do NOT be afraid to change your variable names as a project grows. And Do NOT use stuff like pgrldr.VGraph.EtrCmnt to try to get shorter variable names. Just don't do it. The goal is to lower the amount of brain strain on future developers (including yourself) when trying to figure out what you did the first time around.

End Update

I believe what Robert C. Martin was actually referring to was the following:

<!-- We actually had this in our codebase -->
<button class="btn-submit pers pers_cp"></btnbutton

<!-- What it meant, using the Clean Code standards -->
<button class="btn-submit btn-personnel_module btn-copy_action"></button> 

This button got copied/pasted across all the modules and to actions that were not copy. When writing css, people did not know what the classes meant, so they used those classes for sizing, instead of just colors. It was hell to detangle it.

This also applies to for loops. What is better...? (again, actually pulled from our codebase)

for (let k=0; k < vehsAr.length; k++) {
  let vehs = vehsAr[k];
}
/*---- OR -----*/
for (let vehicleIndex=0; vehicleIndex < vehiclesArray.length; vehicleIndex++) {
  let vehicle = vehiclesArray[vehicleIndex];
}

With the for(i) loop, if I decided to change the nesting level, I would end up reusing i and then having to shift everything inside to k. If I instead actually used descriptive variables, there is less work to do. A little effort goes a long ways.

for (let r = 0; r < width; r++) {
  for (let c = 0; c < height; c++) {
    grid[r][c].doSomething();
    // I see immediately that rows is the first layer, and columns is the second layer.
    // "row" and "column" is better than "r" and "c", but "r" and "c" still go a long ways.
    invertedGrid[c][r].doSomething(); // If it goes in natural English reading order, I only have to check in one spot that r and c are backwards.
  }
}
// Invert the nesting order
for (let c = 0; c < height; c++) {
  for (let r = 0; r < width; r++) {
    grid[r][c].doSomething();
    invertedGrid[c][r].doSomething();
    // Notice how the inner formulas don't change?
    // If I used 'i' and 'k', convention is that 'i' is top layer, then 'j', then 'k', then 'l' which looks like '1'.  It get messy.
    // If I swapped height/width while using 'i' and 'k', I'd have to put in much more brain power to make sure height matched with the right letter and that letter matched with the right spot.

  }
}

Update Using i j and k in for loops is perfectly acceptable and is the most common way to write a loop. But the Clean Code standard, based on what little I've read of it, does not like it. At all. Just like Prettier 1.0 hated trailing commas and Prettier 2.0 loves trailing commas. It's a standard. It has a reason behind it. It's not the only way. But using longer/more descriptive variable names is the standards directive being examined here.

What I would take away from this is when you have items like:

PageReloaderForPagesDisplayingVectorGraphicsThatAreUsedInTheEditorComments
PageReloaderForPagesDisplayingVectorGraphicsThatAreUsedInTheEditorDescriptions

then what you're lacking is context, that you have too many top-level items that deserve to be grouped together in a logical way, and that that grouping provides context. While this is an extreme example, perhaps it could be refactored as:

Comments.Editor.Page.Reloader
Descriptions.Editor.Page.Reloader

(or maybe Page.Comments.Editor.Reloader, whatever!) where the information about whether the page displays vector graphics or not is part of the type of the page, or even the reloader.

Variable names don't exist in isolation, they sit within the context of other objects, and have types, all of these contribute to understanding.

If you have a name that is getting too long, consider whether the variable itself is carrying too much burden.

Don't forget that part of the audience of that book are older programmers who cut their teeth on old compilers that had very short name length limits. The first C language standard only required compilers to treat the first six characters of externally-visible identifiers as significant (C89 spec section 3.1.2). The functions and types in the C standard library have extremely terse names, sometimes to the point where they can confuse the unfamiliar.

I've always interpreted Martin's advice as more of a condemnation of the old habits that treat horizontal screen space as something that should be taken into consideration. Modern compilers don't really care about name lengths, and programmers (for the most part) aren't writing code on a console that's limited to 80 columns. The advantages of plainly readable names far outweighs any benefits that you get from short (or overly-long) names.

For example, the C standard library has a function called mbstowcs(). Can you tell what that function does? Me neither. Martin is saying that compressed names like that don't hold much value. If instead the function was named ConvertMultibyteStringToWchar(), you could probably make sense out of code that uses it without having to dig through documentation.

This is certainly not a replacement for comments. Comments record all sorts of additional information, like whether the caller has to free the memory returned by the function, what exceptions the function can throw, whether the function is thread-safe, etc. Comments also record things like why the function is implemented the way that it is. This is all information that you can't reasonably stuff into a name, regardless of how long you make it.

I think the only case where longer names can replace comments is in cases like this:

// tokenize a string
char *strtok(char *s1, const char *s2)
{
    ...
}

But if that's all the information that you're documenting about a function, names aren't your #1 problem.

Commenting is inherently dangerous.

  • Use it sparingly for // fixmes

Why dangerous?

  • Code comes and go, but comments are always left behind.
  • People fear deleting comments, because they assume it to be vital true information.
  • Try understanding code with vital FALSE information.

I consider bad commenting, one of the deepest layers in Programming hell.

A function name [for example] however, is less likely to become inaccurate as you change things within it, and if its functionality does change, you are naturally more likely to change the name of it as well.

This is one fundamental but important reason why a long name is preferable over commenting, and why it will lead to cleaner code.

I would like to ignore commenting classes and data structures, because I think that's fine and usually we are more concerned about comments in actual code.

One of the things Uncle Bob does is make his comments a horribly offensive bright red. Not the nice pleasant colors they usually are. This is because he feels that if you have to have a comment in the code it better be worth the horrendous color. If it's worth the offensiveness he leaves it if it isn't he deletes it.

So Uncle Bob does believe that comments should be avoided, but in my mind this is in conflict with another one of this clean coding rules. The rule that the length of a variable name should be proportional to it's scope. So global variables should have long names and local variables should have small names.

For example In one of my functions there was a variable name ip with a comment which shoved in to variable name and I got hostname_or_dotted_decimal_ip. So this eliminated a comment, but then it made the variable unnecessarily long.

I've asked Uncle Bob previously specifically about long variable names in local scopes and his comment was as follows "long variables names in small scopes is obnoxious." I personally think having a somewhat lengthy variable name to kill off a comment is an ok sacrifice given it doesn't make the code obnoxious. If that variable was used 10 times it would probably be obnoxious.

One thing that should be avoided at all cost is hiding the meaningful parts of things at the end of the line. I'm a C developer with zero namespacing and I've never had any function, data structure or variable that long.

PageReloaderForPagesDisplayingVectorGraphicsThatAreUsedInTheEditorComments PageReloaderForPagesDisplayingVectorGraphicsThatAreUsedInTheEditorDescriptions

But if by some force of nature I had to have an abomination like those two things in my code. I would move the difference to the front.

CommentsOfPageReloaderForPagesDisplayingVectorGraphicsThatAreUsedInTheEditor DescriptionsOfPageReloaderForPagesDisplayingVectorGraphicsThatAreUsedInTheEditor

This principle is covered by Kelvin Henney in Seven Ineffective Coding Habits of Many Programmers Of course if you are in a language that has namespaces you should be using them to avoid insanity such as this.

Make everything as simple as possible, but not simpler.

For a specific class in a big project, long names like these are perfectly fine as long as there is no easier way to express it:

PageReloaderForPagesDisplayingVectorGraphicsThatAreUsedInTheEditorComments
PageReloaderForPagesDisplayingVectorGraphicsThatAreUsedInTheEditorDescriptions

Just keep it stupid simple. Keep the name so obvious that everybody understands it.

Do not scarify descriptiveness for a short name!

If there was a maximum length for variable names, the compiler or IDE would not allow these. Nowadays most developers have 16:9 to 32:9 screens and modern computers have enough memory, so it is possible to choose class names that are much longer and more descriptive than the typical int i, VctGfx gf or VctrGfx vgf abbreviations. Short names like that stem from the old days or from physicists, mathematicians or Fortran developers, but this coding style has many disadvantages in the modern programming world. Object oriented programming is more like using a language than using maths. (Learning computer programming uses similar brain activations to learning a foreign language.) So what applies to language should also apply to programming: neologisms need to be defined when used.

When new developers come into a team, it is much easier for them to understand what a class does, when they do not have to debug through the code to learn that Vector is defined as VectorGraphics in that scope. Also if you have to edit the code after a year, you will find it much easier to understand, when you haven't invented new scope specific vocabulary whose definition is more implied than declared.

If the class has a very specific task, you force each developer to read it, which is annoying at first, but it pays out in the long run.

ライセンス: CC-BY-SA帰属
所属していません softwareengineering.stackexchange
scroll top