Cohesion Anti-Patterns
In software development, while striving for high cohesion is crucial, it’s equally important to recognize and avoid anti-patterns that can lead to low cohesion. Anti-patterns are common practices or structures that may seem beneficial at first but usually lead to problems and inefficiencies in the long run. Let’s explore some common cohesion anti-patterns, how they manifest, and their implications.
1. The God Object Anti-Pattern
A “God Object” is a class that knows too much or does too much. This anti-pattern results in a single class having many responsibilities, leading to low cohesion and high coupling with other parts of the system.
public class GodObject { public void readFile() { // Read file operation } public void sendEmail() { // Send email operation } public void generateReport() { // Generate report operation } public void manageDatabase() { // Database operations } public void handleUserInput() { // Handle user input } }
Explanation: The GodObject
class performs a variety of unrelated tasks, from file operations to user input handling. This lack of focus makes the code difficult to maintain and understand.
2. The Blob Anti-Pattern
A “Blob” is similar to a God Object but typically involves a class that accumulates too many data fields and methods without a clear structure or purpose, often due to incremental additions over time.
public class Blob { private String fileName; private int userId; private List<String> data; private Map<String, Integer> statistics; public void loadData() { // Load data } public void saveData() { // Save data } public void processData() { // Process data } public void calculateStatistics() { // Calculate statistics } public void printReport() { // Print report } }
Explanation: The Blob
class accumulates various responsibilities and data fields, making it an incohesive and unwieldy part of the system.
3. The Utility Class Anti-Pattern
Utility classes group a variety of unrelated static methods. While they might seem convenient, they often lack cohesion because the methods do not share a common purpose.
public class UtilityClass { public static void formatDate() { // Date formatting } public static void calculateTax() { // Tax calculation } public static void sendNotification() { // Sending notification } public static void convertCurrency() { // Currency conversion } }
Explanation: The UtilityClass
groups unrelated methods, making it an example of coincidental cohesion where methods are arbitrarily placed together.
4. The Feature Envy Anti-Pattern
Feature Envy occurs when a method in one class is more interested in the details of another class. This often indicates that the method should be moved to the class it is more interested in, improving cohesion.
public class Invoice { private double totalAmount; public double getTotalAmount() { return totalAmount; } } public class ReportGenerator { public String generateReport(Invoice invoice) { // Bad practice: access and use data from Invoice extensively return "Report for invoice amount: " + invoice.getTotalAmount(); } }
Explanation: The ReportGenerator
class relies heavily on the Invoice
class’s data, suggesting that the report generation logic might be better placed within the Invoice
class itself.
5. The Shotgun Surgery Anti-Pattern
Shotgun Surgery occurs when a single change requires modifications across multiple classes. This often results from poor cohesion, where related functionalities are scattered across the system.
public class Customer { public void updateAddress(String newAddress) { // Update address in Customer } } public class Order { public void updateCustomerAddress(String newAddress) { // Update address in Order } } public class Invoice { public void updateCustomerAddress(String newAddress) { // Update address in Invoice } }
Explanation: Updating a customer’s address requires changes in multiple classes (Customer
, Order
, Invoice
), indicating a lack of cohesive design and leading to maintenance challenges.
Conclusion
Recognizing and avoiding cohesion anti-patterns is essential for maintaining clean, manageable, and efficient code. By focusing on creating cohesive modules, developers can ensure that each part of the system has a clear purpose, which simplifies maintenance, enhances reusability, and reduces complexity. Striving for high cohesion and being aware of these anti-patterns can significantly improve the quality and longevity of software systems.
In summary, while it’s important to aim for high cohesion, it’s equally vital to be vigilant against anti-patterns that can undermine this goal. Understanding these anti-patterns helps in designing better software by ensuring that modules are well-defined, focused, and easier to maintain.