Private methods are at the heart of many debates within the programming community.
There’s much disagreement on when and where one should use private methods and the purpose they serve. Some even go as far as to call private methods a code smell. A sign that you’re doing something wrong in your code.
But is that really the case?
Like most concepts in programming, private methods can lead to poor code when excessively used. But if you learn how to apply them correctly, private methods are not a code smell. They can become crucial for keeping your code clean and maintainable.
This article will explain why private methods are not bad, but they can be a powerful code block.
Why private methods aren’t a code smell
The opponents of private methods use two main arguments to label them as a code smell.
- Private methods are a sign that the class is violating the Single Responsibility Principle (SRP).
- Private methods prevent programmers from properly unit testing the code.
But do these arguments make a strong case against relying on private methods in your code?
No. They are simply a generalization of certain instances where the use of private methods could go wrong. You can create plenty of private methods in your program without falling into these traps if you know what you’re doing.
Private methods against the Single Responsibility Principle
The first argument claims private methods as an SRP violation. It frames private methods as a lazy or unimaginative way of masking responsibilities that should, ideally, belong to another class. Therefore, refactoring them into separate classes gives your code a better design.
This argument has two main flaws.
It assumes refactoring larger classes into smaller ones with the narrowest possible scope of responsibility always leads to a better design. And it unfairly frames private methods as a unique enemy of SRP when, in reality, you can say the same about public methods.
Yes, refactoring larger classes into smaller ones generally leads to better code designs. But you can’t validate every attempt to get rid of private methods with it. Sometimes, too many smaller classes with minimal responsibility scopes needlessly complicate your code.
As long as the class’s scope stays consistent and narrow enough, you can introduce private methods to handle specific tasks without violating the SRP.
But this is not a rule special to private methods. It’s the same procedure you should follow when creating public methods as well.
Private methods against unit testing
The second argument frames private methods as a barrier against properly unit testing the code. But do you really need to unit test private methods to ensure your code is working as expected?
Usually, private methods are used in code as internal helpers that carry out small tasks. They don’t require dedicated unit tests. You can easily test their simple logic through public methods that call them.
The benefits of using private methods in code heavily outweigh any advantage you can gain from making them public just for the sake of unit testing. If you ever find yourself wanting to unit test a private method, then it could actually be a sign that you need to change the code first.
How can using private methods help you write better code?
Private methods are incredibly helpful for writing cleaner and maintainable code.
They allow you to improve the quality of your codebase in the following ways:
- Adhere to the principle of encapsulation.
- Limit the scope of behavior you’re bound to support.
- Have the freedom to change certain internal implementations over time.
- Create new methods to improve code readability.
- Stop re-implementing certain repeated logic in a class.
Encapsulation and code maintainability
Encapsulation is one of the main concepts in object-oriented programming. It advises you to employ information hiding to reduce code complexity and coupling.
Private methods play a major role in any attempt to use encapsulation in code. They help you hide the internal logic you don’t want to expose to outside users.
It allows users to focus only on public methods that execute tasks relevant to them.
From a programmer’s perspective, this prevents users from making unnecessary couplings with methods that handle internal logic. It allows you to change these implementations over time without forcing the users to modify their code.
The use of private methods to handle internal logic also limits the scope of the behavior you promise to support through the code.
By creating a public method, the programmer commits to supporting certain behavior with minimal changes over time. If you carelessly put any behavior that you don’t expect to maintain under this commitment, it can easily damage the trust users have put in you. So, if you aren’t 100% sure whether to expose a certain behavior to outsiders yet, making it private becomes the low-stakes option over using public methods.
Extract method refactoring and code readability
Extract Method refactoring is one of the most straightforward techniques you can use to improve code readability. It helps you split a long method into several smaller ones or separate different logical concerns into individual methods.
During this process, you mostly use private methods to store the extracted code because it is used only inside the class context. And yes, it is ok if the method is private and static.
You can also use the Extract Method refactoring in combination with private methods to remove re-implementations of a certain logic. If you currently execute the same operation inside two methods, put the repeated logic inside a new private method to allow easier reuse.
This process also improves the self-documentation of your code by letting you give descriptive names to logic that handles different tasks.
Is there such a thing as having too many private functions/methods?
As mentioned above, private methods can lead to bad designs if you’re not careful.
If a class has too many private methods and only a few public methods, it could be the first sign that you’re using them in the wrong way. You should investigate your code for any methods that violate SRP at this point.
If you find the class handling more than one well-defined responsibility, move the surplus private methods to classes that suit them. If no class currently covers the scope of these methods, you can create new classes with relevant responsibilities to complete the refactoring.
Private methods that contain logic too complex to need direct unit testing are also a sign of poor design. Sometimes, you can reduce the complexity of such methods through simple refactoring. But if that’s not the case, there could be a missing level of abstraction in your code causing this issue.
For example, assume your code includes a private method that calculates monthly benefits given to an employee in a Salary class. If this method runs calculations too complex to test through the public methods, it can indicate that you need a new abstraction for managing benefits.
In that case, you should create a new Benefit class and move the calculation logic into a public method in it.
Knowing whether your private method does more harm than good to your code is not always easy. But the following four questions can help you get an idea of whether to refactor a method or not.
- Does the method go beyond the responsibility already assigned to the class?
- Is it not enough to unit test the method through public methods?
- Are there any other parts of the codebase that re-implement its code?
- Should outside users get access to the behavior it supports?
If the answer to any of the above questions is yes, you’ll have to either change the method access to public or move it to another class, depending on the context.
Is it a code smell if a private method calls a public one?
When it comes to code smells, there is a general rule of thumb that private methods can call public ones. It may be perfectly fine for a private method to call a public one. For example, if the public method is simply returning data that the private method needs, there is no harm in this.
As long as the public method is not doing anything that could potentially cause problems, it is okay to call it from a private method.
Conclusion
There are a lot of mixed messages about private methods within the programming community. Some people believe in their ability to improve code design, while others believe the opposite.
As you have seen throughout this post, though, private methods are not bad. They can be incredibly advantageous for writing cleaner and highly maintainable code if you learn to avoid certain pitfalls.
Despite the context, refactoring can massively help you to figure out the best ways to benefit from private methods and know when you’re misusing them.