Contenido del Curso
Software Architecture Fundamentals
Software Architecture Fundamentals
Class Design
In the realm of software architecture, low-level design focuses on the detailed implementation aspects of the system. While high-level design provides a broad overview of the architecture, low-level design dives into the specifics, including class definitions, methods, and their interactions.
This chapter will explore how to project classes effectively, using the e-commerce platform as our primary example.
Key Principles of Class Design
In low-level design each class handles a specific part of the business logic, working independently while integrating seamlessly into the larger system.
Below are key principles for effective class design, illustrated through the e-commerce domain.
Single Responsibility Principle (SRP)
A class should have only one reason to change, meaning it should focus on one specific responsibility. For example, in an e-commerce system, the Order
class manages orders, including the items purchased and the status of the order. The Payment
class, on the other hand, handles only the payment process. If the way orders are handled changes, the Payment
class remains unaffected, ensuring separation of concerns.
Open/Closed Principle (OCP)
A class should be open for extension but closed for modification. This means that new functionality can be added to a class without changing its existing code. For instance, if the platform wants to add a new payment gateway, the system can introduce a new class (e.g., StripePayment
) that extends the Payment
interface—without modifying the core Payment
processing code.
Liskov Substitution Principle (LSP)
Subtypes should be substitutable for their base types without altering the behavior of the system. For example, if the platform has a Product
interface, both PhysicalProduct
and DigitalProduct
should be interchangeable in any part of the system that relies on Product
. This ensures that adding new product types does not break existing functionality.
Interface Segregation Principle (ISP)
Interfaces should be small and specific to avoid forcing classes to implement unnecessary methods. In the e-commerce example, instead of one large OrderInterface
covering all possible operations (like cancelOrder()
, shipOrder()
, and returnOrder()
), the system could have smaller interfaces such as Cancelable
, Shippable
, and Returnable
. This ensures that each class only implements what it needs.
Dependency Inversion Principle (DIP)
High-level modules should not depend on low-level modules; both should rely on abstractions. In the e-commerce platform, the OrderService
class should not depend directly on a specific payment provider like Stripe
. Instead, it should depend on a PaymentGatewayInterface
. This allows switching payment providers (e.g., to PayPal) without changing the core logic in OrderService
.
Example
Below is the design of key classes and interfaces for the e-commerce platform using SOLID principles. This table provides an overview of responsibilities, associations, and behaviors for each class or interface.
Single Responsibility Principle (SRP)
Each class or interface focuses on a specific task. For example, the Order
class only manages order-related data, while the PaymentGateway
interface deals solely with payment processing, ensuring that responsibilities are clearly separated.
Open/Closed Principle (OCP)
Adding new functionality—like integrating PayPal—does not require changes to the existing OrderService
class. Instead, a new class (e.g., PayPalPayment
) can implement the PaymentGateway
interface without altering the core code.
Liskov Substitution Principle (LSP)
Both PhysicalProduct
and DigitalProduct
implement the Product
interface, ensuring they can be used interchangeably wherever a Product
is required. This guarantees that adding new product types won't break the existing system.
Interface Segregation Principle (ISP)
The PaymentGateway
interface only defines essential payment methods, ensuring that unrelated classes are not forced to implement unnecessary methods. This keeps each class focused on what it needs to do.
Dependency Inversion Principle (DIP)
High-level components like OrderService
depend on the abstraction provided by the PaymentGateway
interface rather than specific payment providers. This design allows the payment provider to be switched easily (e.g., from Stripe to PayPal) without impacting the core business logic.
Flexibility and Maintainability
- Adding new product types: introducing a new type (like
SubscriptionProduct
) only requires creating a new class that implements theProduct
interface; - Switching payment providers: implementing a new class (e.g.,
PayPalPayment
) allows the system to use a different payment provider without changing core logic.
This structure ensures a scalable and maintainable design, following the principles of modularity and separation of concerns. It allows the platform to evolve over time without introducing unnecessary complexity or coupling between components.
¡Gracias por tus comentarios!