ibtdi.com's avatar

Code design

I have orderService class contain placeOrder function this function called other services of process order like order validation and Calc fees and create order and update inventory and send customer notification and send invoice my question is this code design apply solid principle ?

For example :

public class OrderService { private OrderValidator validator; private FeeCalculator feeCalculator; private OrderCreator orderCreator; private InventoryUpdater inventoryUpdater; private NotificationSender notificationSender; private InvoiceSender invoiceSender;

public OrderService(OrderValidator validator, FeeCalculator feeCalculator, OrderCreator orderCreator,
                    InventoryUpdater inventoryUpdater, NotificationSender notificationSender, InvoiceSender invoiceSender) {
    this.validator = validator;
    this.feeCalculator = feeCalculator;
    this.orderCreator = orderCreator;
    this.inventoryUpdater = inventoryUpdater;
    this.notificationSender = notificationSender;
    this.invoiceSender = invoiceSender;
}

public void processOrder(Order order) {
    if (validator.validateOrder(order)) {
        BigDecimal fees = feeCalculator.calculateFees(order);
        orderCreator.createOrder(order, fees);
        inventoryUpdater.updateInventory(order);
        notificationSender.sendNotification(order);
        invoiceSender.sendInvoice(order, fees);
    }
}

}

0 likes
1 reply
LaryAI's avatar
Level 58

Your current design is quite good and adheres to several SOLID principles. Let's break down how it aligns with each principle and suggest any improvements if necessary.

Single Responsibility Principle (SRP)

Each class in your design has a single responsibility:

  • OrderValidator is responsible for validating the order.
  • FeeCalculator is responsible for calculating fees.
  • OrderCreator is responsible for creating the order.
  • InventoryUpdater is responsible for updating the inventory.
  • NotificationSender is responsible for sending notifications.
  • InvoiceSender is responsible for sending invoices.

The OrderService class coordinates these services, which is its single responsibility.

Open/Closed Principle (OCP)

Your classes are open for extension but closed for modification. If you need to change the way fees are calculated, you can create a new implementation of FeeCalculator without modifying the existing code.

Liskov Substitution Principle (LSP)

As long as your services (OrderValidator, FeeCalculator, etc.) adhere to their respective interfaces or base classes, you can substitute them with other implementations without affecting the OrderService.

Interface Segregation Principle (ISP)

Each service has a specific interface, which means clients (like OrderService) only need to know about the methods they use. This keeps the interfaces small and focused.

Dependency Inversion Principle (DIP)

Your OrderService depends on abstractions (interfaces or base classes) rather than concrete implementations. This is evident from the constructor injection of the services.

Code Example

Your code already follows these principles well. Here is a slightly refined version to emphasize the use of interfaces:

public interface OrderValidator {
    boolean validateOrder(Order order);
}

public interface FeeCalculator {
    BigDecimal calculateFees(Order order);
}

public interface OrderCreator {
    void createOrder(Order order, BigDecimal fees);
}

public interface InventoryUpdater {
    void updateInventory(Order order);
}

public interface NotificationSender {
    void sendNotification(Order order);
}

public interface InvoiceSender {
    void sendInvoice(Order order, BigDecimal fees);
}

public class OrderService {
    private final OrderValidator validator;
    private final FeeCalculator feeCalculator;
    private final OrderCreator orderCreator;
    private final InventoryUpdater inventoryUpdater;
    private final NotificationSender notificationSender;
    private final InvoiceSender invoiceSender;

    public OrderService(OrderValidator validator, FeeCalculator feeCalculator, OrderCreator orderCreator,
                        InventoryUpdater inventoryUpdater, NotificationSender notificationSender, InvoiceSender invoiceSender) {
        this.validator = validator;
        this.feeCalculator = feeCalculator;
        this.orderCreator = orderCreator;
        this.inventoryUpdater = inventoryUpdater;
        this.notificationSender = notificationSender;
        this.invoiceSender = invoiceSender;
    }

    public void processOrder(Order order) {
        if (validator.validateOrder(order)) {
            BigDecimal fees = feeCalculator.calculateFees(order);
            orderCreator.createOrder(order, fees);
            inventoryUpdater.updateInventory(order);
            notificationSender.sendNotification(order);
            invoiceSender.sendInvoice(order, fees);
        }
    }
}

Conclusion

Your design is well-structured and adheres to the SOLID principles. The use of dependency injection and separation of concerns makes your code maintainable and extensible. Keep up the good work!

Please or to participate in this conversation.