Software Design Principles
Software Design Principles
1
MSc. Ngô Ngọc Đăng Khoa
Software Design
Design Principles
Learning Objectives
☕ Understand and apply fundamental design principles
☕ Master SOLID principles
☕ Gain the ability to create flexible and maintainable code
Main Content
1 Coupling & Cohesion
2
MSc. Ngô Ngọc Đăng Khoa
Software Design
WHY
3
MSc. Ngô Ngọc Đăng Khoa
Software Design
4
MSc. Ngô Ngọc Đăng Khoa
Software Design
Cohesion
Cohesion is the degree to which components within a module/class work together to achieve a clear
purpose.
Classification:
☕ High Cohesion (Good): Closely related methods/attributes
☕ Low Cohesion (Bad): Unrelated methods/attributes
5
MSc. Ngô Ngọc Đăng Khoa
Software Design
Low Cohesion
Problem: Employee class does too many things: data management, printing, database, email.
6
MSc. Ngô Ngọc Đăng Khoa
Software Design
High Cohesion
Benefits: Each class has a clear responsibility, easy to test and maintain.
// Class only manages employee data // Separate class for report printing
public class ReportPrinter {
public class Employee { public void printEmployeeReport(Employee emp) { }
private String name, double salary; }
public String getName() { return name; }
// Separate class for database
public double getSalary() { return salary; } public class EmployeeRepository {
public void calculateSalary() { } public void save(Employee emp) { }
} }
// Separate class for email
public class EmailService {
public void sendToEmployee(Employee emp, String message) { }
}
7
MSc. Ngô Ngọc Đăng Khoa
Software Design
Coupling
Classification
☕ Loose Coupling: Fewer dependencies, changing one module has minimal impact on others
☕ Tight Coupling: Strong dependencies, changing one module affects many others
8
MSc. Ngô Ngọc Đăng Khoa
Software Design
9
MSc. Ngô Ngọc Đăng Khoa
Software Design
Tight Coupling
Problem
// OrderProcessor is tightly coupled to MySQLDatabase
public class OrderProcessor {
private MySQLDatabase database; ☕ Cannot switch to PostgreSQL/MongoDB
public OrderProcessor() {
// Hard initialization - TIGHT COUPLING
☕ Hard to test due to dependence on a real
[Link] = new MySQLDatabase(); database
}
10
MSc. Ngô Ngọc Đăng Khoa
Software Design
Loose Coupling
}
public void save(Order order) { /* MySQL implementation */ } ☕ Easy to test with mock/fake database
public class MongoDatabase implements Database {
public void save(Order order) { /* MongoDB implementation */ }
☕ Changes in MySQLDatabase do not affect
}
OrderProcessor
// OrderProcessor depends on an interface
public class OrderProcessor {
private Database database;
// Dependency Injection
public OrderProcessor(Database database) {
[Link] = database;
}
11
MSc. Ngô Ngọc Đăng Khoa
Software Design
Golden Goal
12
MSc. Ngô Ngọc Đăng Khoa
Software Design
SOLID PRINCIPLES
13
MSc. Ngô Ngọc Đăng Khoa
Software Design
Overview
☕ S - Single Responsibility Principle
☕ O - Open/Closed Principle
☕ L - Liskov Substitution Principle
☕ I - Interface Segregation Principle
☕ D - Dependency Inversion Principle
14
MSc. Ngô Ngọc Đăng Khoa
Software Design
Purpose
☕ Make software understandable, flexible, and maintainable
☕ Reduce complexity when making changes
☕ Increase reusability
15
MSc. Ngô Ngọc Đăng Khoa
Software Design
Explanation
☕ Each class performs only one single task
☕ Only one actor (user/stakeholder) can request changes to a class
16
MSc. Ngô Ngọc Đăng Khoa
Software Design
17
MSc. Ngô Ngọc Đăng Khoa
Software Design
18
MSc. Ngô Ngọc Đăng Khoa
Software Design
Advantages of SRP
☕ Easy to understand: Each class has a clear purpose
☕ Easy to test: Test each responsibility separately
☕ Easy to maintain: Changing validation doesn't affect the database
☕ Reusability: EmailService can be used for Order , Product ...
☕ Reduce conflicts: Teams can work in parallel
Check question: How many reasons does this class have to change?"
19
MSc. Ngô Ngọc Đăng Khoa
Software Design
20
MSc. Ngô Ngọc Đăng Khoa
Software Design
Analysis
public class PaymentProcessor {
public void processPayment(String type, double amount) {
if ([Link]("CREDIT_CARD")) {
[Link]("Processing credit card: " + amount);
☕ Each time a new payment method is added,
// Credit card logic PaymentProcessor must be modified
}
else if ([Link]("PAYPAL")) {
[Link]("Processing PayPal: " + amount);
// PayPal logic
☕ All code must be retested -> Risk of
}
// Adding Momo -> must MODIFY this code! breaking old code
else if ([Link]("MOMO")) {
[Link]("Processing Momo: " + amount);
// Momo logic
}
}
}
21
MSc. Ngô Ngọc Đăng Khoa
Software Design
22
MSc. Ngô Ngọc Đăng Khoa
Software Design
Benefits
public class Main {
public static void main(String[] args) {
PaymentProcessor processor = new PaymentProcessor(); ☕ Adding a new payment method -> create a
// Use Credit Card new class
[Link](new CreditCardPayment(), 100.0);
// Use PayPal
[Link](new PayPalPayment(), 200.0);
☕ No modification of tested code
// Use Momo - NO NEED TO MODIFY PaymentProcessor
[Link](new MomoPayment(), 150.0);
☕ No risk of breaking old code
}
} ☕ Easy to maintain and extend
23
MSc. Ngô Ngọc Đăng Khoa
Software Design
Liskov Substitution Principle: Objects of a subclass must be replaceable by objects of the parent
class without altering the correctness of the program.
Explanation
24
MSc. Ngô Ngọc Đăng Khoa
Software Design
25
MSc. Ngô Ngọc Đăng Khoa
Software Design
// Expected: 5 * 4 = 20
// Actual: 4 * 4 = 16 (because Square changes both width and height!)
☕ Cannot replace Rectangle with Square
[Link]([Link]()); // 16 ???
}
}
☕ Violates the contract of Rectangle
26
MSc. Ngô Ngọc Đăng Khoa
Software Design
27
MSc. Ngô Ngọc Đăng Khoa
Software Design
Interface Segregation Principle: Clients should not be forced to depend on interfaces they do not
use
Explanation
☕ Split large interfaces into multiple small, specialized interfaces
☕ Clients only implement what is necessary
☕ Avoid fat interfaces - interfaces with too many methods
🌿 Transform into multiple focused interfaces
28
MSc. Ngô Ngọc Đăng Khoa
Software Design
29
MSc. Ngô Ngọc Đăng Khoa
Software Design
Follow ISP
30
MSc. Ngô Ngọc Đăng Khoa
Software Design
Advantages of ISP
☕ Flexibility: Classes only implement what's needed
☕ Easy to understand: Small interfaces with a clear purpose
☕ Reduce coupling: Changing an interface has minimal impact
☕ Easy to test: Easier to mock/stub
31
MSc. Ngô Ngọc Đăng Khoa
Software Design
Realworld Example
// DAO pattern
public interface ReadableRepository<T> {
T findById(String id);
List<T> findAll();
}
32
MSc. Ngô Ngọc Đăng Khoa
Software Design
Explanation
☕ Depend on interfaces/abstract classes, not on concrete classes
☕ Invert the dependency direction: from high -> low to both -> abstraction
33
MSc. Ngô Ngọc Đăng Khoa
Software Design
// Low-level module
Problem
public class MySQLDatabase {
public void save(String data) {
[Link]("Saving to MySQL: " + data);
☕ UserService direct dependency on
} MySQLDatabase
}
34
MSc. Ngô Ngọc Đăng Khoa
Software Design
35
MSc. Ngô Ngọc Đăng Khoa
Software Design
Benefits
public class Main {
public static void main(String[] args) {
// Inject MySQL ☕ Easy to change implementations
Database mysqlDb = new MySQLDatabase();
UserService userService1 = new UserService(mysqlDb);
[Link]("John Doe"); ☕ Easy to test with mock/stub
// Switch to PostgreSQL - NO CHANGE to UserService
Database postgresDb = new PostgreSQLDatabase(); ☕ Reduced coupling
UserService userService2 = new UserService(postgresDb);
[Link]("Jane Doe");
☕ Increased flexibility
// Test with Mock
Database mockDb = new MockDatabase();
UserService testService = new UserService(mockDb);
[Link]("Test User");
}
}
36
MSc. Ngô Ngọc Đăng Khoa
Software Design
Summary
Principle Meaning Mnemonic
OCP Open for extension, closed for modification Add new, don't touch old
37
MSc. Ngô Ngọc Đăng Khoa
Software Design
38
MSc. Ngô Ngọc Đăng Khoa
Software Design
OTHER PRINCIPLES
39
MSc. Ngô Ngọc Đăng Khoa
Software Design
Every piece of knowledge must have a single, unambiguous, authoritative representation within a
system
Explanation
☕ Each logic segment should appear only once
☕ Avoid copy-pasting code
☕ Reuse via function , class , module
40
MSc. Ngô Ngọc Đăng Khoa
Software Design
41
MSc. Ngô Ngọc Đăng Khoa
Software Design
Problem: Validation logic is duplicated -> Fixed in one place, forgotten in another!
42
MSc. Ngô Ngọc Đăng Khoa
Software Design
Follow DRY
}
}
☕ Fewer bugs
public void createOrder(Order order) {
validateOrder(order); // Reuse
[Link](order);
☕ More concise code
}
43
MSc. Ngô Ngọc Đăng Khoa
Software Design
DRY - Should
☕ Identical business logic
☕ Validation rules
☕ Complex calculations
☕ Database queries
44
MSc. Ngô Ngọc Đăng Khoa
Software Design
DRY - Shouldn't
// These two methods are IDENTICAL but have different business meanings
public double calculateOrderTotal() { return price * quantity; }
public double calculateTax() { return price * quantity; } // Coincidentally identical
45
MSc. Ngô Ngọc Đăng Khoa
Software Design
Simplicity should be a key goal in design, and unnecessary complexity should be avoided
Explanation
☕ The simplest solution is usually the best
☕ Avoid over-engineering
☕ Readable code > Smart code
46
MSc. Ngô Ngọc Đăng Khoa
Software Design
47
MSc. Ngô Ngọc Đăng Khoa
Software Design
☕ Unnecessarily complex
}
48
MSc. Ngô Ngọc Đăng Khoa
Software Design
Benefits
// Simple, easy-to-understand solution
public class NumberChecker {
public boolean isEven(int number) { ☕ Easy to read, easy to understand, even for
return number % 2 == 0; // Simple freshmen
}
49
MSc. Ngô Ngọc Đăng Khoa
Software Design
KISS - HOW
50
MSc. Ngô Ngọc Đăng Khoa
Software Design
KISS - HOW
☕ Giữ function ngắn gọn:
// Mỗi function làm 1 việc, < 20 dòng
51
MSc. Ngô Ngọc Đăng Khoa
Software Design
Explanation
☕ Only implement what is NECESSARY now
☕ Don't code for a potential future use
☕ Avoid over-engineering
52
MSc. Ngô Ngọc Đăng Khoa
Software Design
53
MSc. Ngô Ngọc Đăng Khoa
Software Design
// Requirement: Lưu user vào MySQL public class MySQLUserRepository implements UserRepository {
public void save(User user) { /* Implementation */ }
public interface UserRepository {
void save(User user); // Must implement ALL unnecessary methods!
public void saveToMongoDB(User user) {
throw new UnsupportedOperationException("Not needed yet");
// "Maybe needed in the future" }
void saveToMongoDB(User user); // ... 7 more unused methods
void saveToRedis(User user); }
void saveToElasticsearch(User user);
void export ToJSON(User user);
void exportToXML(User user); ☕ Unnecessarily complex code
void exportToCSV(User user);
☕ Time-consuming to implement
// "Maybe needed for analytics"
void saveUserActivity(User user); ☕ Hard to maintain
void trackUserBehavior(User user);
} ☕ Might never be used
54
MSc. Ngô Ngọc Đăng Khoa
Software Design
}
void save(User user); // Only need MySQL for now
☕ More simple code
public class MySQLUserRepository implements UserRepository {
public void save(User user) {
// MySQL implementation
☕ Faster development
}
} ☕ Easier to maintain
// When MongoDB is ACTUALLY needed -> create new
// public class MongoDBUserRepository implements UserRepository { ... }
☕ Focus on real-world requirements
// When export is ACTUALLY needed -> create new service
// public class UserExportService { ... }
55
MSc. Ngô Ngọc Đăng Khoa
Software Design
56
MSc. Ngô Ngọc Đăng Khoa
Software Design
57
MSc. Ngô Ngọc Đăng Khoa
Software Design
// YAGNI: Only need the sum (no need for average, product, ...)
// KISS: Use a simple for loop (don't use complex Stream)
// DRY: Extract into a reusable method
58
MSc. Ngô Ngọc Đăng Khoa
Software Design
Best Practices
Before implementation After implementation
☕ [ ] Are requirements clear? (YAGNI) ☕ [ ] Is the code understandable? (KISS)
☕ [ ] Is it the simplest solution? (KISS) ☕ [ ] Is it replaceable? (LSP)
☕ [ ] Is abstraction needed? (OCP, DIP) ☕ [ ] Is coupling low? (DIP)
During implementation
☕ [ ] Does each class do one thing? (SRP)
☕ [ ] Is there duplicate logic? (DRY)
☕ [ ] Is the interface too large? (ISP)
59
MSc. Ngô Ngọc Đăng Khoa
Software Design
60
MSc. Ngô Ngọc Đăng Khoa
Software Design
Problem
Scenario: Which principles does this order management system violate? Suggest adjustments?
61
MSc. Ngô Ngọc Đăng Khoa
Software Design
Solution
Refactor according to SOLID
// SRP: Separate responsibilities private PriceCalculator calculator;
public class OrderValidator { ... } private DiscountService discountService;
public class PriceCalculator { ... } private OrderRepository repository;
public class DiscountService { ... } private EmailService emailService;
// Main service
public class OrderService {
private OrderValidator validator;
62
MSc. Ngô Ngọc Đăng Khoa
Software Design
Anti-Patterns
Over-Engineering
Under-Engineering
63
MSc. Ngô Ngọc Đăng Khoa
Software Design
Anti-Patterns (cont)
Premature Abstraction
64
MSc. Ngô Ngọc Đăng Khoa
Software Design
65
MSc. Ngô Ngọc Đăng Khoa
Software Design
Evolution of Design
☕ Good design doesn't come immediately
☕ Refactor frequently
☕ Refactor in small steps
☕ Test before refactoring
66
MSc. Ngô Ngọc Đăng Khoa
Software Design
67
MSc. Ngô Ngọc Đăng Khoa
Software Design
Common Questions
Q: When should SOLID be violated?
A: When compliance makes code unnecessarily complex. Principles are guidelines, not laws.
68
MSc. Ngô Ngọc Đăng Khoa
Software Design
Mindset Shift
Shift from To
☕ "Working code is enough" ☕ "Code must be easy to maintain"
☕ "Write fast, fix later" ☕ "Write it right from the start, refactor
frequently"
☕ "Only I read this code"
☕ "Code for the team and future self"
"Any fool can write code that a computer can understand. Good programmers write code that
humans can understand." - Martin Fowler
69
MSc. Ngô Ngọc Đăng Khoa
Software Design
Q&A
70
MSc. Ngô Ngọc Đăng Khoa