Java code and naming conventions

Why having Java code and naming conventions ?

Code and naming conventions are important to programmers for a number of reasons:
– The essential of the lifetime cost of software is its maintenance. We coud said that in general, a line code is read up to a hundred times but written once.
– Hardly any software is maintained for its whole life by the same person.
– Code and naming conventions improve the readability of the software, allowing engineers to understand new code more quickly and thoroughly.
– Naming conventions allows all the team to speak with the same language. So, business and technical concepts are clearly identified: no variant terms, no approximate terms…All the applicative code is meaningful for all the team.

For all these reasons, code should be written in a form shared between developers.
The original document Java Code Conventions, published by Sun in 1997 (last update in 1999) gives some guidelines.
The document, which stands for a very good basis was not updated and improved for a long time. Besides, some parts and conventions may be subject to discussions.
So, it seems to be relevant to use conventions mixing relevant Java Code Conventions by Sun and our own way of seeing them.

Here, I give details about  Code and Naming Convention I use and I propose on the projects where I participate.
It was inspired by Java Code Conventions by Sun , my own experience and some reading or discussions.

I will address the matter on the basis of two important themes :
– Source file organization.
– Naming conventions

 Source file organization

A Java source file (class, interface, enum) consists of several logical sections which should respect a certain formalism.

Class size

As a general rule, class with many lines (more 1000 lines), even with a good organization, may become cumbersome to maintain. So when it’s possible, they should be avoided.
When you are confronted with big class, the solution to reduce it is generally not very complicated.
In some cases, you should move the part of the class in a or some existing classes where it seems to be more relevant.
In other cases, you should divide the class in several classes with each one responsibilities  more thin.

Method size

To be aware of the size of our methods is important too.
When your method performs multiple types of processing and these processings requires many instructions, it may become hard to read, to understand what the method does. So modification may become error-prone.
In this case, you can wonder if you should not refactor each type of processing in a dedicated method with a meaningful name.

Access level modifiers  (visibility)

Access level modifiers determine whether other classes can use a particular field or invoke a particular method. There are two levels of access control:

  • At the top level—public, or package-level(no explicit modifier).
  • At the member level—public, private, protected, or package-private(no explicit modifier).

A class may be declared with the modifier public, in which case that class is visible to all classes everywhere. If a class has no modifier ( also known as package-level), it is visible only within its own package.

At the member level, you can also use the public modifier or no modifier (package-private) just as with top-level classes, and with the same meaning. For members, there are two additional access modifiers: private and protected. The private modifier specifies that the member can only be accessed in its own class. The protected modifier specifies that the member can only be accessed within its own package (as with package-private) and, in addition, by a subclass of its class in another package.

The following table from https://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html shows the access to members permitted by each modifier.

Access Levels
Modifier Class Package Subclass World
public Y Y Y Y
protected Y Y Y N
no modifier Y Y N N
private Y N N N

 

The first data column indicates whether the class itself has access to the member defined by the access level. As you can see, a class always has access to its own members. The second column indicates whether classes in the same package as the class (regardless of their parentage) have access to the member. The third column indicates whether subclasses of the class declared outside this package have access to the member. The fourth column indicates whether all classes have access to the member.

Source: Oracle Java Documentation.

Top element Javadoc

Classes, Interfaces and Enums should begin with a Javadoc explaining briefly their role and their specificities if they have.

For example for a JPA entity class:

/**
* JPA entity representing an employee

**/
public class Employee {

}

For example for an interface:

/**

* Service contract to do creations, updates and searches on Employees.
It should be stateless
**/
public interface EmployeeService {

}
For example for an enum:
/**

* Enumeration of sex types
**/

public enum SexType {

}
The @author Javadoc is not really useful. Java code is generally shared between developers and code appropriation is not a good practice.
Often, some developed the essential of the class whereas others only added minor changes and don’t master the class. Having the two author names is misleading.
Besides, revision control systems (CVS, SVN, GIT, etc…) allow to retrieve all changes done by users on the source code.
To know the current referrer developers for a Java application or component, it seems more relevant to have an updated general document on the project organization or a project wiki with that information.

 

Class organization

Ordering classes in a shared way allows to spare much time when you have to read, understand and modify them.

Important
The package-level modifiers should be used only if you have a good reason to use it.
Generally, public, private and protected are enough.

Use cases where package-level could be tolerated :

– you have a technical constraint which forces you to use it. For example, if you use the GWT framework, the package-level modifier is needed for declaring UI fields in the Java side if you use UiBinder.

– you develop a library for other applications or services and you want to hide internal classes and processing  to your clients.

–  you want to unit test some methods which should be private. Nevertheless, that trick should be avoided by structuring the code in a more testable way.

Important :
When you are not sure of the order to use for fields, instances and methods,  remember that for a same class level (static or not) and a same Java meta object (field, instance and method) an acceptable order is ordering by more visible to less visible : public, protected, package-level, private. We could call it the classic order.

Java classes should have the logical sections in the following order:

  • static fields
    they should appear in the classic order : public, protected, package-level, private.
    Important : protected static fields should be avoided because it creates ambiguity.
  • static initialization blocks
  • static methods
    they should appear in the classic order : public, protected, package-level, private.
    Important : protected static methods should be avoided because it creates ambiguity.
  • instance initialization blocks
  • instance fields
    they should appear in the classic order : public, protected, package-level, private.
    Important : generally, public instance fields should be avoided because it violates encapsulation principles.
  • constructors
    They should appear in the classic order : public, protected, package-level, private.
  • instance methods
    Broadly, they are two ways of doing :
    1.keeping the classic order : public, protected, package-level, private
    2.organizing methods by matter and responsibility.
    Using the one or the other way is a good thing.
    Consistency is also important. If you use a way for a class, you should  try to use it for the most of classes of your project. Exceptions are possible but it should stay exceptions.
  • inner classes
    Broadly, they are three ways of doing :
    1. put it at the top of the outer class
    2.put it at the bottom of the outer class
    3. put it close to where it is used


Important
When you mix several types of modifier, you should respect this conventional order :

Access Levels (public, protected, private, package)
abstract
static
final
transient
volatile
synchronized
native
strictfp

Naming conventions

All what you declare in Java bears a name and in Java we declare many things: packages, interfaces, abstract classes, classes, instances of the class, methods, variables, etc…
Using names with meaning and commonly shared in the software development world and in your team is essential to avoid building a code base with ambiguities and error-prone terms.
With meaningful naming, most of developers are able to understand right now any chunk of source code in general terms. It saves a precious time for the team.

 

Package Naming

  • Don’t use uppercase in package

From the Oracle Documentation: package names are written in all lower case to avoid conflict with the names of classes or interfaces.

  • Use the same prefix base package for all classes of your application

All Java source code for all Java components participating to the build of your application must be indirect children of this package. The indirect notion is important because all classes must be associated to a kind of category in order to give more meaningfulness to it. For example, in the JDK class, the List class or the System classes are not directly in the java package.
They are in the java.lang package. And in the JDK Javadoc, we can read that Package java.lang Provides classes that are fundamental to the design of the Java programming language.

  • If you use Maven, it may be a good thing if the Java prefix base package name could match with the groupId Maven

For example, if your package base is davidhxxx.agendasoft, you could use the Maven groupId : davidhxxx.agendasoft for you Maven project.
It creates a bridge between the two worlds and therefore, it homogenize reads and searches in your Java packages and in your Maven repositories.

  • Avoid package name too long

A package name must be short. It must convey a general concept. In this way, it improves the type search and the readability in the Java Code explorer of your IDE .

  • Avoid package with too many levels

It also improves the type search and the readability in the Java Code explorer of your IDE.
Besides, from a some level of package, the meaning may become clumsy and ambiguous.
In most of the cases, after the prefix base package, you should try to limit to three additional levels.
In some application, you may have 4 or a 5 additional levels but it should stay the exception, not the rule.

For example, if my base package is davidhxxx.agendasoft, so the package davidhxxx.agendasoft.commun.controller.converter.person has many levels.
We should wonder if we could reduce it. For example, if in the davidhxxx.agendasoft.commun  package, converters are only for controllers, we don’t need to precise it in the package, so we could remove the controller subpackage. So, we would a package like that : davidhxxx.agendasoft.commun.converter.person.

 

Variable Naming

Camel case is recommended with a lowercase first letter.
Variable names should not start with underscore _ or dollar sign $ characters, even though both are allowed.

  • Don’t use black-box names for variables:

a, x, x1, myVar, etc… These are encrypted names….

  • Avoid too generic names for variables

var, temp, old, prev, next, actual, test, etc…
Nothing prevents you from using generic terms such as test, temp, old, prev, next, actual as a prefix or a suffix for a variable. But you should not use it alone. You should give a precise context to it. For example, tempPerson or prevPerson are acceptable variable names.

Type Naming (class, interface, enum)

Camel case is recommended with an uppercase first letter.
Types should be nouns (ex: Address, UserService, ClientType) and not verbs.

  • Avoid too generic names for types

A name is considered as too generic according to the context. Which is true in an application is not necessarily true in another one.
For example, in a very small application with few services and layers, PersonService could be a meaningful name while in a more featured application, it could not be the case. Indeed, if there are multiples classes of services related to Persons, PersonService would be too generic.  So, you should use a prefix or a suffix to distinguish them in an easy, natural and common shared way.
We could have for example PersonDAO for services accessing to the Database and  PersonBS for business services applying on the Person objects etc..

  • Avoid too long names for types if possible

Type names must be explicit, easy to remember and as short as possible. The shortness of type names is important for multiples reasons. Indeed, having too long type names can:

– make the code harder to read because lines are longer and you must read more things

– make the code harder to write because recalling the correct type become harder

– make less effective the Java types searches with your IDE

Sometimes, it is easy and natural enough to find a name both relevant  and short.
Other times, it is more complicated.  But anyway, before using a relatively long name, it is a good practice to think about it and to check if you cannot find a shorter equally relevant name.
For example, imagine that you need to create a class representing an address . If your application handles only addresses for your clients and that a client is related to only a type of address, there is no interest to specify it in the name. The ClientAddress class name would be longer and not more relevant than Address because in your application a address is always associated to a Client. So Address would be a better class name.
Using ClientAddress as class name brings previously quoted drawbacks but besides, it may give the impression than there is several types of address (for example, ClientAddress, CompanyAddress, ProviderAdress, etc…) while it is not the case.

  • Use short prefix as marker for common type

We could take over the example of Person services.
We have chosen PersonDAO as name for our service class making queries related to the persons in the Database. It is short and relevant name.
We could have chosen a more explicit name such as PersonDataBaseService but it would be a bad idea because the suffix DataBaseService  is a verbose naming convention.
Suppose that PersonDataBaseService is an interface, the implementation of it could be PersonDataBaseServiceImpl . It is too long.
PersonDAOImpl is better because while being shorter, it conveys as much as information as PersonDataBaseServiceImpl.

Method Naming

Camel case is recommended with a lowercase first letter.
Methods should be verbs (ex: findAddress, saveUser, listAllTypes) and not nouns.

  • The name must convey what the method does

Contrary to the type or variable naming, you must not be afraid to have a method with a long name if it allows to understand broadly what the method does.
For example, suppose we have a method which saves in DB a person and his address. Naming it  savePerson(Person person)  is not relevant not because it hides the address persistence. savePersonAndAddress(Person person)  would be better.
But the verbosity of the methods naming has also its limits. The naming should be chosen in such a manner that it is as durable and readable as possible but also maintainable and not error prone.
To illustrate this point, now suppose we update our savePerson(Person person) method to save in database a person, his address but also other related information : person’s contract and person’s category. In this case, it would not a good idea to enumerate all sub-entities saved. For example, savePersonAndAdressAndContractAndCategory(Person person)  would not be a nice name because it makes the method name not durable, not readable, error prone and hard to maintain.
It’s hard to maintain because when the body of the method  is modified, the method name may not to be true any longer if you add or remove an entity in the saving operation.  If you forget to update correctly the method name, the method name doesn’t express any longer what the method does, therefore it is error-prone.
In this case, to avoid this kind of problem, it is better to generalize what the method does. savePersonAndSomeRelatedData(Person person) would be a good candidate. In the Javadoc, we may detail saved entities but actually, we should avoid it too because by doing it, we could have the same problem if this Javadoc is not updated.

 

Enum Naming

Uppercase and  an underscore character for separating words is recommended.
Enums should be nouns.

 

Constant Naming

There are multiple ways to define constants. This question will be addressed later.
But whatever the way you use, as for enums, uppercase and  an underscore character for separating words is recommended.

Ce contenu a été publié dans Non classé. Vous pouvez le mettre en favoris avec ce permalien.

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *