-
Design Pattern
- Singleton Design Pattern
- Factory Design Pattern
- Factory Method Design Pattern
- Abstract Factory Design Pattern
- Builder Design Pattern
- Prototype Design Pattern
- Object Pool Design Pattern
- Chain of Responsibility Design Pattern
- Command Design Pattern
- Interpreter Design Pattern
- Iterator Design Pattern
- Mediator Design Pattern
- Memento Design Pattern
- Observer Design Pattern
- Observer Design Pattern - Xử Lý Exception
- Strategy Design Pattern
- Template Method Design Pattern
- Visitor Design Pattern
- Null Object Design Pattern
- Adapter Design Pattern
- Bridge Design Pattern
- Composite Design Pattern
- Decorator Design Pattern
- Flyweight Design Pattern
- Proxy Design Pattern
- S.O.L.I.D
- Clean code
- Lập trình socket
- Java Core
- Multi-Thread
- Spring
- Java Web
- Memory Caching
- Message Queue
- DevOps
- Xây dựng một nền tảng
- MongoDB
- MySQL timestamp
- Properties vs yaml
- Kotlin
- Lập Trình Machine Learning với PyTorch
- Mã Nguồn Mở
- Ezy HTTP
- Free Chat
- Một số kinh nghiệm với Git
- Review cho đồng nghiệp!
- Kinh nghiệm phát triển dự án phức tạp, nhiều người - Tuân thủ
- Kinh nghiệm phát triển dự án phức tạp, nhiều người - Lựa chọn người đi cùng
- Ngành công nghiệp phần mềm tại Việt Nam - Mới chỉ là bắt đầu.
- Ngành công nghiệp phần mềm tại Việt Nam - Dây chuyền sản xuất.
- Ngành công nghiệp phần mềm tại Việt Nam - Thị trường
- Ngành công nghiệp phần mềm tại Việt Nam - Công ăn việc làm
- Setup Dev Environment
- Hello World
- Create a Server Project
- Handle Client Requests
- Using ezyfox-server-csharp-client
- Using ezyfox-es6-client
- Client React.js Interaction
- Build And Deploy In Local
- Tham gia phát triển open source!
- Buôn có bạn, bán có phường
- Đam mê đi đâu rồi?
- Giữa lửa đam mê!
- Tương lai nào cho tester? Thay đổi để dẫn đầu xu thế!
- Tương lai nào cho tester? - Khi thế sự đổi thay!
- Tương lai nào cho lập trình viên? Khi không có hệ quy chiếu!
- Tương lai nào cho lập trình viên - Làm đến bao nhiêu tuổi?
- Tương lai nào cho lập trình viên? Có làm giàu được không?
- Tương lai nào cho lập trình viên? Có cân bằng cuộc sống được không?
- Tương lai nào cho lập trình viên - Nhảy việc đến khi nào?
- Tương lai nào cho lập trình viên - Con đường sự nghiệp (Career path)!
- Tương lai nào cho lập trình viên - Tổng kết lại!
- Con đường sự nghiệp cho lập trình viên - Giai đoạn sơ cấp (Junior)!
- Con đường sự nghiệp cho lập trình viên - Giai đoạn trung cấp (Intermediate)!
- Con đường sự nghiệp cho lập trình viên - Giai đoạn lành nghề (Senior)!
- Giai đoạn lành nghề (Senior) - Giữa những hoang mang!
- Giai đoạn lành nghề (Senior) - Phân hoá trong doanh nghiệp!
- Con đường sự nghiệp cho lập trình viên - Trở thành chuyên gia (Expert)!
- Con đường sự nghiệp cho lập trình viên - Trở thành người ảnh hưởng (Influencer)!
- Các giai đoạn phát triển của lập trình viên - Tổng kết lại!
- Metaverse - Câu chuyện 10 nghìn CCU (Người tham gia đồng thời)
- Metaverse có khả thi ở Việt Nam?
- Lựa chọn nghề nghiệp - DevOps!
- Lựa chọn nghề nghiệp - Project Manager (PM)!
- Lựa chọn nghề nghiệp - Data Engineer!
- Lựa chọn nghề nghiệp - BackEnd Engineer!
- “Talk is cheap. Show me the code” ― Linus Torvalds
- Lựa chọn nghề nghiệp - Web Front-End Engineer!
- Lựa chọn nghề nghiệp - Mobile Engineer!
- Lựa chọn nghề nghiệp - Game Engineer!
- Lựa chọn nghề nghiệp - Product Owner!
- Tuổi trẻ cần đột phá!
- Tuổi trẻ cần sự đồng cảm!
- Tuổi trẻ - điều đáng sợ đầu tiên là gì?
- Tuổi trẻ - Điều đáng sợ thứ 2 là gì?
- Tuổi trẻ - Điều đáng sợ thứ 3 là gì?
- Tuổi trẻ - Điều đáng sợ thứ 4 là gì?
- Nếu tận dụng hết năng lực thì sẽ thế nào?
- Tuổi trẻ - Điều đáng sợ thứ 5 là gì?
- Tuổi trẻ - Điều đáng sợ thứ 6 là gì?
- Tuổi trẻ - Điều đáng sợ thứ 7 là gì?
- Tuổi trẻ - ham học hỏi là như thế nào?
- Đầu tư cho bản thân là gì?
- Học chủ động!
- Có nên quay lại công ty cũ?
- Làm cho startup (công ty nhỏ) hay làm cho công ty lớn? (Phần 1)
- Làm cho startup (công ty nhỏ) hay làm cho công ty lớn? (Phần 2)
- Làm cho startup (công ty nhỏ) hay làm cho công ty lớn? (Phần 3)
- Tự học
- Học tập tại doanh nghiệp
- Học tại trung tâm
- Cách đọc sách kỹ thuật hiệu quả
- Học trong một tổ chức mã nguồn mở.
- Câu chuyện lập trình viên - Công việc đầu tiên
- Câu chuyện lập trình viên - Mức lương đầu tiên
- Câu chuyện lập trình viên - 2018
- Định hướng là gì?
- Wordpress nguy hiểm thế nào?
- Danh sách 10 trung tâm đào tạo trình uy tín, chất lượng ở Hà Nội
Đóng thay đổi, mở tương lai!
Nếu hỏi đâu là nguyên tắc quan trọng nhất trong lập trình phần mềm (SOLID) thì OpenClose chính là nguyên tắc quan trọng nhất. Nguyên tắc này nhắc nhở chúng ta rằng hãy hạn chế tối việc thay đổi những thứ đang chạy ổn định và nếu phải cập nhật thì hãy tìm cách mở rộng thay vì thay đổi source code. Hệ thống có mở rộng được hay không, giảm thiểu chi phí nâng cấp hệ thống được bao nhiêu và trình độ của lập trình viên cao hay thấp chính là ở kỹ năng để đáp ứng nguyên tắc này.
Vấn đề trong thực tế
Với con mắt của người tạo ra những dòng code thì nó là đẹp, gọn gàng, nhưng khi đưa chính source code đó cho những người khác thì nó lại trở thành một mớ hỗn độn, hãy tưởng tượng bạn có 1 tính năng cập nhật mật khẩu, và hiện tại code là thế này:
public class AuthenService {
public void refreshToken(String username) {}
public void logout(String username) {}
public void updatePassword(String username, String password) {
if(password.length < 6) {
throw new InvalidPasswordException("password's too short");
}
if(password.length > 36) {
throw new InvalidPasswordException("password's too long");
}
User user = userService.getUserByName(username);
user.setPassword(password);
userService.saveUser(user);
}
}
Nhìn code vẫn rất gọn gàng đúng không mọi người? Thế nhưng đột nhiên chúng ta nhận được yêu cầu là: mật khẩu phải không được trùng với 3 mật khẩu đã đổi trước đó và lúc này chúng ta sẽ cần cập nhật code:
public class AuthenService {
public void refreshToken(String username) {}
public void logout(String username) {}
public void updatePassword(String username, String password) {
if(password.length < 6) {
throw new InvalidPasswordException("password's too short");
}
if(password.length > 36) {
throw new InvalidPasswordException("password's too long");
}
Set<UpdatePasswordHistory> updatePasswordHistories =
updatePasswordHistoryRepository.findPasswordUpdateHistories(username, 3);
Set<String> updatedPasswords = updatePasswordHistories.stream()
.map(it -> it.getPassword())
.collect(Collectors.toSet())
if(updatedPasswords.contains(password)) {
throw new InvalidPasswordException("new password can not be same last 3 updated passwords");
}
User user = userService.getUserByName(username);
user.setPassword(password);
userService.saveUser(user);
}
}
Việc update code thế này đã làm thay đổi hàm updatePassword trong lớp AuthenService và nó dẫn đến hệ lụy là chúng ta sẽ phải đi test lại toàn bộ các tính năng có trong lớp AuthenService để chắc chắn rằng sẽ không có sự nhầm lẫn nào và không có lỗi xảy ra. Thêm nữa là lớp AuthenService ngày càng dài ra và càng ngày càng rối. Một câu chuyện có thật là bọn mình đã từng phải maintain 1 lớp UpdateUserAction, lớp này đã lên đến hàng nghìn dòng, cứ mỗi lần nhận được task update nghiệp vụ cho lớp này là tất cả anh em đều đẩy đưa nhau, chẳng ai muốn làm vì sợ lỗi, và sự thực là lỗi đã xảy ra làm block toàn bộ luồng update user, thật may nó mới chỉ diễn ra trên bản Beta.
Giải quyết vấn đề
Vậy để đóng việc thay đổi lớp AuthenService và dễ mở rộng về sau này thì làm thế nào? Đơn giản thôi, hãy sử dụng Composite designpattern và ChainOfResponsibility design pattern để tách việc kiểm tra password ra chỗ khác, nó như này:
public class PasswordValidator {
private final List<Validator> validators;
public PasswordValidator() {
this.validators = Arrays.asList(
new PasswordLengthValidator(),
new PasswordHistoryValidator()
);
}
public void validatePassword(String username, String password) {
validators.forEach(it -> it.validate(username, password));
}
private class PasswordHistoryValidator implements Validator {
public void validate() {
Set<UpdatePasswordHistory> updatePasswordHistories =
updatePasswordHistoryRepository.findPasswordUpdateHistories(username, 3);
Set<String> updatedPasswords = updatePasswordHistories.stream()
.map(it -> it.getPassword())
.collect(Collectors.toSet())
if(updatedPasswords.contains(password)) {
throw new InvalidPasswordException("new password can not be same last 3 updated passwords");
}
}
}
private class PasswordLengthValidator implements Validator {
public void validate() {
if(password.length < 6) {
throw new InvalidPasswordException("password's too short");
}
if(password.length > 36) {
throw new InvalidPasswordException("password's too long");
}
}
}
private interface Validator {
void validate(String username, String password);
}
}
Và lớp AuthenService sẽ không cần phải thay đổi nếu như có thêm những nghiệp vụ về password nữa.
public class AuthenService {
public void refreshToken(String username) {}
public void logout(String username) {}
public void updatePassword(String username, String password) {
passwordValidator.validate(username, password);
User user = userService.getUserByName(username);
user.setPassword(password);
userService.saveUser(user);
}
}
Tổng kết
Nguyên tắc này rất quan trọng đối việc phát triển phần mềm, nếu có thể hãy làm nó ngay từ đầu, còn nếu bạn đang vội thì hãy dành 1 phase refactor code để sửa code của mình theo hướng Open/Close này nhé. DesignPattern sẽ là công cụ giúp ích cho bạn rất nhiều đấy. Và đây chỉ là bài đầu tiên nói về nguyên tắc này thôi nhé, 🙂
Tham khảo
-
Design Pattern
- Singleton Design Pattern
- Factory Design Pattern
- Factory Method Design Pattern
- Abstract Factory Design Pattern
- Builder Design Pattern
- Prototype Design Pattern
- Object Pool Design Pattern
- Chain of Responsibility Design Pattern
- Command Design Pattern
- Interpreter Design Pattern
- Iterator Design Pattern
- Mediator Design Pattern
- Memento Design Pattern
- Observer Design Pattern
- Observer Design Pattern - Xử Lý Exception
- Strategy Design Pattern
- Template Method Design Pattern
- Visitor Design Pattern
- Null Object Design Pattern
- Adapter Design Pattern
- Bridge Design Pattern
- Composite Design Pattern
- Decorator Design Pattern
- Flyweight Design Pattern
- Proxy Design Pattern
- S.O.L.I.D
- Clean code
- Lập trình socket
- Java Core
- Multi-Thread
- Spring
- Java Web
- Memory Caching
- Message Queue
- DevOps
- Xây dựng một nền tảng
- MongoDB
- MySQL timestamp
- Properties vs yaml
- Kotlin
- Lập Trình Machine Learning với PyTorch
- Mã Nguồn Mở
- Ezy HTTP
- Free Chat
- Một số kinh nghiệm với Git
- Review cho đồng nghiệp!
- Kinh nghiệm phát triển dự án phức tạp, nhiều người - Tuân thủ
- Kinh nghiệm phát triển dự án phức tạp, nhiều người - Lựa chọn người đi cùng
- Ngành công nghiệp phần mềm tại Việt Nam - Mới chỉ là bắt đầu.
- Ngành công nghiệp phần mềm tại Việt Nam - Dây chuyền sản xuất.
- Ngành công nghiệp phần mềm tại Việt Nam - Thị trường
- Ngành công nghiệp phần mềm tại Việt Nam - Công ăn việc làm
- Setup Dev Environment
- Hello World
- Create a Server Project
- Handle Client Requests
- Using ezyfox-server-csharp-client
- Using ezyfox-es6-client
- Client React.js Interaction
- Build And Deploy In Local
- Tham gia phát triển open source!
- Buôn có bạn, bán có phường
- Đam mê đi đâu rồi?
- Giữa lửa đam mê!
- Tương lai nào cho tester? Thay đổi để dẫn đầu xu thế!
- Tương lai nào cho tester? - Khi thế sự đổi thay!
- Tương lai nào cho lập trình viên? Khi không có hệ quy chiếu!
- Tương lai nào cho lập trình viên - Làm đến bao nhiêu tuổi?
- Tương lai nào cho lập trình viên? Có làm giàu được không?
- Tương lai nào cho lập trình viên? Có cân bằng cuộc sống được không?
- Tương lai nào cho lập trình viên - Nhảy việc đến khi nào?
- Tương lai nào cho lập trình viên - Con đường sự nghiệp (Career path)!
- Tương lai nào cho lập trình viên - Tổng kết lại!
- Con đường sự nghiệp cho lập trình viên - Giai đoạn sơ cấp (Junior)!
- Con đường sự nghiệp cho lập trình viên - Giai đoạn trung cấp (Intermediate)!
- Con đường sự nghiệp cho lập trình viên - Giai đoạn lành nghề (Senior)!
- Giai đoạn lành nghề (Senior) - Giữa những hoang mang!
- Giai đoạn lành nghề (Senior) - Phân hoá trong doanh nghiệp!
- Con đường sự nghiệp cho lập trình viên - Trở thành chuyên gia (Expert)!
- Con đường sự nghiệp cho lập trình viên - Trở thành người ảnh hưởng (Influencer)!
- Các giai đoạn phát triển của lập trình viên - Tổng kết lại!
- Metaverse - Câu chuyện 10 nghìn CCU (Người tham gia đồng thời)
- Metaverse có khả thi ở Việt Nam?
- Lựa chọn nghề nghiệp - DevOps!
- Lựa chọn nghề nghiệp - Project Manager (PM)!
- Lựa chọn nghề nghiệp - Data Engineer!
- Lựa chọn nghề nghiệp - BackEnd Engineer!
- “Talk is cheap. Show me the code” ― Linus Torvalds
- Lựa chọn nghề nghiệp - Web Front-End Engineer!
- Lựa chọn nghề nghiệp - Mobile Engineer!
- Lựa chọn nghề nghiệp - Game Engineer!
- Lựa chọn nghề nghiệp - Product Owner!
- Tuổi trẻ cần đột phá!
- Tuổi trẻ cần sự đồng cảm!
- Tuổi trẻ - điều đáng sợ đầu tiên là gì?
- Tuổi trẻ - Điều đáng sợ thứ 2 là gì?
- Tuổi trẻ - Điều đáng sợ thứ 3 là gì?
- Tuổi trẻ - Điều đáng sợ thứ 4 là gì?
- Nếu tận dụng hết năng lực thì sẽ thế nào?
- Tuổi trẻ - Điều đáng sợ thứ 5 là gì?
- Tuổi trẻ - Điều đáng sợ thứ 6 là gì?
- Tuổi trẻ - Điều đáng sợ thứ 7 là gì?
- Tuổi trẻ - ham học hỏi là như thế nào?
- Đầu tư cho bản thân là gì?
- Học chủ động!
- Có nên quay lại công ty cũ?
- Làm cho startup (công ty nhỏ) hay làm cho công ty lớn? (Phần 1)
- Làm cho startup (công ty nhỏ) hay làm cho công ty lớn? (Phần 2)
- Làm cho startup (công ty nhỏ) hay làm cho công ty lớn? (Phần 3)
- Tự học
- Học tập tại doanh nghiệp
- Học tại trung tâm
- Cách đọc sách kỹ thuật hiệu quả
- Học trong một tổ chức mã nguồn mở.
- Câu chuyện lập trình viên - Công việc đầu tiên
- Câu chuyện lập trình viên - Mức lương đầu tiên
- Câu chuyện lập trình viên - 2018
- Định hướng là gì?
- Wordpress nguy hiểm thế nào?
- Danh sách 10 trung tâm đào tạo trình uy tín, chất lượng ở Hà Nội