Why We Use Class in Java?

Java is the most widely used object-oriented programming (OOP) language in the world, and in 2018; Java is number one in TIOBE index*. OOP is a programming model based on the concept of objects which are simply data structures that have fields, or attributes, that hold information (data) about themselves and methods they can perform. From OOP, we getting the the concept of classes and objects.

And why are classes useful? What the purpose of creating a class?

Short answer is, classes help you take all the properties and behaviors of an object in your program, and combine them into a single template.

Yes, a class in Java is simply a template for creating objects with similar attributes and behavior. As a template, the class defines the attributes and behavior that objects constructed from it can exhibit. And as we all know, an object is merely an instance of a class. Learn about Java and OOP in this article.

Now the long answer/explanation:

Let's start with our example; Employee, EmployeeStatus, EmployeeRepository, and EmployeeController (to make it shorter, package name and import is not included)

Employee.java
@Getter
@Setter
@ToString
public class Employee {

    private String name;
    private Date birthDate;
    private Date joinDate;
    private EmployeeStatus status;
}
                    

EmployeeStatus.java
package com.dariawan.spring.domain;

public enum EmployeeStatus {
    PERMANENT, CONTRACT, INTERNS
}
                    

EmployeeRepository.java
@Component
public class EmployeeRepository {
    String url = "jdbc:oracle:thin:@dariawan:1524:humancapital";
    String username = "buttler";
    String password = "coffeebreak";
    String insertSql = "INSERT INTO employee values (?, ?, ?, ?)";
    
    public void save(Employee emp) throws SQLException{
        try (Connection conn = DriverManager.getConnection(url, username, password)) {
            PreparedStatement ps = conn.prepareStatement(insertSql);
            ps.setString(1, emp.getName());
            ps.setDate(2, new java.sql.Date(emp.getBirthDate().getTime()));
            ps.setDate(3, new java.sql.Date(emp.getJoinDate().getTime()));
            ps.setString(4, emp.getStatus().name());
            ps.executeUpdate();
        }
    }
}
                    

EmployeeController.java
@Controller
public class EmployeeController {

    @Autowired
    private EmployeeRepository employeeRepository;

    @RequestMapping(value = "/addEmployee", method = RequestMethod.POST)
    public String submit(@RequestBody Map<String, Object> formMap) throws Exception {
        Employee emp = new Employee();
        
        emp.setName(formMap.get("name").toString());
        
        SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd");
        emp.setBirthDate(fmt.parse(formMap.get("birthdate").toString()));
        emp.setJoinDate(fmt.parse(formMap.get("joindate").toString()));
        
        emp.setStatus(EmployeeStatus.valueOf(formMap.get("status").toString()));
        
        employeeRepository.save(emp);

        return "employeeView";
    }
}
                    

Question: Is the Employee and EmployeeStatus class necessary? Why not done everything in existing class like Map or Array?

To be clear, let me create the implementation using Map:

EmployeeRepository.java
@Component
public class EmployeeRepository {
    String url = "jdbc:oracle:thin:@dariawan:1524:humancapital";
    String username = "buttler";
    String password = "coffeebreak";
    String insertSql = "INSERT INTO employee values (?, ?, ?, ?)";
    
    public void save(Map<String, Object> mapEmp) throws Exception{
        try (Connection conn = DriverManager.getConnection(url, username, password)) {
            PreparedStatement ps = conn.prepareStatement(insertSql);
            int i = 0;
            for (String key : mapEmp.keySet()) {
                i++;
                ps.setObject(i, mapEmp.get(key));
            }
            ps.executeUpdate();
        }
    }
}
                    

EmployeeController.java
@Controller
public class EmployeeController {

    @Autowired
    private EmployeeRepository employeeRepository;

    @RequestMapping(value = "/addEmployeeArray", method = RequestMethod.POST)
    public String submit(@RequestBody Map<String, Object> formMap) throws Exception {
        employeeRepository.saveMap(formMap);
        return "employeeView";
    }
}
                    

Wow, we get significant reduction of lines of codes... I even just need to loop the Map for preparedStatement...

But it's totally wrong, and if you done it (or doing it now)... you need to repent!

At least there are two drawback of this approach:

  1. Source code is difficult to understand
  2. More prone to error

Source Code is Difficult to Understand

If new programmer join your team, and he/she need to change this code, he/she need to:

  1. Understand what possible key/value in the Map for employee
  2. Understand the data type of each possible key/value
  3. Understand ...

You name it... what the possible difficulties this newbie may encounter? Did you know that good code is its own best documentation? From Martin Fowler's Code As Documentation:

One of the common elements of agile methods is that they raise programming to a central role in software development - one much greater than the software engineering community usually does. Part of this is classifying the code as a major, if not the primary documentation of a software system.

...

This principle comes with a important consequence - that it's important that programmers put in the effort to make sure that this code is clear and readable.

The Employeeclass defined above is one of the principles implementation encapsulation in OOP. Class Employee is called as the domain class, which is a class that modelling (represent) the entities that the application deals with. Because class is working as a template, so we get the clear design what are available variable (and methods) for Employee, compared if using Map.

I think part of the reason that code is often so hard to read is because people aren't taking it seriously as documentation.

And what the consequences of source code that is difficult to understand?

  • It's hard to maintain (and enhance)
  • More prone to error (again... back to this point)

More Prone to Error

Using Employee class, we can use different data type for each variable (property):

  • String: name
  • Date: birthDate, joinDate
  • EmployeeStatus: status

But for Map, the value is always Object (without extra validation). By using a specific data type, if an incorrect entry is found, an error occurs when you typing in the source code (Most of IDE will catch this), or during compilation time.

emp.setBirthDate(formMap.get("birthdate").toString());

incompatible types: java.lang.String cannot be converted to java.util.Date

If using Map and you assign incorrect data type, you will get the surprise during runtime.

Another extra is most modern IDE has autocomplete feature to "print" your selected property.

*The TIOBE Programming Community index is an indicator of the popularity of programming languages