

Thiết kế lại và Triển khai
- 28-06-2025
- Toanngo92
- 0 Comments
Ở bài viết trước, ta đã nghiên cứu một hệ thống quản lý phương tiện với sơ đồ lớp và logic nghiệp vụ sơ bộ.
Tuy nhiên, việc từ thiết kế chuyển sang mã nguồn thật sự không phải là con đường tuyến tính.
Trong quá trình triển khai, người phát triển thường gặp phải:
- Các chi tiết thiết kế chưa rõ ràng
- Những ràng buộc chưa được lường trước
- Các vấn đề về hiệu năng, tương thích, mở rộng
→ Vì vậy, cần quay lại và thiết kế lại (redesign) trước khi tiến hành viết mã hoàn chỉnh.
Mục lục
🛠️ 1.3. Hộp công cụ mở rộng – Các mẫu thiết kế
Ở các chủ đề trước, bạn đã được học các mẫu thiết kế như:
- MVC (Model–View–Controller)
- Facade
- Factory
- Observer
- Strategy
v.v.
Chúng chính là những công cụ hữu ích giúp bạn:
- Giảm phụ thuộc giữa các lớp (low coupling)
- Tăng khả năng mở rộng
- Cải thiện sự phân tách trách nhiệm
♻️ 1.4. Tại sao phải thiết kế lại?
Không phải mọi bản thiết kế ban đầu đều tốt. Khi tiến hành triển khai, chúng ta thường:
- Phát hiện lỗ hổng logic
- Gặp khó khăn khi viết mã
- Nhận ra mô hình quá rối rắm hoặc quá chặt chẽ
Thiết kế lại là một bước quan trọng giữa thiết kế lý thuyết và triển khai thực tế, nhằm:
- Tối ưu hóa kiến trúc
- Đơn giản hóa sự phụ thuộc
- Tận dụng mẫu thiết kế đúng lúc, đúng chỗ
⚠️ 1.5. Triển khai không đơn thuần là “viết code”
Việc triển khai cần:
- Tư duy hệ thống: mỗi dòng code phải phù hợp với toàn bộ cấu trúc hệ thống.
- Kỹ năng sử dụng mẫu thiết kế: lựa chọn mẫu phù hợp để code dễ mở rộng và bảo trì.
- Biết đánh đổi: ví dụ thêm một mẫu design pattern có thể làm hệ thống linh hoạt hơn, nhưng cũng làm tăng số lượng class.
💡 1.6. Từ đây, ta sẽ học gì tiếp?
Trong các chương tiếp theo, bạn sẽ được hướng dẫn:
- Đánh giá lại thiết kế hiện tại (sơ đồ lớp cũ)
- Quyết định có cần thiết kế lại không
- Áp dụng các mẫu thiết kế phù hợp
- Viết code triển khai thực tế theo mô hình MVC
- Phân tích cách dùng Factory, Facade, Observer trong bối cảnh cụ thể
- Hiểu quá trình chuyển hóa từ thiết kế thành mã nguồn
✅ Ghi nhớ:
Thiết kế lại không có nghĩa là bỏ đi thiết kế cũ.
Mà là cải tiến dựa trên góc nhìn mới và trải nghiệm triển khai thực tế.
Đánh giá thiết kế cũ và cơ hội tái cấu trúc
🔍 2.1. Vì sao phải đánh giá lại thiết kế?
Sau khi có bản thiết kế sơ bộ (ví dụ: sơ đồ lớp ở Chủ đề 6), ta cần:
- Xác định vấn đề tiềm ẩn trong thiết kế
- Đánh giá xem có đang vi phạm các nguyên lý thiết kế như cohesion thấp hoặc coupling cao
- Tìm kiếm cơ hội để refactor trước khi triển khai chính thức
❗ Một thiết kế không được rà soát kỹ trước khi code rất dễ tạo ra “nợ kỹ thuật”.
🧱 2.2. Sơ đồ lớp hiện tại
Thiết kế hệ thống hiện tại bao gồm các lớp như:
Job
,Employee
,Garage
,Vehicle
,Customer
,Payroll
,Organisation
Mỗi lớp đại diện cho một thực thể trong hệ thống quản lý phương tiện.
✅ Nhận xét sơ bộ:
- Các lớp có trách nhiệm rõ ràng
- Không trùng chức năng
- Không chia sẻ biến toàn cục
- → Thiết kế ổn, nhưng chưa tối ưu.
🔎 2.3. Đánh giá theo Cohesion và Coupling
Tiêu chí | Nhận xét |
---|---|
Cohesion (kết dính) | Tương đối cao. Mỗi lớp đều tập trung làm đúng 1 nhiệm vụ |
Coupling (phụ thuộc) | Ở mức trung bình. Các lớp vẫn còn liên kết trực tiếp với nhau |
→ Cơ hội cải thiện:
- Tách biệt các module lớn để giảm liên kết
- Ẩn chi tiết thực thi bên trong các lớp “vỏ bọc” (dùng Facade)
- Tự động hóa việc tạo đối tượng (dùng Factory)
🔁 2.4. Khi nào nên refactor?
Dấu hiệu | Hành động |
---|---|
Một lớp có quá nhiều chức năng | Tách lớp |
Nhiều lớp gọi trực tiếp đến nhau | Dùng interface hoặc mẫu Facade |
Mã khởi tạo đối tượng lặp đi lặp lại | Áp dụng Factory |
Thay đổi một phần làm ảnh hưởng nhiều phần khác | Dùng Observer để giảm liên kết |
🧠 2.5. Tư duy thiết kế lại (Redesign Thinking)
“Thiết kế lại là một nghệ thuật – không có đúng tuyệt đối, nhưng có rất nhiều sai.”
Các nguyên tắc cần nhớ:
- Không thay đổi chỉ vì “muốn sạch đẹp hơn”
- Thiết kế lại phải giải quyết vấn đề thực tế
- Luôn cân nhắc cái giá phải trả (phức tạp tăng lên? số lượng class tăng?)
- Không nên lạm dụng các mẫu thiết kế
📌 2.6. Các lựa chọn tái thiết kế
🔹 Phương án 1: Thiết kế lại theo thành phần (Component-based)
- Tách hệ thống thành các nhóm lớn:
- Vehicle Management
- Personnel Management
- Customer Management
→ Ưu điểm: dễ quản lý theo mô-đun
→ Nhược điểm: tăng số lượng lớp, cohesion thấp hơn, không phù hợp với quy mô nhỏ
🔹 Phương án 2: Áp dụng mẫu thiết kế phù hợp
- Facade: tạo lớp giao diện hộp đen giữa các module
- Factory: xử lý logic khởi tạo phức tạp
- Observer: cập nhật giữa model và UI
→ Phù hợp hơn cho hệ thống hiện tại
📎 2.7. Kết luận chương
- Thiết kế cũ nhìn chung ổn định, nhưng vẫn có điểm nghẽn
- Không nên triển khai vội nếu:
- Có coupling cao
- Lớp chịu nhiều trách nhiệm
- Việc mở rộng gây ảnh hưởng nhiều nơi
- Refactor là cách chuẩn bị để triển khai dễ dàng và hiệu quả hơn
- Mẫu thiết kế nên được chọn dựa trên vấn đề cụ thể, không phải theo sở thích cá nhân
Áp dụng các mẫu thiết kế
🎯 3.1. Tại sao cần mẫu thiết kế?
Sau khi đánh giá lại thiết kế, ta nhận ra:
- Một số lớp phụ thuộc trực tiếp vào nhau
- Việc tạo đối tượng thiếu kiểm soát và lặp lại
- Giao diện người dùng và logic nghiệp vụ chưa tách biệt
→ Đây là cơ hội để áp dụng các mẫu thiết kế (design patterns) nhằm:
- Tăng tính mở rộng
- Giảm phụ thuộc giữa các lớp
- Làm rõ trách nhiệm của từng phần
🏗️ 3.2. Mô hình MVC – Tách biệt rõ ràng giao diện và logic
Thành phần | Vai trò |
---|---|
Model | Chứa dữ liệu, xử lý logic nghiệp vụ |
View | Giao diện người dùng (UI) |
Controller | Điều phối giữa View và Model |
📌 Trong hệ thống hiện tại:
- Model: đã có – gồm
Vehicle
,Job
,Garage
,Organisation
… - View/Controller: cần thiết kế cho cả bản desktop và web (dùng chung model)
→ Ưu điểm:
- Tăng khả năng tái sử dụng model
- Cho phép triển khai đa giao diện
🎭 3.3. Mẫu Facade – Giao diện hộp đen đơn giản hóa tương tác
Vấn đề: Nếu các lớp frontend gọi trực tiếp vào các lớp trong model → coupling cao, khó bảo trì.
✅ Giải pháp:
Tạo một lớp trung gian gọi là Facade, ví dụ SystemGateway
, chịu trách nhiệm:
- Gọi đến các lớp con trong model
- Cung cấp API đơn giản cho UI
→ View chỉ cần gọi SystemGateway.addVehicle(...)
mà không cần biết chi tiết bên dưới là gì.
🏭 3.4. Mẫu Factory – Quản lý việc tạo đối tượng
Vấn đề: Nếu mỗi lần tạo xe đều phải new Vehicle()
và cấu hình lại → trùng lặp và dễ sai.
✅ Giải pháp:
Tạo lớp VehicleFactory
với phương thức getVehicle(int type)
- Tự động trả về đối tượng Vehicle đã cấu hình đúng
- Dễ bảo trì khi thêm loại xe mới
Ví dụ:
javaCopyEditVehicle v = VehicleFactory.getVehicle(TYPE_TRANSIT);
→ Ưu điểm:
- Giảm lặp code
- Dễ cấu hình, mở rộng loại phương tiện
👁️ 3.5. Mẫu Observer – Giao tiếp tự động giữa các lớp
Vấn đề: Khi dữ liệu thay đổi (Model), View không tự biết để cập nhật.
✅ Giải pháp:
- Model có thể “thông báo” tới các View khi có thay đổi
- Dùng interface
Observer
để thiết kế linh hoạt
→ Kết nối lỏng (loose coupling) giữa Model và View
Ví dụ ứng dụng:
- Khi
Garage.addVehicle(...)
được gọi, View sẽ tự động cập nhật danh sách xe.
🧠 3.6. Khi nào không nên dùng mẫu thiết kế?
Tình huống | Giải pháp |
---|---|
Hệ thống quá nhỏ | Không dùng pattern phức tạp, chỉ cần code đơn giản |
Không có khả năng tái sử dụng | Tránh over-engineering |
Quá nhiều pattern → rối rắm | Chỉ dùng khi có vấn đề cụ thể cần giải quyết |
✅ 3.7. Tổng kết chương
Mẫu thiết kế | Tác dụng |
---|---|
MVC | Tách biệt UI – Logic |
Facade | Giảm phụ thuộc frontend ↔ model |
Factory | Quản lý việc khởi tạo đối tượng |
Observer | Tự động cập nhật UI khi model thay đổi |
🧩 Dùng đúng pattern vào đúng chỗ là chìa khóa để hệ thống dễ bảo trì – dễ mở rộng – dễ kiểm thử.
Triển khai hệ thống từ thiết kế
🧭 4.1. Mục tiêu của quá trình triển khai
Sau khi hoàn tất thiết kế và lựa chọn các mẫu phù hợp, bước tiếp theo là viết mã nguồn (coding) cho từng thành phần của hệ thống. Việc triển khai cần:
- Tuân thủ đúng thiết kế đã thống nhất
- Áp dụng mẫu thiết kế vào thực tế
- Viết code có cấu trúc, rõ ràng, dễ bảo trì
📐 4.2. Phân tích thứ tự triển khai
Triển khai nên bắt đầu từ lớp ít phụ thuộc nhất:
- Các lớp cơ bản như
Vehicle
,Job
- Các lớp chứa tập hợp như
Garage
- Lớp điều phối trung tâm như
Organisation
- Facade
- View / Controller
✅ Triển khai từ trong ra ngoài, từ logic sang UI
🚗 4.3. Cài đặt lớp Vehicle
Đây là lớp cơ bản đại diện cho phương tiện.
javaCopyEditpublic class Vehicle {
private double rate;
private int capacity;
public void setRate(double val) { rate = val; }
public double getRate() { return rate; }
public void setCapacity(int val) { capacity = val; }
public int getCapacity() { return capacity; }
}
⚙️ Lớp đơn giản, dễ test, không phụ thuộc ai
🏭 4.4. Cài đặt lớp VehicleFactory
Dùng mẫu Factory để tạo các đối tượng Vehicle
theo loại.
javaCopyEditpublic class VehicleFactory {
public static final int TYPE_TRANSIT = 0;
public static final int TYPE_COMBO = 1;
public static final int TYPE_BOX = 2;
public static Vehicle getVehicle(int type) {
double rate = 0.0;
int capacity = 0;
Vehicle v = new Vehicle();
switch (type) {
case TYPE_TRANSIT: rate = 2.0; capacity = 2000; break;
case TYPE_COMBO: rate = 1.5; capacity = 1000; break;
case TYPE_BOX: rate = 3.0; capacity = 5000; break;
default: return null;
}
v.setRate(rate);
v.setCapacity(capacity);
return v;
}
}
🎯 Tách riêng logic khởi tạo → dễ quản lý, dễ mở rộng
🅿️ 4.5. Cài đặt lớp Garage
– tập hợp các phương tiện
javaCopyEditimport java.util.HashMap;
public class Garage {
private HashMap<String, Vehicle> myVehicles;
public Garage() {
myVehicles = new HashMap<>();
}
public void addVehicle(String licence, int type) {
Vehicle v = VehicleFactory.getVehicle(type);
if (v != null) {
myVehicles.put(licence, v);
}
}
public Vehicle getVehicle(String licence) {
return myVehicles.get(licence);
}
}
📦 Lưu trữ phương tiện theo biển số xe.
DùngHashMap
để tra cứu nhanh.
🧑💼 4.6. Triển khai Facade – lớp điều phối trung tâm
javaCopyEditpublic class SystemGateway {
private Garage garage;
public SystemGateway() {
garage = new Garage();
}
public void registerVehicle(String licence, int type) {
garage.addVehicle(licence, type);
}
public Vehicle findVehicle(String licence) {
return garage.getVehicle(licence);
}
}
🎯 Giúp UI không cần biết
Garage
hayFactory
, chỉ gọiSystemGateway
.
👁️ 4.7. Kết nối với View – định hướng Observer
Giả sử bạn có UI JavaFX hoặc Swing:
javaCopyEditSystemGateway system = new SystemGateway();
system.registerVehicle("51A-12345", VehicleFactory.TYPE_TRANSIT);
Vehicle v = system.findVehicle("51A-12345");
System.out.println("Rate: " + v.getRate());
Nếu bạn muốn UI tự động cập nhật khi có thay đổi, có thể dùng mẫu Observer hoặc Property Binding (trong JavaFX).
🔧 4.8. Ghi nhớ kỹ thuật triển khai
Bước | Nội dung |
---|---|
1 | Bắt đầu từ lớp độc lập |
2 | Cài đặt Factory để đơn giản hóa khởi tạo |
3 | Dùng Facade để gom các tương tác phức tạp |
4 | Tách riêng View – Model – Controller |
5 | Viết test sớm để kiểm tra từng lớp |
📌 4.9. Tổng kết chương
- Quá trình triển khai nên đi theo thiết kế đã được cải tiến
- Mẫu thiết kế giúp code dễ hiểu, dễ mở rộng
- Dù viết code, ta vẫn cần tư duy thiết kế – không nên “code freestyle”
Tổng kết dự án
🎯 5.1. Hành trình từ thiết kế đến triển khai
Chúng ta đã bắt đầu với một hệ thống có sẵn thiết kế sơ bộ. Qua quá trình:
- Đánh giá lại thiết kế để phát hiện điểm yếu (coupling cao, cohesion thấp)
- Áp dụng mẫu thiết kế phù hợp để tối ưu kiến trúc
- Viết mã nguồn triển khai từng lớp, từ đơn giản đến phức tạp
- Xây dựng Facade và phân lớp rõ ràng để chuẩn bị tích hợp với UI
→ Giúp hệ thống sạch hơn, dễ mở rộng và dễ bảo trì.
🧰 5.2. Các mẫu thiết kế đã áp dụng – và lý do
Mẫu thiết kế | Mục đích | Áp dụng |
---|---|---|
MVC | Tách UI khỏi logic nghiệp vụ | Dùng cho cả desktop & web |
Facade | Ẩn chi tiết hệ thống, giảm phụ thuộc UI | Lớp SystemGateway |
Factory | Tạo đối tượng đúng cách, không lặp code | Lớp VehicleFactory |
Observer | Kết nối model và UI linh hoạt | Gợi ý dùng nếu muốn cập nhật UI tự động |
🧠 Dùng design pattern đúng lúc đúng chỗ là yếu tố quyết định cho kiến trúc tốt.
📉 5.3. Những sai lầm thường gặp khi thiết kế và triển khai
Sai lầm | Hậu quả |
---|---|
Thiết kế ban đầu thiếu đánh giá | Gặp lỗi logic khi code |
Không dùng mẫu phù hợp | Code rối, khó bảo trì |
Quá lạm dụng pattern | Tăng độ phức tạp không cần thiết |
Code trước, thiết kế sau | Không mở rộng được về sau |
✅ 5.4. Kinh nghiệm rút ra
- Thiết kế lại là bình thường, không phải thất bại
- Phải luôn đánh giá lại kiến trúc trước khi viết code
- Pattern là công cụ, không phải mục tiêu
- Tách UI – Logic ngay từ đầu giúp tránh lỗi khó sửa
- Code phải phản ánh đúng thiết kế, và ngược lại
🧭 5.5. Hướng phát triển tiếp theo
Sau khi đã hoàn thành quá trình thiết kế lại và triển khai hệ thống nhỏ, bạn nên tiếp tục học:
- Viết Unit Test và TDD cho các lớp đã triển khai
- Thiết kế lại hệ thống với yêu cầu mở rộng (thêm tính năng quản lý tài xế, phân quyền…)
- Triển khai Web UI hoặc Mobile App dựa trên MVC
- Học nâng cao về Domain-Driven Design, Microservices
📌 5.6. Tổng kết cuối cùng
Một thiết kế tốt không phải là thiết kế đẹp trên giấy,
mà là thiết kế có thể chuyển thành code hoạt động thực tế
và chịu được thay đổi theo thời gian.