Java: Coding Style or Bad Practice?
We all have styles and preferences, including how we write code. Is coding style always harmless? Or does it impact readability and therefore maintenance?
Join the DZone community and get the full member experience.
Join For FreeIntroduction
We all have different styles and preferences in everything in life, including how we write code. Imprinting your personality in the code brings originality and a sense of ownership and responsibility for it. This is important to keep us motivated; it makes us feel good (at least I do).
However, is the coding style always just a harmless style? Or does it impact readability and therefore maintenance?
During a code review, for example, I often find myself questioning whether I should bring certain ways of coding to discussion or not—is it readable and is it easy to maintain? Or perhaps I should leave it alone, thinking to myself—Don’t be picky, it’s just how they code; it’s not a matter of right or wrong.
We could say a developer has a coding identity, or ‘fingerprint.' Similar to what happens with regular writing. For narrative writing, there is often a pattern with which someone writes—the terms, vocabulary, structure—a linguistic expert, for instance, can analyze and identify the author of some anonymous material. It might even tell things such as the age and place of birth of the author. This technique is called stylometry. It’s commonly used in criminal investigations, for example. Machine learning algorithms are used for stylometry as well—it can process many texts/books and identify patterns.
We probably can’t tell who committed a crime based on the coding style (or can we?). But let’s say in a team of ten developers, if there are no strict standards to follow, I believe it’s quite possible to identify who wrote a block of code without looking at the author's information.
In this post, I’ll list down different ways of writing code I’ve encountered and remember throughout my career as a Software Engineer. I’ll focus on Java, but some are applicable in general. I’ll also take a stab and give my perspective on whether it is just a coding preference that we shouldn’t care about, or perhaps there is a right (and wrong) way of doing it.
Curly Braces Vs No Curly Braces
Specifically, when there is only one statement to be executed.
This one pertains more to Java or similar, languages where the curly braces become ‘optional’ when there is only one statement as part of an if condition, for example (also applicable to while and for loops). Here’s an example:
if (condition)
System.out.println(1);
Versus
xxxxxxxxxx
if (condition){
System.out.println(1);
}
Both snippets do the same; there is no difference functionality-wise. Which one do you prefer? For me, I’m totally in favor of using curly braces, always. It shouldn’t be optional.
Mainly because, in languages like Java, the indentation doesn’t drive what it will be executed as part of the if condition or loop (in Python it does, for example). Indentation only, without curly braces, cannot be relied on—it may trick you into thinking that something will be executed (or won’t be executed) when it won’t (or when it will). So not using curly braces may lead to hidden bugs and bad readability in general. In contrast, by using it, it leaves no room for doubt on which line will run or not, it becomes easier to maintain in my view.
Here are some examples to explain better:
xxxxxxxxxx
if (count > 10)
System.out.println(1);
System.out.println(2);
System.out.println(3);
When you read the code above, you think all three lines will be executed if the condition satisfies. But it’s not true. There are no curly braces, hence only 1 will be printed if let’s say, the count is equal to 11. 2 and 3 will be printed in any case, even if for example count is 5.
Another example:
xxxxxxxxxx
int count=15;
if (count > 10)
if (count > 20)
return 1;
else
return 2;
return 3;
The else is aligned with the first if condition, but it’s rather part of the if condition just before. The program returns 2 as the count is less than 20.
In a code review, I would probably ask to change it (very politely and diplomatically of course). The other team member may prefer the code without curly braces and depending on my position, that’s fine—I wouldn’t push it too much. There is not much you can do if the person is not convinced. There is no reason to fight over this (hm, or is there..?)
Default-if-then-otherwise Versus if-then-else-otherwise
Let’s jump right to the example.
xxxxxxxxxx
String value = null;
if(booleanFlag){
value = “A”;
}else{
value = “B”;
}
...use value, insert value in database for example…
versus
xxxxxxxxxx
String value = “B”;
if(booleanFlag){
value = “A”;
}
..use value, insert value in database for example…
I commonly do the second version when it’s a simple variable assignment case, like in the example. I don’t know. It just feels cleaner to me.
A counter-argument could be that the first one uses fewer resources. Because you start with null, only one value (A or B) is assigned at max. While in the other one, a max of two variable assignments could happen (if booleanFlag is true). I’d agree with that, and expound that if not for all cases setting a default first would be fine. It depends on what is being executed as the ‘default.'
This example was actually one ‘challenge’ that my Bachelor course coordinator threw at us newbies, in the first semester during a programming class—“How could you rewrite the first version in fewer lines?”
No one in the class could answer it. Everyone was still coming to terms that the course wasn’t really about learning Microsoft Office. Although I prefer the second version (for a simple variable assignment), in a code review, I’d probably not bring it to discuss or ask to change.
Checked Vs Unchecked Exception
Exceptions are events that happen outside of the normal flow. It allows programmers to clearly separate the code that deals with the success path from the one that deals with errors.
Let's focus on Java. Java has its own Exception classes, or the developer can create its own by extending Exception or RuntimeException. Let’s say there is some particular error validation related to your business. You could create a class, for example, ProductNotFoundException, that extends the Exception class.
Another characteristic of how exceptions in Java work, is that there are two types of exceptions: Checked and Unchecked.
Checked exceptions are exceptions that extend the Exception class. Their behavior is: If a code inside method A throws a checked exception, any method that calls method A, must handle the checked exception by either catching or throwing (or perhaps both). The code will not compile otherwise. Extending a Checked exception is a way to enforce programmers to handle a certain error.
Unchecked exceptions are used for unrecoverable errors. Such errors are not to be handled. Instead, programmers should tackle the root cause that triggers them. Example: NullpointerException. These exceptions extend RuntimeException, and are different from Checked ones; the caller method is not enforced to handle it by catching or throwing it. Despite being used for unrecoverable errors, one could create a custom Unchecked exception. It’s just a matter of extending RuntimeException.
Any method can handle such exceptions, but the compiler doesn’t complain if they don’t. That means that you can have the exception handling code only where is needed.
I learned and used to code by always using Checked exceptions. You probably learned that way too. If you implement a method that calls another method A that generates a checked error, the compiler will tell you that you need to do something about it. And the intent of who created method A was exactly that, to alert and force others to handle the error.
Oracle recommends that you always use a Checked exception if you expect to recover from the error.
Here’s the bottom line guideline: If a client can reasonably be expected to recover from an exception, make it a checked exception. If a client cannot do anything to recover from the exception, make it an unchecked exception.
I admit that despite Oracle’s recommendation and being a good practice to use Checked exceptions, I have sometimes extended RuntimeException. I understand that throwing exceptions should be considered just as essential as the method’s parameters and return value; it’s part of the method programming interface. But for example, no one creates a method that receives a parameter and does nothing with it. I find that throwing it, and re-throwing it upstream without doing any meaningful handling (log, return message to the user) creates a bit of clutter; it’s unnecessary.
With unchecked exceptions, only the method that generates the error and the one that handles it needs to deal with it. It’s a calculated risk I choose to take sometimes. It’s a calculated risk in the sense that an error that is supposed to be handled may not be—another developer that calls your method won’t be alerted by the compiler to handle the exception that your method raises. It’s a drawback from making it Unchecked and that’s why is considered a bad practice in general.
If I see that one of the team members chose to create and use an Unchecked exception, I would probably want to know the thought process behind it and make sure he or she is aware of the pros and cons.
If-then-exception-normal flow Vs if-then-normal flow-else-exception
This one is about validating at the beginning of a method and throwing an exception if the condition does not satisfy, then continuing with normal flow.
xxxxxxxxxx
if (name.length() > 100){
throw new Exception (“Invalid length.”);
}….insert name in database...
Versus
Continuing with the normal flow if the condition satisfies and throwing exception otherwise.
xxxxxxxxxx
If (name.length() <= 100){
….insert name in database...
}else{
throw new Exception (“Invalid length.”);
}
I’ve experimented with both ways throughout my career as a developer. Today I prefer the first version. I see it as clearer and easier to read where errors are generated. And I usually have it aside from the main logic in a private ‘validate’ method.
In a code review, I would probably try to pursue a change if one of my peers is using the second version. Unless the code is as simple as the example in this section, then I’d leave it (maybe).
Multiple 'Returns' Vs a Single One
xxxxxxxxxx
if (condition){
return 1;
}else if (condition) {
return 2;
}
return 3;
Versus
xxxxxxxxxx
int result = 3;
int count = 10;
if (condition){
result=1;
}else if (condition) {
result=2;
}
return result;
I used to prefer just one 'return' in the end, and I still do this way sometimes. But mostly, more recently, I prefer to return right where the condition satisfies. I think it’s easier to maintain (I find it uglier though), you’re more sure of when a certain value is returned by the method, and you know any code after the return won’t be executed.
Otherwise, you need to read every if-else or break inside a loop, for example. Often the logic is not as simple as the one presented above.
If I see some complex logic with multiple if-else conditions chained together, mixed with ‘break’ inside loops, etc., and one single return at the end, when a certain value could’ve been returned before, I’d explain my perspective and see if the person agrees with doing the change. However, I wouldn’t push it too much and be picky about it. It’s a subtle benefit that may be hard to convince.
Curly Braces in the Same Line Versus Line Below
This one is really just cosmetics. It’s silly. It’s like preferring a toast cut diagonally versus horizontally or vertically (You’re probably wondering—How can someone not prefer diagonally?! Anyway…).
It’s about the position of opening curly braces:
xxxxxxxxxx
if (condition) {
.....
Versus
xxxxxxxxxx
if (condition)
{
....
I find it funny that even at things like that people have preferences. I prefer the first one, with curly braces in the same line as if condition or loop. I don’t see any considerable benefit of one or the other. I would definitely not ask another programmer to change it.
Conclusion
Certain coding style choices are really personal, with no benefit or cons over others. It’s like preferring blue to red, orange to apple.
However, some other preferences are more arguable—does it make the code less readable or error-prone? Out of the ones I explained, no use of curly braces and checked versus unchecked exception, stand out to me. They are the ones with the most impact.
It’s very common for companies/teams to have coding standards in place, which eliminates a lot of the difference between developers. I totally agree with defining standards and templates. It helps with readability and hence maintenance.
However, I believe it shouldn’t be too strict. For example, I would set a rule that says always to use curly braces and perhaps to use checked exceptions.* but that’s it. (*Although I see some pros with Unchecked exception, using Checked ones is safer. It can be discussed and agreed upon with the team).
Published at DZone with permission of Vinicius Monteiro. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments