Naming Things in Code

来源:互联网 发布:dns欺骗攻击 无网络 编辑:程序博客网 时间:2024/05/12 21:56

When I’m designing software, I spend a lot of time thinking about names. For me, thinking about names is inseparable from the process of design. To name something is to define it.

In the beginning was the Word, and the Word was with God, and the Word was God.

The Gospel According to John

One of the ways I know a design has really clicked is when the names feel right. It may take some time for this to happen (I rename things alot when I’m first putting them down in code), but that’s OK. Good design doesn’t happen fast.

Of course, good names alone don’t make a good design, but it’s been my experience that crappy names doprevent one. With that in mind, here’s the guidelines I try to follow when naming things. The examples here are in C++, but work more or less for any language.

Types (Classes, Interfaces, Structs)

The name should be a noun phrase.

Bad:  HappyGood: Happiness

Do not use namespace-like prefixes.

That’s what namespaces are for.

Bad:  SystemOnlineMessageGood: System::Online::Message

Use just enough adjectives to be clear.

Bad:  IAbstractFactoryPatternBaseGood: IFactory

Do not use “Manager” or “Helper” or other null words in a type name.

If you need to add “Manager” of “Helper” to a type name, the type is either poorly named or poorly designed. Likely the latter. Types should manage and help themselves.

Bad:  ConnectionManager      XmlHelperGood: Connection      XmlDocument, XmlNode, etc.

If a class doesn’t represent something easily comprehensible, consider a concrete metaphor.

Bad:  IncomingMessageQueue      CharacterArray      SpatialOrganizerGood: Mailbox      String      Map

If you use a metaphor, use it consistently.

Bad:  Mailbox, DestinationIDGood: Mailbox, Address

Functions (Methods, Procedures)

Be terse.

Bad:  list.GetNumberOfItems();Good: list.Count();

Don’t be too terse.

Bad:  list.Verify();Good: list.ContainsNull();

Avd abbrvtn.

Bad:  list.Srt();Good: list.Sort();

Name functions that do things using verbs.

Bad:  obj.RefCount();Good: list.Clear();      list.Sort();      obj.AddReference();

Name functions that return a boolean (i.e. predicates) like questions.

Bad:  list.Empty();Good: list.IsEmpty();      list.Contains(item);

Name functions that just return a property and don’t change state using nouns.

Bad:  list.GetCount();Good: list.Count();

(In C#, you’d actually use properties for this.)

Don’t make the name redundant with an argument.

Bad:  list.AddItem(item);      handler.ReceiveMessage(msg);Good: list.Add(item);      handler.Receive(msg);

Don’t make the name redundant with the receiver.

Bad:  list.AddToList(item);Good: list.Add(item);

Only describe the return in the name if there are identical functions that return different types.

Bad:  list.GetCountInt();Good: list.GetCount();      message.GetIntValue();      mmessage.GetFloatValue();

Don’t use “And” or “Or” in a function name.

If you’re using a conjunction in the name, the function is likely doing too much. Break it into smaller pieces and name accordingly.

If you want to ensure this is an atomic operation, consider creating a name for that entire operation, or possibly a class that encapsulates it.

Bad:  mail.VerifyAddressAndSendStatus();Good: mail.VerifyAddress();      mail.SendStatus();

Does it Matter?

Yes, I firmly believe it does. A module with well-named parts quickly teaches you what it does. By reading only a fraction of the code, the you’ll quickly build a complete mental model of the whole system. If it calls something a “Mailbox” you’ll expect to see “Mail”, and “Addresses” without having to read the code for them.

Well-named code is easier to talk about with other programmers, helping knowledge of the code to spread. No one wants to try to say “ISrvMgrInstanceDescriptorFactory” forty times in a meeting.

Over on the other side, poor names create an opaque wall of code, forcing you to painstakingly run the program in the your head, observe its behavior and then create your own private nomenclature. “Oh,DoCheck() looks like it’s iterating through the connections to see if they’re all live. I’ll call thatAreConnectionsLive().” Not only is this slow, it’s non-transferrable.

From the code I’ve seen, there’s a strong correspondence between a cohesive set of names in a module, and a cohesive module. When I have trouble naming something, there’s a good chance that what I’m trying to name is poorlydesigned. Maybe it’s trying to do too many things at once, or is missing a critical piece to make it complete.

It’s hard to tell if I’m designing well, but one of the surest guides I’ve found that I’mnot doing it well is when the names don’t come easy. When I design now, I try to pay attention to that. Once I’m happy with the names, I’m usually happy with the design.

原创粉丝点击