Resources for an Operation
Consider the highlighted lines in the following code snippet:
public static Set findAllBusinessUnits() throws RepositoryException {
Set businessUnits = new HashSet();
try {
FileReader businessUnitFile = null;
BufferedReader bufferedBusinessUnitFile = null;
try {
businessUnitFile = new FileReader(FILE_NAME);
bufferedBusinessUnitFile = new BufferedReader(businessUnitFile);
String businessUnitRecord;
while((businessUnitRecord = bufferedBusinessUnitFile.readLine()) != null) {
BusinessUnit businessUnit = BusinessUnitFactory.createBusinessUnit(businessUnitRecord);
businessUnits.add(businessUnit);
}
} finally {
if(bufferedBusinessUnitFile != null) {
bufferedBusinessUnitFile.close();
}
if(businessUnitFile != null) {
businessUnitFile.close();
}
}
} catch(IOException ioe) {
String message = "IOError. Unable to find Business Unit records";
logger.log(SEVERE, message, ioe);
throw new RepositoryException(message, ioe);
}
logger.log(INFO, "Manager Records returned:" + businessUnits.size());
return businessUnits;
}
The code tries to read business unit records from a CSV file using FileReader and BufferedReader.
Applications repeatedly acquire a resource for an operation and then release it once the operation is complete. Removing this aspect of an application would improve the code readability and lead to a better design since once removed the remaining code does only what it is supposed to do. In this example, the method's objective is to read business unit records. So it doesn't need to worry about acquiring and releasing the necessary resources. Similarly, you also can handle the exceptions differently with AOP. (More on that later.)
Persistence
Traditional OOP uses repository classes to take care of an application's persistence. The following example illustrates this concept:
public class EmployeeRepository {
public static void createEmployee(Employee employee) throws RepositoryException {
// Uses print writer to persist to the csv file.
}
public static String findEmployeeRecordById(String id) throws RepositoryException {
// Uses file reader to retrieve the employee record for the given id.
}
public static Employee findEmployeeById(String id) throws RepositoryException {
// Uses findEmployeeRecordById to fetch the employee record and the Employee
// object is created using the factory class.
}
public static void updateEmployee(Employee employee) {
// Updates the employee record.
}
}
The EmployeeService class uses a repository class to provide services related to employees in the application. In an enterprise application, removing persistence from the domain model improves the design. Modelers and programmers would be able to concentrate on the domain logic and handle persistence separately. You will see how this is achieved using AOP later.
Logging
Removing loggingbe it for debugging or auditingfrom the classes would drastically improve the code readability. Consider the following code snippet:
public Employee createEmployee(String name,
String contactNumber,
BusinessUnit businessUnit,
Manager manager)
throws EmployeeServiceException {
String id = createNewEmployeeId();
Employee employee =
EmployeeFactory.createEmployee(id, name, contactNumber, businessUnit, manager);
try {
EmployeeRepository.createEmployee(employee);
} catch(RepositoryException re) {
String message = "Created employee successfully:" + employee;
logger.log(SEVERE, message);
throw new EmployeeServiceException(message, re);
}
logger.log(INFO, "Created employee successfully:" + employee);
return employee;
}
The above example includes a couple of audit logs, a fatal error, and a success message. The logging aspect can be moved out of the domain model and implemented separately.
Error Handling
The sample application leaves the error handling aspect of the application to you, but this section does discuss the underlying concept using above code. When you call the
createEmployee method in the
EmployeeRepository object, you could get
RepositoryException. In the traditional approach, you handle this error in the same class. Alternatively, the
createEmployee method of the service class can return
null if
RepositoryException is thrown, and other logic in the catch block can be handled outside this class.
Error handling varies case by case. Hence, applying AOP might differ for each of these scenarios.