Last Wednesday, September 26th, the Wellington .NET User group got together for a roundtable discussion on day to day programming. Based on notes taken that night, here’s a summary of one of our discussions.
Giving methods accurate and useful names is hard, but very important.
Misleading method names will cause significant problems for later maintenance - which could well be the same developer
- so it becomes vital that the method names are good.
The names of other things - classes, interfaces, namespaces, databases, tables, columns, stored procedures, indexes, constraints, local and member variables - are also important.
The age old convention of verb noun naming is still good advice:
-
CalculateInvoiceTotal()
-
SendNotificationEmail()
But we need to exercise caution, because here are exceptions where this naming style is less useful - see below.
Consistency is useful - stick with the verbs and nouns already common in the current or other systems. Here are some suggestions.
-
Get (find one specific item) or Find (find all matching items) instead of Retrieve or Obtain.
-
Send (synchronous) or Post (asynchronous) instead of Transmit
There are some verbs so generic that they should be avoided:
-
Process
-
Manage
The exception is when the host object is itself a “Processor” or “Manager” - though this can be a code smell that the Single Responsibility Principle is being violated.
Exception #1: API Design
In the LINQ framework, they used method names designed to make the end code more readable. For example:
-
Where() not FilterItems()
-
OrderBy() not OrderItems()
-
Select() not ApplyTransformation()
Lesson: When you’re designing an API for other developers to call - or even just as an abstraction between components - optimizing for readability can be useful.
Exception #2: Object Context
Sometimes the host object of our method provides the context, removing the need for the noun.
-
printCommand.Execute()
-
mediaTrack.Play()
-
Double.TryParse()
Exception #3: Missing Operators
If the method is acting like an operator, it can be Ok to name it like an operator, even though the name by itself might not be very meaningful.
For example, this code will blow up if any of the associations are null:
By writing appropriate helper methods, we can simulate null-tolerant operators and instead write this:
This is a special case of Exception #2.
Abbreviations, Acronyms, Contractions and Initialisms
Generally, these should be considered evil - unless the term is so common that almost everyone will understand it at a glance.
Good examples:
-
Id (Identifier)
-
Xml (eXtensible Markup Language)
-
Gst (Goods and Services Tax)
Evil Examples
-
Otsd (Output Time Series Definition)
-
FMX (Foreign Markets eXchange)
The Stephen Test
How to tell if you should use an abbreviation in your code, a three part test.
-
Show five other developers the full term and ask them what abbreviation they would use. If four or more say the same thing, you pass this test.
-
Show five different other developers the proposed abbreviation and ask them what it stands for. If four or more say your original term, you pass this test.
-
Show Stephen and ask him what he thinks. If he agrees, you pass this test. :-)
General advice - abbreviations should only be used if they are truly ubiquitous throughout the business.
While it used to be the case that there were performance benefits to be reaped by using short names, this is no longer true.
There are no meaningful performance gains to be found - at compile time or design time - by making identifiers shorter than necessary.
Predicates and Tests
Having negative terms in the name can make the code difficult to read, usually better to use a single term.
-
Instead of IsNotClean() use IsDirty() or !IsClean()
-
Instead of DoesNotHaveName() use !HasName()
Sometimes it’s easy to miss the ! operator.
Because of this, some like to have a pair of predicates to use for testing:
-
IsClean and IsDirty
-
IsActive and IsComplete
Though others thought this a dangerous approach because future maintenance might result in the two falling out of sync, with predictably subtle and weird results.
Instead of using ! to invert a test, some like to compare with false:
- if (IsClean == false)
though others thought this cure was worse than the original problem, particularly because tools like Resharper will nag you to change it.
Storing the result of a complex test in a boolean variable before using it in an if statement can make code easier to read and debug.
Boolean variables used this way - and test methods or properties returning bool - should start with Is or Has.
-
IsComplete()
-
HasOutstandingInvoices()
-
IsActive
-
HasCookies
References
Brad Abrams and Krzysztof Cwalina’s book Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries is recommended for all serious .NET developers.
Comments
blog comments powered by Disqus