DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workkloads.

Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • Architecture Anti-Patterns: The DARK Side of the Architect
  • Testing the Untestable and Other Anti-Patterns
  • Common Performance Management Mistakes
  • Common Performance Management Mistakes

Trending

  • How the Go Runtime Preempts Goroutines for Efficient Concurrency
  • The Modern Data Stack Is Overrated — Here’s What Works
  • Unlocking AI Coding Assistants Part 2: Generating Code
  • A Guide to Developing Large Language Models Part 1: Pretraining

Void Methods Considered Anti-Pattern

If you want to know why you should avoid void methods, this article is just for you. Here you can find all their sins and see how they can impact your system.

By 
Bartłomiej Żyliński user avatar
Bartłomiej Żyliński
DZone Core CORE ·
Jul. 20, 21 · Opinion
Likes (8)
Comment
Save
Tweet
Share
18.4K Views

Join the DZone community and get the full member experience.

Join For Free

Today's topic is quite different from all of my previous topics. Today, I will let myself loose and hopefully trigger a discussion, at least in the comments, regarding the usage of void methods in our code and if we should consider them a code smell. I will cover some basics of void keyword and mention cases when we may see it as beneficial to use methods with this keyword. Then I will provide arguments to show you that, in the end, it may not be such a good idea. 

But first, please keep in mind that this text is written from the perspective of the Java language and some cases may not be applicable in your favorite language.

Void Keyword Purpose

As any other keyword, void has a reason to exists – or it at least seems to. In Java, as in other languages derived from C, it is used to describe methods that are executed normally but do not provide returned value to its caller. 

It is worth mentioning that in Java, alongside void keyword we have Void type which is used to represent the void return type as a class. It has only a private constructor so we cannot instantiate it. Additionally, the only value we can assign to a Void variable is null.

When and Why We May Need Void Methods?

In most cases, we use void methods when we need to perform an operation with some kind of side effects. The most common use case of void methods is System.out.println which prints desired text to standard output. 

Other examples are:

  • Running a job or task, like running your Java app with the main method
  • Performing database query
  • Using bean life-cycle annotation, like @PostConstruct
  • Setters for your object properties are voids by default

Additionally, some libraries or APIs you have to integrate with use void methods and, by extension, you need to use them too. javax.mail library may be a good example here. Its most important method, SendMessage, is void so even if you prefer not to use voids yourself, you still may be forced to do it.

About why we use void methods - as usually, it depends. For example, in case of printing it may be hard to come up with what exactly should be returned. The same holds true for running jobs or tasks but there the matter is more complex. For life-cycle annotations, there is nothing that they can return. They are just simple hooks and that is all, even if we decide to return something from such method it will be omitted anyway.

As you can see void methods seem pretty useful, so now you may be tempted to ask: Why exactly do I believe that we should avoid them if they are so helpful? – and as usual, I am here to help you and provide the answer.

Why Using Void Methods Is a Bad Idea?

Void methods:

  1. Break encapsulation may lead to leaking some unnecessary implementation details of our application. Additionally, it could result in needing more in-depth knowledge of system from anyone interested in contributing to or solving some tasks around app. It may not be a case for a relatively simple code base, but it will for sure show its full “glory” in a larger application. Even so, I am sure that almost everyone of us forgot to call a method like public void doSth(..arguments) and spent an hour or so thinking, “why is my code not working?”.

  2. Do not provide any contract, in terms that we have input and output, we just have input and after input we have magic. We have to guess what exactly is going on inside the method. In my opinion, it is the biggest problem with void methods. You may notice that it is the reason behind all of the other problems described below, at least in some part.

  3. Can limit local reasoning because you lose information about what is actually returned by method. You have to dive into implementation to get knowledge about the expected outcome of method execution. Of course, descriptive naming may reduce the impact of this issue but still, normal methods provide more information, and what is even more important is that such information is more visible for the reader.

  4. Are significantly harder to test. Lack of returned value makes it impossible to perform any kind of assertion-based tests known from libraries like JUnit. To verify if our method works as desired we will have to check the state of object it modifies (simple case) or state of some test database which plays the role of production counterpart (complex case). It can get even worse when we are forced to use methods like .spy() (which itself is worth a similar article), from libraries like Mockito, to verify correctness of particular method inner workings.

  5. Live only thanks to the side effects (another semi anti-pattern especially in functional programming). If you want to avoid or limit them in your codebase you should also stay away from void keyword.

  6. Tends to spread very fast across codebase because it looks like an easier and faster way to implement what we need.

Above you can find some useful tips for preparing a good spaghetti code. Back to being serious, these are my fundamental arguments against using void methods. If you disagree with any of them or have another argument to support my view I invite you to the comment section of this article to have a cultural discussion over the topic.

As we are slowly reaching the end of today’s reading there is one more important question to ask.

Are All Void Methods Bad?

Certainly not, but most of them are. Tasks like printing to console, logging to file or sending mails are good examples of when void methods may be used without causing too many problems. However, in almost any other case they should be avoided and used in as limited fashion as possible, at least in my opinion. 

If limiting the use of voids is impossible you should focus on limiting their impact on overall application. For instance, you can put them as low in your execution order as possible. Therefore, any failure of such method can be better isolated and overall impact on style and inner workings of our codebase will be lessened.

Summary

I will say it one more time just to be clear: in most cases void methods are bad and should be considered anti-pattern, using them may lead to a very tasteful spaghetti code where everything is implicitly stateful.

I have presented my view on using void methods and provide a hopefully clear explanation of why I think so. I hope that my text will raise some questions about your codebase style and quality or at least that next time you will think twice before creating a method like public void doSth(). As usual, thank you for your time.

Anti-pattern

Opinions expressed by DZone contributors are their own.

Related

  • Architecture Anti-Patterns: The DARK Side of the Architect
  • Testing the Untestable and Other Anti-Patterns
  • Common Performance Management Mistakes
  • Common Performance Management Mistakes

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!