

Phân tích và Thiết kế Tĩnh
- 14-06-2025
- Toanngo92
- 0 Comments
Mục lục
Khái niệm Mô hình tĩnh trong kiến trúc phần mềm
1.1. Mô hình tĩnh là gì?
Trong thiết kế phần mềm hướng đối tượng, mô hình tĩnh (static model) là cách biểu diễn cấu trúc bên trong của hệ thống mà không phụ thuộc vào thời gian hay hành vi người dùng. Nó thể hiện:
- Các lớp (class) trong hệ thống
- Thuộc tính và phương thức của lớp
- Quan hệ giữa các lớp (kế thừa, kết hợp, phụ thuộc…)
🔍 Mô hình tĩnh còn được gọi là “cái nhìn cấu trúc” (structural view) – trái ngược với mô hình động (behavioral view) vốn tập trung vào hành vi và luồng thực thi.
🧭 1.2. Khác biệt giữa mô hình tĩnh và động
Tiêu chí | Mô hình tĩnh | Mô hình động |
---|---|---|
Mục đích chính | Biểu diễn cấu trúc nội tại của hệ thống | Biểu diễn hành vi thay đổi theo thời gian |
Giai đoạn sử dụng | Phân tích – Thiết kế | Thiết kế – Mô phỏng – Kiểm thử |
Công cụ chính | Class Diagram | Sequence Diagram, Activity Diagram, State Diagram |
Có liên quan đến thời gian? | ❌ Không | ✅ Có |
Ví dụ | Quan hệ giữa lớp User , Order , Product | Người dùng đăng nhập → thêm hàng → thanh toán |
🧱 1.3. Mô hình tĩnh trả lời các câu hỏi:
- Những thành phần chính trong hệ thống là gì?
- Các thành phần này có mối liên hệ với nhau như thế nào?
- Chúng có dữ liệu gì, và chức năng nào đi kèm với dữ liệu đó?
- Đâu là cấu trúc “lõi” tạo nên toàn bộ hệ thống?
🧰 1.4. Công cụ chính để tạo mô hình tĩnh: Class Diagram (Sơ đồ lớp)
Trong UML (Unified Modeling Language), công cụ chính để biểu diễn mô hình tĩnh là Class Diagram.
Một sơ đồ lớp bao gồm:
Thành phần | Ý nghĩa |
---|---|
Class (Lớp) | Định nghĩa khuôn mẫu cho object – bao gồm thuộc tính (attribute) và hành vi (method) |
Thuộc tính | Thông tin mà lớp lưu trữ |
Phương thức | Hành động mà lớp có thể thực hiện |
Quan hệ | Kế thừa (inheritance), kết hợp (aggregation), phụ thuộc (dependency), liên kết (association) |
⚠️ 1.5. Những điều mô hình tĩnh không làm được
- Không mô tả trình tự các hành động
- Không biểu diễn tương tác người dùng
- Không phản ánh luồng điều khiển (control flow) hay điều kiện nhánh
→ Do đó, để có cái nhìn toàn diện, cần kết hợp với mô hình động
🔁 1.6. Mô hình tĩnh và sự thay đổi trong agile
Trong môi trường phát triển linh hoạt (agile):
- Mô hình tĩnh vẫn rất cần thiết → để hiểu hệ thống, chia module, giao việc
- Nhưng phải linh hoạt, dễ cập nhật, tránh biến sơ đồ thành “tượng đài bất động”
- Class Diagram nên được cập nhật theo iteration, như code vậy
📌 1.7. Ứng dụng của mô hình tĩnh trong thực tế
Giai đoạn | Vai trò của mô hình tĩnh |
---|---|
Phân tích | Xác định các thực thể chính trong nghiệp vụ |
Thiết kế | Định nghĩa lớp, module, kiến trúc phần mềm |
Lập trình | Hướng dẫn viết class, mối quan hệ và logic |
Giao tiếp nội bộ | Giúp các thành viên hiểu hệ thống chung |
Giao tiếp với khách hàng | Dễ hình dung hệ thống hơn sơ đồ code hoặc văn bản |
Ghi nhớ:
- Mô hình tĩnh = cấu trúc phần mềm ở dạng “xương sống”
- Class Diagram là công cụ chính để thể hiện mô hình này
- Không mô tả hành vi – nhưng quyết định toàn bộ kiến trúc
- Cần được duy trì song song với code, và không được lạc hậu
Thu thập yêu cầu và xác định lớp ứng viên bằng phân tích ngôn ngữ tự nhiên (NLA)
Vấn đề: Làm sao chuyển từ mô tả sang thiết kế?
Khi bắt đầu xây dựng hệ thống phần mềm, nhóm phát triển thường nhận được:
- Tài liệu yêu cầu
- Kết quả từ phỏng vấn người dùng
- Ghi chú từ prototype giấy
Tất cả các thông tin đó được viết bằng ngôn ngữ tự nhiên – và nhiệm vụ của kỹ sư phân tích là:
Biến những mô tả “rối rắm” đó thành cấu trúc lớp có thể lập trình được.
Ngôn ngữ tự nhiên chứa gì?
Ngôn ngữ con người sử dụng mỗi ngày (tiếng Việt, tiếng Anh…) tuy không chính xác như ngôn ngữ lập trình, nhưng lại ẩn chứa rất nhiều manh mối để tìm ra thiết kế kỹ thuật, như:
Thành phần câu | Có thể dùng để xác định |
---|---|
Danh từ (noun) | Lớp (Class) |
Động từ (verb) | Phương thức (Method) |
Tính từ (adjective) | Thuộc tính (Attribute) |
Câu điều kiện / mô tả hành vi | Logic xử lý (business logic) |
Phân tích ngôn ngữ tự nhiên (Natural Language Analysis – NLA)
Bước 1: Đọc đoạn mô tả nghiệp vụ
Ví dụ:
“Hệ thống quản lý thư viện cho phép thêm, xóa, sửa thông tin sách và khách hàng. Thông tin sách bao gồm mã ISBN, tiêu đề, mô tả. Người dùng có thể truy cập trang web để xem danh mục sách và giữ chỗ.”
Bước 2: Rút ra các từ khóa chính
Thành phần | Loại từ | Ứng viên thiết kế |
---|---|---|
sách, thư viện, khách hàng, trang web, danh mục | danh từ | → Class |
thêm, xóa, sửa, truy cập, xem, giữ chỗ | động từ | → Method |
ISBN, tiêu đề, mô tả | danh từ nhỏ | → Attribute |
Lợi ích của NLA
- Giúp xác định nhanh lớp và chức năng cơ bản
- Tăng tính hệ thống khi làm việc với tài liệu nghiệp vụ dài
- Phù hợp cho giai đoạn đầu, khi chưa rõ nghiệp vụ chi tiết
Tuy nhiên: NLA chỉ là bước đầu tiên, cần kết hợp với kiểm tra logic & xác minh cùng người dùng để tránh hiểu sai.
Làm sạch danh sách lớp ứng viên
Sau khi lấy được danh sách sơ bộ, cần lọc lại:
Loại nên loại bỏ | Lý do |
---|---|
Từ đồng nghĩa hoặc trùng lặp (VD: “người dùng”, “khách hàng”) | Giữ lại một bản đại diện |
Từ quá trừu tượng (VD: “quản lý”, “hệ thống”) | Không biểu diễn được trong code |
Thực thể có sẵn trong nền tảng (VD: “cơ sở dữ liệu”) | Không cần biểu diễn thành lớp riêng |
Các yếu tố không nằm trong phạm vi hệ thống | Tránh làm phức tạp thiết kế |
Ví dụ sau khi lọc
Lớp (Class) | Hành động (Method) |
---|---|
Library | thêm sách, xóa sách, thêm khách hàng… |
Book | cập nhật tiêu đề, hiển thị chi tiết |
Patron (Khách hàng) | cập nhật thông tin, đặt chỗ |
Catalogue (Danh mục) | tìm kiếm sách, phân loại sách |
WebPage | hiển thị danh sách, điều hướng |
Những gì NLA không cho bạn được
- Mối quan hệ giữa các lớp (kế thừa, kết hợp…)
- Chi tiết xử lý logic hoặc điều kiện nghiệp vụ
- Phạm vi hoạt động của từng method
➤ Đây là nhiệm vụ của giai đoạn thiết kế chi tiết sau đó, thông qua vẽ sơ đồ lớp, sơ đồ trình tự, hoặc pseudocode.
Ghi nhớ:
- Ngôn ngữ tự nhiên là kho dữ liệu tiềm ẩn để xác định thiết kế phần mềm
- Phân tích danh từ → lớp; động từ → hành động; tính từ → thuộc tính
- Kỹ thuật NLA giúp bạn bắt đầu nhanh và có hệ thống, nhưng phải kiểm tra và lặp lại
- Sau bước này, bạn sẽ có danh sách lớp và chức năng sơ bộ – nền tảng để vẽ sơ đồ lớp UML
Xây dựng sơ đồ lớp
🧱 3.1. Mục tiêu của sơ đồ lớp
Sau khi có danh sách lớp ứng viên, ta cần xây dựng sơ đồ lớp (Class Diagram) để:
- Tổ chức mối quan hệ giữa các lớp
- Gán hành động (method) cho đúng lớp
- Thiết kế hệ thống có cấu trúc rõ ràng, dễ bảo trì, mở rộng
🎯 Sơ đồ lớp là xương sống của mô hình tĩnh – thể hiện kiến trúc bên trong hệ thống
🛠 3.2. Nguyên tắc khi chuyển từ danh sách sang sơ đồ
Nguyên tắc thiết kế lớp | Giải thích |
---|---|
Gán method vào class “nắm giữ dữ liệu liên quan” | Nếu phương thức cần dữ liệu gì → đặt vào lớp chứa dữ liệu đó |
Giữ mức trừu tượng cao | Không mô tả chi tiết logic xử lý trong sơ đồ lớp |
Loại bỏ class dư thừa | Nếu class không có method hoặc attribute → cân nhắc gộp/bỏ |
Tránh class chỉ có một thuộc tính | Có thể gộp thành thuộc tính trong class khác |
Giữ số lượng class đủ dùng | Không quá ít, không quá nhiều, tránh phức tạp hóa hoặc đơn giản hóa quá mức |
📉 3.3. Cách trình bày sơ đồ lớp UML
Mỗi class gồm 3 phần chính:
pgsqlCopyEdit+------------------------+
| ClassName |
+------------------------+
| - attribute1: Type |
| - attribute2: Type |
+------------------------+
| + method1(): ReturnType|
| + method2(arg: Type): |
| ReturnType |
+------------------------+
- Dấu
+
: public - Dấu
-
: private - Gạch ngang phân tách phần tên, thuộc tính, phương thức
🔄 3.4. Ví dụ minh họa từ hệ thống quản lý thư viện
Danh sách lớp ứng viên:
- Library
- Book
- Patron
- Catalogue
- WebPage
Chuyển thành sơ đồ lớp đơn giản:
diffCopyEdit+-------------------+
| Library |
+-------------------+
| - books: List<Book> |
| - patrons: List<Patron> |
+-------------------+
| + addBook(...) |
| + removeBook(...) |
| + addPatron(...) |
| + getBook(...) |
+-------------------+
diffCopyEdit+-------------------+
| Book |
+-------------------+
| - ISBN: String |
| - title: String |
| - author: String |
+-------------------+
| + getSummary() |
+-------------------+
→ Quan hệ: Library
có Book
và Patron
→ association
🧠 3.5. Khi nào nên bỏ bớt hoặc gộp class?
Tình huống | Giải pháp gợi ý |
---|---|
Class chỉ có 1 attribute và 0 method | Gộp vào class khác |
Class không được dùng bởi class nào khác | Xem lại, có thể bỏ hoặc đang thừa |
Class có cùng logic & dữ liệu như class khác | Gộp lại hoặc dùng kế thừa |
🔁 3.6. Vẽ sơ đồ lớp: nên lặp lại
- Bản vẽ đầu tiên chỉ là phác thảo
- Sau khi:
- Kiểm thử với người dùng
- Xác định quy trình logic
- Lập trình thử prototype
→ Cần vẽ lại để phản ánh thay đổi logic, sửa lỗi hoặc tối ưu
📌 3.7. Tóm tắt quá trình xây dựng sơ đồ lớp
Bước | Mô tả |
---|---|
1 | Từ yêu cầu → phân tích NLA → danh sách class & method sơ bộ |
2 | Loại bỏ class trùng lặp, không cần thiết |
3 | Vẽ sơ đồ: tên class, thuộc tính, phương thức |
4 | Thêm quan hệ giữa class (association, inheritance…) |
5 | Kiểm tra lại mức trừu tượng, sự hợp lý |
6 | Lặp lại – tối ưu – xác nhận với nhóm hoặc người dùng |
💬 Ghi nhớ:
- Sơ đồ lớp là công cụ thiết kế kỹ thuật cốt lõi trong phân tích tĩnh
- Phải được xây dựng cẩn thận từ yêu cầu → chứ không vẽ cho có
- Thiết kế class tốt sẽ giúp:
- Code dễ tổ chức
- Kiểm thử dễ hơn
- Bảo trì lâu dài tốt hơn
Giải quyết mơ hồ
🧩 4.1. Mơ hồ là điều không thể tránh khỏi
Khi tiếp cận một tài liệu yêu cầu hoặc phỏng vấn người dùng, bạn sẽ thường xuyên gặp những mô tả như:
“Hệ thống cho phép quản lý sách.”
“Người dùng có thể thao tác với đơn hàng.”
“Thông tin cần được xử lý hợp lý.”
Những cụm từ này không đủ thông tin kỹ thuật, không rõ ràng, và không thể lập trình ngay được.
🔎 4.2. Vì sao mơ hồ xảy ra?
Nguyên nhân | Ví dụ |
---|---|
Người dùng không biết diễn đạt kỹ thuật | Họ nói “xử lý đơn hàng” nhưng không rõ “xử lý” là gì |
Tài liệu copy từ hệ thống cũ | Có những cụm từ chung chung như “quản lý dữ liệu” |
NLA tạo ra động từ chung chung | “manipulate”, “handle”, “process” – cần làm rõ thêm |
🎯 4.3. Mục tiêu: chuyển từ “mơ hồ” → hành động cụ thể
Ví dụ:
“Hệ thống cần xử lý sách.”
Bạn không biết:
- “Xử lý” là thêm, sửa, xóa hay chỉ là hiển thị?
- Ai làm điều đó?
- Khi nào hành động diễn ra?
🛠 4.4. Kỹ thuật làm rõ mơ hồ
✅ 1. Đặt câu hỏi phản hồi (clarifying questions)
Hành động mơ hồ | Câu hỏi gợi ý |
---|---|
“Quản lý sách” | Có nghĩa là thêm, xóa, sửa, hay chỉ xem? Ai làm việc đó? |
“Xử lý đơn hàng” | Bao gồm in hóa đơn, cập nhật trạng thái, tính phí vận chuyển? |
“Gửi email” | Tự động hay thủ công? Theo lịch hay theo sự kiện? |
🎤 Trao đổi với người dùng là cách duy nhất để xác thực
✅ 2. Tạo nguyên mẫu (prototype)
- Dùng prototype giấy, hoặc vẽ sơ đồ Use Case đơn giản → cho người dùng phản hồi trực tiếp
- Hỏi: “Nếu bạn làm công việc này trên phần mềm, bạn sẽ làm theo bước nào?”
✅ 3. Liệt kê hành động khả dĩ, rồi xác nhận
Ví dụ: “Quản lý thư viện” → có thể là:
- Thêm sách mới
- Cập nhật thông tin sách
- Tìm sách
- Gắn sách vào kệ
→ Tạo danh sách, hỏi người dùng: “Bạn muốn hệ thống làm những gì trong số này?”
⚠️ 4.5. Những lỗi phổ biến khi gặp mơ hồ
Sai lầm | Hậu quả |
---|---|
Giả định theo cảm tính | Thiết kế sai, mất thời gian sửa lại sau |
Cố gắng code luôn | Lập trình dựa trên thông tin chưa đủ → lỗi phát sinh |
Không hỏi kỹ người dùng | Dễ gây hiểu nhầm, dẫn đến mất lòng tin |
Mặc định “tính năng này ai cũng biết” | Bỏ sót xử lý quan trọng, làm phần mềm thiếu tính năng |
💡 4.6. Lời khuyên chuyên nghiệp
- Nếu một mô tả khiến bạn phải hỏi: “Cụ thể là gì?” → có nghĩa là nó chưa đủ rõ để đưa vào thiết kế
- Mọi phương thức trong sơ đồ lớp đều phải:
- Có hành vi cụ thể
- Gắn với dữ liệu cụ thể
- Gắn với người thực hiện cụ thể
💬 Nếu không rõ 3 điều đó, đừng code vội.
🧾 4.7. Quy trình 3 bước xử lý yêu cầu mơ hồ
Bước | Hành động cụ thể |
---|---|
1 | Khoanh vùng hành động mơ hồ trong tài liệu |
2 | Liệt kê mọi khả năng hành vi tương ứng |
3 | Xác minh lại với người dùng / khách hàng |
Ghi nhớ:
- Mơ hồ là bình thường – nhưng đưa mơ hồ vào thiết kế là nguy hiểm
- Mỗi hành động được đưa vào sơ đồ lớp phải rõ ràng, xác thực, có mục đích
- Câu hỏi hay + prototype thông minh = thiết kế tốt
- Hiểu sai yêu cầu = mất tiền, mất thời gian, mất niềm tin
Vẽ sơ đồ lớp sơ bộ
✏️ 5.1. Bản nháp đầu tiên: chưa cần hoàn hảo, chỉ cần rõ
Sau khi có:
- Danh sách lớp và hành động sơ bộ (qua NLA)
- Lọc bỏ lớp thừa, hành động mơ hồ
- Xác định trách nhiệm sơ bộ của từng class
Ta bắt đầu vẽ sơ đồ lớp sơ bộ – đây là bước để:
✅ Xác nhận thiết kế ban đầu có hợp lý không
✅ Dùng làm công cụ trao đổi với người dùng hoặc nhóm phát triển
📐 5.2. Nội dung cần có trong sơ đồ lớp nháp
Thành phần | Có bắt buộc không? | Ghi chú |
---|---|---|
Tên lớp (class name) | ✅ Bắt buộc | Viết rõ, dễ hiểu, dùng danh từ |
Các thuộc tính (attributes) | ✅ Bắt buộc nếu đã xác định | Ghi kiểu dữ liệu nếu có |
Các phương thức (methods) | ✅ Bắt buộc nếu đã biết | Chỉ cần tên và đầu vào |
Quan hệ giữa các lớp | ✅ Nên có | Dùng association / inheritance |
📝 Không cần ghi logic xử lý (implementation) trong giai đoạn nháp.
📊 5.3. Các kiểu quan hệ cơ bản giữa lớp
Quan hệ | Biểu tượng UML | Ý nghĩa |
---|---|---|
Association | Đường thẳng | Class A “biết tới” Class B |
Aggregation | Đầu rỗng (◻) | Class A “có” Class B (quan hệ sở hữu, không bắt buộc sống cùng) |
Composition | Đầu đặc (◆) | Class A “sở hữu chặt” Class B (sống chết cùng nhau) |
Inheritance | Mũi tên tam giác rỗng | Kế thừa (Class A là Class B) |
🧠 5.4. Mục tiêu của bản sơ đồ nháp
- Xác định cấu trúc hợp lý giữa các class
- Phân bổ đúng trách nhiệm cho từng class
- Tìm điểm bất hợp lý:
- Lớp quá phức tạp (God class)
- Nhiều lớp trùng chức năng
- Quan hệ sai logic nghiệp vụ
📉 5.5. Ví dụ: Sơ đồ lớp sơ bộ cho hệ thống thư viện
Giả sử từ yêu cầu ban đầu, ta xác định 4 class:Library
, Book
, Patron
, Catalogue
Ta có thể vẽ sơ đồ lớp như sau (minh họa bằng văn bản):
sqlCopyEdit+-------------------+
| Library |
+-------------------+
| - books: List<Book> |
| - patrons: List<Patron> |
+-------------------+
| + addBook(...) |
| + removeBook(...) |
| + addPatron(...) |
| + getBook(...) |
+-------------------+
|
| contains
↓
+-------------------+
| Book |
+-------------------+
| - ISBN: String |
| - title: String |
| - author: String |
+-------------------+
| + getSummary() |
+-------------------+
→ Sau đó sẽ bổ sung tiếp các lớp như Catalogue
, WebPage
, Shelf
nếu thấy cần.
🧰 5.6. Kiểm tra sơ đồ lớp nháp
Câu hỏi kiểm tra | Mục tiêu |
---|---|
Lớp này có dữ liệu & hành động cụ thể không? | Tránh lớp “rỗng” |
Quan hệ giữa các lớp có đúng nghiệp vụ không? | Tránh nhầm hướng, sai logic |
Có lớp nào làm quá nhiều việc? | Nếu có → tách nhỏ |
Có lớp nào giống nhau về vai trò? | Nếu có → gộp lại hoặc tạo lớp cha |
♻️ 5.7. Chu kỳ hoàn thiện sơ đồ lớp
- Vẽ bản nháp sơ bộ
- Xem lại cùng nhóm hoặc với người dùng
- Điều chỉnh, tách/gộp/đổi tên class nếu cần
- Bổ sung quan hệ, phương thức rõ ràng hơn
- Lặp lại 1–2 vòng đến khi hợp lý
📌 5.8. Sơ đồ lớp không phải là bản vẽ “một lần là xong”
Trong dự án phần mềm thực tế:
- Mỗi thay đổi nghiệp vụ → có thể cần sửa sơ đồ lớp
- Khi logic mới xuất hiện → cần thêm class / method
💬 Hãy coi sơ đồ lớp như bản đồ Google Map – luôn cập nhật, không phải tranh treo tường.
Ghi nhớ:
- Sơ đồ lớp nháp giúp thử nghiệm tư duy thiết kế trước khi viết code
- Không cần chi tiết hóa logic – chỉ cần cấu trúc rõ + quan hệ đúng
- Càng sớm vẽ sơ đồ, càng sớm phát hiện lỗi thiết kế
- Vòng đời của sơ đồ lớp là lặp – kiểm thử – cải tiến
Chuyển thiết kế thành phần mềm thực tế
💡 6.1. Mục tiêu của sơ đồ lớp là để… lập trình
Sơ đồ lớp không chỉ để “trưng bày” – nó là cầu nối giữa giai đoạn thiết kế và lập trình.
🎯 Nếu sơ đồ lớp tốt, việc viết code sẽ rõ ràng, có tổ chức, dễ kiểm thử và dễ mở rộng.
📐 6.2. Những gì sơ đồ lớp cung cấp cho bạn
Thành phần từ sơ đồ | Trong code sẽ là… |
---|---|
Tên class | Tên file hoặc class trong IDE |
Thuộc tính (attributes) | Biến thành các biến (field/property) trong class |
Phương thức (methods) | Thành hàm (function) trong class |
Quan hệ (inheritance, association…) | Dùng từ khóa extends , khai báo đối tượng liên kết |
🧪 6.3. Ví dụ: Từ sơ đồ lớp Library
sang code C# (hoặc Java)
🎓 Từ sơ đồ lớp:
diffCopyEdit+-------------------+
| Library |
+-------------------+
| - books: List<Book> |
| - patrons: List<Patron> |
+-------------------+
| + addBook(...) |
| + removeBook(...) |
| + addPatron(...) |
| + getBook(...) |
+-------------------+
✍️ Thành mã C# (giả lập):
csharpCopyEditclass Library
{
private List<Book> books = new List<Book>();
private List<Patron> patrons = new List<Patron>();
public void AddBook(string ISBN, string title, string author, string description)
{
// TODO: thêm logic sau
}
public void RemoveBook(string ISBN)
{
// TODO: xóa sách theo ISBN
}
public void AddPatron(string forename, string surname, string address)
{
// TODO: thêm khách hàng
}
public Book GetBook(string isbn)
{
return books.FirstOrDefault(b => b.ISBN == isbn);
}
}
🔁 Đây là “bản dịch” thô từ sơ đồ lớp → mã nguồn.
Logic xử lý sẽ được viết sau, từng bước một.
🛠 6.4. Các quyết định lập trình cần đưa ra
Trong UML | Trong lập trình thực tế |
---|---|
List<Book> | Dùng ArrayList , List<T> , hoặc Set ? |
+ getBook(): Book | Cần kiểm tra null, xử lý ngoại lệ? |
- books: List<Book> | Có cần bảo mật? Có cần dùng private + getter không? |
void addBook(...) | Nên trả bool hay void ? Xử lý lỗi thế nào? |
🧠 Sơ đồ chỉ gợi ý – bạn cần ra quyết định cụ thể khi code.
🧬 6.5. Giai đoạn này không cần viết toàn bộ code
Mục tiêu là:
- Tạo “bộ khung” class
- Khai báo biến, method với tên và kiểu phù hợp
- Để sau đó:
- Viết logic
- Viết unit test
- Giao cho thành viên khác code cụ thể
🔁 6.6. Kết nối lại với sơ đồ Use-Case
Mỗi Use Case trước đó (VD: “Thêm sách”, “Tìm khách hàng”) → sẽ được thực thi bằng một hoặc nhiều method trong class.
Use Case | Lớp liên quan | Method dự kiến |
---|---|---|
Thêm sách mới | Library | addBook(...) |
Mượn sách | Library , Patron | borrowBook(Patron, Book) |
Tìm sách theo ISBN | Library | getBook(string isbn) |
⚠️ 6.7. Những lỗi thường gặp khi chuyển từ sơ đồ lớp sang code
Lỗi | Hậu quả |
---|---|
Quên truyền đủ tham số | Không đủ dữ liệu khi khởi tạo đối tượng |
Lạm dụng getter/setter | Phá vỡ tính đóng gói của class |
Viết logic trong class sai | Mất trách nhiệm rõ ràng → khó bảo trì |
Tạo God class | Quá nhiều method trong một class |
📌 6.8. Nguyên tắc thực hành khi viết mã từ sơ đồ lớp
- Tạo mỗi class thành một file riêng
- Khai báo tên, biến, phương thức rõ ràng
- Không viết logic vội nếu chưa chắc
- Chỉ cần cấu trúc rõ ràng, đặt đúng nơi
Ghi nhớ:
- Sơ đồ lớp tốt → code dễ tổ chức
- Không cần viết đầy đủ logic ban đầu – chỉ cần khung rõ ràng, gọn gàng
- Quan hệ giữa class nên được biểu diễn qua biến (composition), kế thừa, interface
- Sau bước này, bạn đã có:
- Toàn bộ cấu trúc code ban đầu
- Các method có tên rõ ràng, thông số cụ thể
- Nền tảng để phát triển thật sự hệ thống
Prototype – Làm trước, bỏ sau
7.1. Prototype là gì?
Prototype (nguyên mẫu) trong thiết kế phần mềm là một phiên bản đơn giản hóa của hệ thống, được tạo ra sớm để:
- Kiểm tra tính khả thi ý tưởng
- Nhận phản hồi từ người dùng
- Xác định điểm thiếu sót trong thiết kế
💬 “Prototype là nơi thử sai rẻ tiền – trước khi bước vào xây dựng tốn kém.”
Tại sao cần prototype trong OOAD?
Với thiết kế hướng đối tượng, việc phân chia class, xây dựng quan hệ, và gắn hành động vào đúng nơi không phải lúc nào cũng rõ ràng.
Một prototype giúp:
- Kiểm tra sơ đồ lớp đã hợp lý chưa
- Cho người dùng thấy luồng chức năng có thực tế không
- Giúp nhóm phát hiện lỗi logic sớm
Hai loại prototype phổ biến
Loại nguyên mẫu | Mục đích chính | Đặc điểm |
---|---|---|
Throwaway Prototype | Kiểm tra ý tưởng nhanh, nhận phản hồi | Viết nhanh, dùng xong rồi bỏ |
Incremental Prototype | Xây dần từng phần hệ thống thật | Có thể dùng lại, phát triển tiếp luôn |
Throwaway Prototype – “Viết để vứt, nhưng không uổng”
- Được làm ra để:
- Thử nghiệm ý tưởng mới
- Minh họa cho người dùng
- Giao tiếp trong nhóm
- Thường là:
- Code đơn giản (viết nhanh, thiếu kiểm tra)
- Giao diện chưa đẹp
- Logic sơ bộ
- Sau khi xác nhận:
- Bỏ đi hoàn toàn
- Xây lại từ đầu cho sạch sẽ
Không nên “tái chế” throwaway → sẽ dẫn đến nợ kỹ thuật
Incremental Prototype – “Viết để dùng thật”
- Là cách xây hệ thống từ các phần nhỏ
- Mỗi phần là một nguyên mẫu có thể chạy được
- Khi các phần hoàn thành → ghép lại thành hệ thống thật
- Ưu điểm:
- Tiết kiệm thời gian
- Có thể kiểm thử từng phần
- Tránh viết lại toàn bộ
- Cần:
- Tổ chức mã cẩn thận
- Viết test tốt
- Có plan tích hợp từ đầu
Khi nào dùng throwaway, khi nào dùng incremental?
Mục đích | Nên chọn loại nào? |
---|---|
Khám phá yêu cầu mới | Throwaway |
Trình bày ý tưởng nhanh cho khách hàng | Throwaway |
Phát triển thật sự sản phẩm | Incremental |
Kiểm thử từng module | Incremental |
Bạn chưa chắc logic có đúng không | Throwaway |
Công cụ tạo prototype đơn giản
Dạng prototype | Công cụ gợi ý |
---|---|
Giao diện web | Figma, Adobe XD, Balsamiq |
Code nhanh | Python, NodeJS, PHP đơn giản |
Prototype class | VSCode, NetBeans, IntelliJ + mẫu code rỗng |
Những điều không nên khi dùng prototype
Sai lầm | Hậu quả |
---|---|
Dùng prototype tạm rồi “dán băng dính” thành hệ thống thật | Gây nợ kỹ thuật nghiêm trọng |
Viết prototype quá công phu | Lãng phí thời gian – mất tính thử nghiệm |
Không xác định mục tiêu prototype | Viết xong không biết dùng làm gì |
Ghi nhớ chương này
- Prototype là công cụ giúp bạn nghĩ bằng cách làm
- Có thể vứt bỏ (throwaway) hoặc phát triển tiếp (incremental)
- Giúp phát hiện lỗi thiết kế, hiểu người dùng, kiểm thử nhanh
- Hãy coi prototype như vòng trắc nghiệm trước khi lập trình chính thức
Từ sơ đồ lớp đế thực tế – Viết mã dựa trên thiết kế tĩnh
8.1. Sau sơ đồ, là lúc biến ý tưởng thành mã
Khi sơ đồ lớp đã ổn định:
- Các class đã xác định rõ
- Quan hệ giữa class đã rõ ràng
- Method đã được mô tả tên, đầu vào, đầu ra
👉 Giờ là lúc chuyển chúng thành các đoạn mã thật trong ngôn ngữ lập trình như Java, C#, PHP, Python…
🛠 8.2. Mục tiêu của bước triển khai này
Mục tiêu | Ý nghĩa |
---|---|
Dựng cấu trúc code ban đầu | Mỗi class = 1 file .java / .cs / .py… |
Khai báo các thuộc tính, method | Theo như thiết kế từ sơ đồ lớp |
Chưa cần viết logic đầy đủ | Chỉ cần khung chuẩn xác để xây tiếp |
🧪 8.3. Mã mẫu từ sơ đồ lớp – Ví dụ: Thư viện
📐 Sơ đồ lớp Library
(tóm tắt):
- Class:
Library
- Thuộc tính:
List<Book> allBooks
List<Patron> allPatrons
- Phương thức:
addBook(...)
removeBook(...)
addPatron(...)
getBook(...)
✍️ Mã C# tương ứng:
class Library
{
private List<Book> allBooks = new List<Book>();
private List<Patron> allPatrons = new List<Patron>();
public void AddBook(string isbn, string title, string author, string description)
{
// TODO: thêm logic thêm sách
}
public void RemoveBook(string isbn)
{
// TODO: tìm sách và xóa
}
public void AddPatron(string forename, string surname, string address)
{
// TODO: thêm người dùng
}
public Book GetBook(string isbn)
{
// TODO: tìm và trả về sách
return null;
}
}
💡 Các method trên chỉ là khung (stub) – logic sẽ được viết sau.
📦 8.4. Tương tự với các class còn lại
Bạn sẽ làm giống vậy với:
Book
Patron
Catalogue
Mỗi class:
- Có các thuộc tính (từ sơ đồ)
- Có method (tên, kiểu trả về, tham số)
- Giao tiếp với class khác qua biến thành viên hoặc truyền tham số
🔄 8.5. Những điều cần tinh chỉnh khi triển khai
Vấn đề trong sơ đồ | Cách xử lý khi viết code |
---|---|
List<Book> | Chọn ArrayList , List , Set tùy ngữ cảnh |
Quan hệ “has-a” | Tạo thuộc tính là class kia |
Quan hệ kế thừa | Dùng extends , : , hoặc khai báo interface |
Method “mơ hồ” | Bổ sung mô tả bằng comment TODO |
⚠️ 8.6. Lưu ý không nên làm
Không nên… | Vì… |
---|---|
Viết logic phức tạp quá sớm | Dễ lệch thiết kế, khó sửa |
Đổi tên class/method tùy tiện | Gây sai lệch giữa sơ đồ và code |
Bỏ qua những method nhỏ | Sẽ thiếu chức năng sau này |
Gộp nhiều class vào 1 file | Giảm tính tổ chức, khó bảo trì |
📌 8.7. Checklist khi hoàn tất bước này
✅ Tạo đủ class theo sơ đồ
✅ Tên class, method, thuộc tính nhất quán
✅ Mỗi class có ít nhất 1 phương thức chính
✅ Các quan hệ class được thể hiện bằng biến thành viên hoặc kế thừa
✅ Mỗi class là 1 file riêng (hoặc module riêng nếu dùng Python)
Ghi nhớ:
- Sơ đồ lớp là bản thiết kế – mã nguồn là ngôi nhà xây trên bản vẽ đó
- Việc chuyển sơ đồ lớp thành code nên được:
- Chính xác
- Tách biệt rõ ràng
- Có thể mở rộng
- Sau bước này, bạn đã có:
- Cấu trúc code đúng hướng đối tượng
- Đủ nền tảng để bắt đầu viết logic nghiệp vụ
- Nền móng cho việc kiểm thử (unit test)