Translate

Tuesday, September 11, 2018

Mark Your Safe Zone! Utilizing Access Modifiers in Java


Source: https://dzone.com/articles/mark-your-safe-zone-utilizing-access-modifiers

Mark Your Safe Zone! Utilizing Access Modifiers in Java

by Mateusz Winnicki

A vast majority of methods and classes in Java are marked as public. Check out this post on one developer's thoughts on public classes and why it is unwise.

Recently, I was wondering which keyword in Java is the most used by programmers. Is it final, return, class, or maybe something else?
Unluckily, I haven’t found any broader statistic on the Internet or even on GitHub. However, I remained curious, and so, I wrote a simple file crawler and ran it on several big projects found on GitHub. The outcome was horrible.
Three of the most used keywords in projects that I noticed are — in order — public, final, and, lastly, return.
I agree that final and return can be used in almost every method and class in our programs, but I cannot believe that public is so common, let alone the most used method. 
A bell went off in my head — something is wrong. Why is the public access modifier so heavily used? I checked projects one more time only for access modifiers:
  • Public — 80%
  • Private — 17%
  • Protected — 3%
Unfortunately, I couldn’t check the default scope, as it has no keyword, but based on a number of classes in projects, I checked and can tell that the default scope count will be similar to the protected. So, the number is very little — too little!
What does it mean that almost everything is public in our code? Is it bad or is it good? Well, it is definitely not good. It is actually awful and can lead to many cases of abuse.

Why Is Public a Bad Thing?

First, we should consider why this problem occurs. My main guess is modern IDEs. Modern IDEs, like IntelliJ or Eclipse, are creating a new class by default with the visibility set to public. But, should they? Don't we already have a default modifier that is no modifier? I think that the creators of the Java language tried to save our time from writing new classes by making that. If the majority of classes and methods will be set to the default, why do we need to assign a modifier to them? I guess that was the question that they asked when they were creating the Java Language Specification.
Another option is that programmers actually don’t know how or why we should use a default modifier. Unfortunately, this leads to problems that static analyzers have the option to warn on the usage of default/protected modifier, which is really disgusting!
Ok, but why is public so wrong? Why can’t we just make everything public?
Because we should always respect the privacy of our code. For example, we respect the privacy of our friends, colleagues, and we want to keep our lives private. It is as simple as that.
But, something needs to be public, right? Yes, there is a public function in programming called an API. An API has to be public because the parameters of an API have to be public. Everything behind the API, however, has to be made not public. Of course, I am not talking about the API of our whole application. I am talking about the feature.
What is the default modifier in Java? The default modifier is a package-private visibility, which means that nobody outside our package can directly use this field, method, or class with that modifier. This approach is commonly used in the package-by-feature or hexagonal architecture in contrast to dividing code by layers or themes.

What Steps Need to Be Done to Create a New Feature?

We need to:
  • Define the public API of your feature
  • Write tests for your public API
  • Implement public APIs using many, many internal classes and methods (with the default or private modifier)
It makes no difference if we are talking about service-oriented applications or object-oriented applications. We can almost always break it down.
Let's look at an example: you want to expose a feature using the SELECT clause on the SQL database. In a standard way, there will be a public driver that will have direct access to the database, and with it, you can call anything from anywhere. Do you want to drop the database directly from the front-end? No problem. In this way, you will have a public API for the database, which will expose methods with SELECT. There won’t be an easy way to expose the whole database.
Anyone who wants to use your feature will have to access your public API to do so. Are you using database inside? No problem — nobody will be allowed to access it directly and corrupt your state. Are you calling the external system inside your feature? Still no problem; nobody will have access to that.

What Are the Benefits of This Approach?

You have a big control over your code, and as long as your public API will fulfill a contract that long, you can do whatever you want inside. You can easily refactor your behind-API code, you can divide classes, extract additional methods, breaking down responsibilities, and you will not need to think about the outside world.
Your code is easily testable; you wrote tests for your API, and now, you have a big regression suite to avoid problems in the future. Moreover, your tests are a documentation on how to use it. Keep in mind: noone forbids writing tests for your nonpublic classes. It is all right to do it when it is needed. In an example, when you have to test your super complicated algorithm or regex, it can be more complicated for testing it through the API. Just remember to not attach to this class and test. At some point, you need to delete it and forget that you ever wrote it.
As your inside classes are not accessible by the outside world, your whole solution is characterized by high cohesion. All you have to do is stick to a contract and you will be fine.
From a user perspective, all your features will be easily accessible and usable. Nobody will have to check all the codebase to know what is going on. Just look on packages and public APIs.
I don’t know why the majority of classes are public, but I know why it is a bad thing. Remember, once you expose all your classes, it will be difficult to remove them from the system in the future, as everybody can use them directly. Next time, when you are creating a new class, think and consider if it is necessary to make it public.