Method Naming – What is the problem?
Method names that don’t describe what they are expected to do are confusing. There are methods that are the “Mr. Know-It-All” – they do everything you could imagine: they create, update, save, delete, save again, delete again, and they can also throw an Exception… You must be thinking, “Please stop! I can’t take this anymore!” Yes, these methods are like a nightmare. They are the kind of methods that even the creator doesn’t know what is happening. Developers just invoke the method because it works. But nobody has the guts to change a method like this. If it has a bug, most developers will just code around it.
Also, there are the names of the methods that say one thing and do another.
Imagine this situation, there is a method with this name:
public void find(int id) { // Do tons of actions }
Find what? We must specify what is happening in the method so we can just invoke it by knowing WHAT it does instead of HOW.
Another example:
public void markCheckBox() { // Do tons of actions }
Again, the screen that this method is being executed on may have more than one checkbox. How can we find out which checkbox is associated with which action? We could read through the body of the method, but we don’t want to do this. We want to be able to confidently invoke the method and know what is happening just from reading the method name.
How do we solve this huge problem?
First, you have to understand the concepts of high cohesion and low coupling. Then you have to develop your coding skills until it becomes second nature to write your code with these benefits. What follows is a brief explanation of these two important concepts:
Low Coupling: This is how much a class knows about other classes. If a class knows many things about many other classes, it means that the class is highly coupled. Classes that can stand alone – or almost alone have low coupling. Classes with low coupling are easier to use and extend. Accessing methods from objects of many different classes is an indication of high coupling. Remember: your class can play with its own toys, but it can’t play with the toys of other classes!
High Cohesion: This is how specific your class/method is. If your method is the “Mr. Know-It-All” that does everything you could imagine, it has low cohesion and is code that nobody will understand. If your method does ONE thing, your method has high cohesion. Methods with high cohesion are easier to use, reuse, and understand.
With those concepts in mind, now we can create meaningful method names.
Let’s see the following business requirements:
- Given product information, create a new product in the system
- Add an initial quantity of stock to the product store
- Return the product stock reference to the user
A good way to do this is to use the Facade design pattern. This is basically a pattern that performs multiple required actions that orchestrate and delegates actions from other classes.
It means that we don’t need to know the business requirements so deeply. If we need to create a product we can just invoke the createProduct method.
public Class ProductFacade { //... public StockReference createProduct(ProductDTO productDTO) { Product product = convertDTOtoEntity(productDTO); catalogService.add(product); StockReference stockReference = getProductStorage().addStock(product, productDTO.getInitialAmount()) return stockReference; } //... }
This is a good example of method name implementation. You can easily see that we don’t have a lot of code inside the method.
Keep in mind that your method must have a specific name and it must know how to do only ONE thing very well. Often Facade methods will have a generic operation name and then call more specific methods inside, as the example above demonstrates.
Extra naming tip: sometimes we need to find something by id and name and date and so on.
Instead of creating several methods like this:
public void findByIdAndName(int id, String name) {} public void findByIdAndNameAndDate(int id, String name, Date date) {} public void findByIdAndDate(int id, String name) {}
The methods can be created like this:
public void findBy(int id, String name) {} public void findBy(int id, String name, Date date) {} public void findBy(int id, Date date) {}
It’s much more concise and simpler to understand.
Remember, when naming your method, you must take the same care as you would in choosing your child’s name. Consider that the name you choose for your methods will be used, discussed, and called for years to come.
It’s important to remember that the Camel Case convention has to be always used when coding with Java. It means that the method name must start with a lowercase letter and as the word changes a capital letter is used.
Example:
executeAction();
Variable Naming – What is the problem with bad variable names?
One would think that naming variables should be easy. We do it all the time. Why is it so hard?
Consider the following code:
for (int i = 0; i < 10; ++i) { n += i * CONST; }
This is code that is so easy to write. We do it all the time. Why? It requires almost no thought. If it’s easy to write, we can assume it will be hard to read. Let’s look at some of the obvious problems with this short code snippet.
- That big CONST sticks out. I wonder what that is. Why would we be using it? Is it the right value? How would I know I’ll have to research the code to figure this all out?
- A “for” loop is usually an indication of someone not thinking about the problem. Is there a way we could replace this with a stream expression and make it more readable? And maintainable?
- The loop index goes from 0 to 9. What is special about the number 10? And 0 for that matter? Maybe one or both should also be constants? Now I have to do more research to figure out what these numbers mean.
- Using “i” as the index for a small loop, we can let that slide for now, but “n” is inexcusable. Where is it used? What was its value before we got to this code? How will it be used later? What type is it? Why is it a primitive value hanging here in the middle of the code? Is it local to the method, or global to the whole program? More research!
So in these simple four lines of code that took probably 30 seconds to bang out, I’ve created possibly half a day – or more – of research for the next developer who comes along and has to maintain this. It’s irresponsible and lazy.
So what does GOOD variable naming look like?
First, we look at general Java naming conventions:
- Variable and method names are Camel Case
- Constants are in all caps and words are separated with an underscore: MAX_INT
- Class names are Pascal Case. This is similar to Camel Case, but starts with a capital letter.
For example:
DataBufferDouble
Variable names must be clear to the reader. For the constant used above, “CONST” is meaningless. Is it Planck’s Constant? Pi? Some internally defined interest rate? Instead, use a name like “GROWTH_RATE” or “MAX_SAVINGS”. Giving it a meaningful name saves other developers so much time when they have to read this code later.
At least a constant is being used. Having numbers directly in code is almost never a good idea. Sometimes 0 or 1 can be used without a problem (for example the beginning of a loop counter), but it is usually confusing and can be a source of bugs. Whenever possible, use a constant value instead of a literal number. In the end, use good sense in deciding to use constant values.
Additionally, Instead of “n” in the code above, we could use “accumulator”, “interest” or “totalGrowth“. Any of these would be much easier to understand than “n”. They would also give a sense of the intent of the developer.
Spending a few extra minutes thinking of helpful variable names can save hours of confusion and research for the developers who need to follow you and read your code.
Join the discussion and if there is a specific tool or technique or discipline you would like to learn more about, leave a comment. Contact Rafael at the Java Challengers or Scott at Keep Calm and Refactor.