Giới thiệu:
Nguyên tắc S.O.L.I.D được giới thiệu bởi Robert C. Martin, còn được biết đến với biệt danh Uncle Bob, trong bài báo của ông năm 2000 có tiêu đề “Nguyên tắc Thiết kế và Mẫu Thiết kế.” Các khái niệm này sau đó được phát triển bởi Michael Feathers, người đã giới thiệu cho chúng ta thuật ngữ S.O.L.I.D. Và trong 20 năm qua, năm nguyên tắc này đã làm thay đổi cách chúng ta viết phần mềm trong lĩnh vực lập trình hướng đối tượng, thay đổi cách chúng ta viết code.
Uncle Bob cũng là tác giả của các cuốn sách bán chạy Clean Code và Clean Architecture, và là một trong những người tham gia của “Liên minh Agile.” Do đó, không có gì ngạc nhiên khi tất cả các khái niệm về việc viết mã sạch, kiến trúc hướng đối tượng và mẫu thiết kế đều somehow liên quan và bổ trợ lẫn nhau.
Tất cả đều phục vụ một mục tiêu chung:
“Tạo ra mã nguồn dễ hiểu, dễ đọc và dễ kiểm tra mà nhiều nhà phát triển có thể cùng làm việc.”
5 nguyên tắc S.O.L.I.D bao gồm:
- Single Responsibility
- Open and Closed
- Liskov substitution
- Interface segregation
- Dependency inversion
Trong bài viết này, bạn sẽ cố gắng hiểu từng nguyên tắc một với các ví dụ.
1. Nguyên tắc Single responsibility (SRP)
Nguyên tắc SRP chỉ ra rằng một lớp chỉ nên có một lý do để thay đổi, có nghĩa rằng một lớp chỉ nên có một nhiệm vụ duy nhất. Nói cách khác, một lớp nên chỉ có một nhiệm vụ duy nhất và chỉ có một lý do để thay đổi.
Hãy xem xét ví dụ với lớp Invoice:
class Invoice {
let book: Book
let quantity: Int
let discountRate: Int
let taxRate: Float
var total: Float = 0.0
init(book: Book, quantity: Int, discountRate: Int, taxRate: Float) {
self.book = book
self.quantity = quantity
self.discountRate = discountRate
self.taxRate = taxRate
self.total = self.calculateTotal()
}
public func calculateTotal() -> Float {
let price = ((book.price - book.price * discountRate) * quantity)
let priceWithTaxes = Float(price) * (1.0 + taxRate)
return priceWithTaxes
}
public func printInvoice() {
print("\(quantity) x \(book.name) \(book.price)$")
print("Discount Rate: \(discountRate)")
print("Tax Rate: \(taxRate)")
print("Total: \(total)")
}
public func saveToFile(filename: String) {
// Tạo một tệp với tên được cho và ghi hóa đơn vào tệp đó
}
}
Lớp Invoice vi phạm nguyên tắc SRP vì nó xử lý các tính toán, in và lưu vào tệp. Để tuân thủ SRP, chúng ta có thể tạo ra các lớp riêng biệt cho việc in và lưu trữ:
class InvoicePrinter {
let invoice: Invoice
init(invoice: Invoice) {
self.invoice = invoice
}
public func printInvoice() {
// In chi tiết hóa đơn
}
}
class InvoicePersistence {
let invoice: Invoice
public init(invoice: Invoice) {
self.invoice = invoice
}
public func saveToFile(filename: String) {
// Lưu hóa đơn vào tệp
}
}
Bây giờ mỗi lớp sẽ đảm nhiệm 1 nhiệm vụ duy nhất để luôn tuân thủ nguyên tắc Single responsibility
Tham khảo:
https://www.codeproject.com/Articles/703634/SOLID-architecture-principles-using-simple-Csharp
https://scotch.io/bar-talk/s-o-l-i-d-the-first-five-principles-of-object-oriented-design