What's In A Name?
In Object Oriented Programming it's considered to be good practice to write methods that only do one major job. One strategy you can use to ensure that your methods follow this practice is to write method names that describe what the method does. "Clean Code" by Robert C. Martin shares the following old but sound advice: "Functions should do one thing. They should do it well. They should do it only."
Sometimes it can be hard to tell whether the method only does one thing; it's at those times that I turn to the name for assistance. Can I write a descriptive name without the use of "and" or "or"? If the answer is no, it's possible that the method has multiple things going on, but a yes answer means I'm safe (or not being descriptive enough in my naming). It's okay if method names are long - Martin states that "A long descriptive name is better than a short enigmatic name." It's also good convention to use similar verbage for actions taken or abstract concepts such as get whenever retrieving a value, set whenever setting a value, or write whenever writing something to a file.
A few examples of good descriptive method names:
Whatever you do, don't make the mistake of using a method name like DoStuff() to get started, then forget to go back and update it! If you can't think of a descriptive name, you just need to do a little more conceptualization first.
Don't be afraid to use multiple words to get your point across because a descriptive name can act as a replacement for a long descriptive comment (and won't require extra documentation updates if the method changes!) It should be clear to future you and any developers who come after you what each method does before they've even inspected it. Once they have gone to the method, it should do everything they would have expected from the name.
Class and variable names won't necessarily be as long, but they are no less important for clarity and readability. These names should be nouns such as Customer() or ShippedPartProduct(), and string partIdCSV or int customerAge. I usually choose to make List and Array names longer so I can better describe whatever set of data it's holding such as partProductsRetrievedFromSalesforce or itemIdsFromThisShipment.
Variable and class names that are unacceptable:
- int x = 42;
- bool trueFalse = false;
- var object = "xyz";
Strategies To Help
I have developed a few strategies that help me with both good naming and ensuring my methods are all short and perform only one major function.
The first strategy seems like a no-brainer, but it took me awhile to actually figure it out:
Don't break out code into new methods until a full portion of code has you satisfied
By holding off on breaking out code until you've completed one or several portions, you allow yourself to essentially finish your thought process before moving on to the next thing. Much like you might refine an article after you've written your first draft, you can get your ideas out there and refine them into more suitably-formed sentences and paragraphs (e.g. methods) before releasing it into the wild. You also open yourself up to seeing the whole picture which means you have the opportunity to see where the most optimal splits can be instead of trying to conceptualize the splits as you're working through how to solve the issue.
Typically I will start with one method and have it named according to what it should do. I'll write all of the supporting code within this method, even though it isn't part of its job, and run my tests and whatnot. Once I'm satisfied with the results, I will look at each portion of the code I've written and break it apart into its bite-sized method portions. These will either be called by the method I wrote them in, or I'll move them out to be called from a position before or after the method I originally wrote the code in. Then I will run through my tests again, just to make sure the changes didn't break anything unexpectedly.
Consider whether you have multiple similar data sources
Are you using a database and another source of data such as Salesforce within your application? I like to indicate source of data in my variables because it's not uncommon that I'll be using an ItemID from our Item table as well as the ItemID from a Salesforce object. These two variables could have very different values, so it's important to keep them straight. A great example from my current code base would be partProductSerialNumbersFromSalesforce and partProductSerialNumbersFromDB. These lists will hold two different sets of potentially the same stored values - I compare them to determine whether a specific part in our database already exists in Salesforce to avoid creating duplicates.
I don't know whether this strategy is a best practice, but I will also occasionally include the actual table or stored procedure name if I am worried about any ambiguity. An example could be an application that updates two similar tables (let's say Shipments and ShipmentLines); these tables both have a UserDef field that must be updated and you want to avoid ambiguity in which one is being updated when. UpdateShipmentTableUserDef() and UpdateShipmentLinesUserDef() seem like perfectly reasonable and clear names for the methods that will update those fields. Obviously this would be overly wordy and unnecessary for most database updates, but I feel it certainly helps in the odd case like the example.
Is your method returning something?
In the case of a method that returns something, I opt toward using names that describe whatever is being returned. If I'm returning a comma separated string of item Ids, I may choose a name like CommaSeparatedPartProductItemIds(); or GetPartAccountIdFromSalesforce() if I'm running a query that returns the id of the Salesforce Account associated with a part. The important part is to indicate to the reader what the expected value being returned should be. If they're expecting an itemId and get back a customer name, they have a good idea where to start looking for that bug.
Recently fellow dev.to writer @somedood released an article describing the details of naming grammar - essentially when you should be using camelCase, PascalCase, or SCREAMING_CASE. Check it out here:
Did I Miss Anything?
Do you have any awesome ways you make sure your names tell the story of your code? Any techniques to ensure good readability for those who may come behind you? I'd love to hear your own favorite naming conventions.
I'd also love to hear the worst names you've ever seen. I'm sure there's some funny ones out there!