Ngôn ngữ mô hình hóa thống nhất (UML) là một ký pháp chuẩn để mô hình hoá các hệ thống hướng đối tượng. Được giới thiệu với cộng đồng lập trình hướng đối tượng trong khoảng thời gian giữa các năm 1995 đến 1997, UML đã được OMG (Object Management Group - Tập đoàn Quản lý Đối tượng) phê duyệt vào cuối năm 1997. Mặc dù đã có nhiều tranh cãi khi khởi đầu -- nó đã được giới thiệu giữa một bầu không khí phản đối và phản đề nghị -- UML kể từ đó đã trở thành tiêu chuẩn công nghiệp dành cho ký pháp hệ thống. UML hiện là phiên bản 1.4 và tiếp tục tiến hoá để đáp ứng nhu cầu của các nhà phát triển hướng đối tượng. (Để biết thêm chi tiết về lịch sử của UML, xem Tài nguyên.)
UML có thể là khó học, chủ yếu do nó cố gắng đưa ra ký pháp mô hình hoá đối với một mảng rộng lớn đến thế các tình huống. Các ký pháp mô hình hoá đều dưới dạng sơ đồ, và hiện có chín sơ đồ trong đặc tả UML. Rất may là việc học UML có thể là một quá trình, chia thành các giai đoạn; bạn có thể chỉ học một sơ đồ mỗi lần, và bạn không cần phải ôm đồm toàn bộ những sự phức tạp của một sơ đồ trong nỗ lực đầu tiên của bạn.
Trong chuyên mục này, tôi sẽ dẫn dắt bạn qua quá trình thiết kế và ký pháp UML để phát triển ứng dụng dựa trên Java. Tôi sẽ giới thiệu những điểm cốt yếu về khung công tác UML và các công nghệ mô hình hoá khác theo một cách lôgic (và hy vọng là thú vị), và bạn sẽ học được các kinh nghiệm thực hành bằng các ví dụ mô hình hoá từ thế giới thực. Trong bài viết đầu tiên này, chúng ta sẽ bắt đầu với việc lập sơ đồ tuần tự, bằng cách sử dụng một ứng dụng xử lý vay nợ làm ví dụ. Xin lưu ý rằng tôi giả thiết bạn đã quen với ngôn ngữ Java và có một kiến thức cơ bản về các phương pháp và thuật ngữ phát triển hướng đối tượng. Các khái niệm hướng đối tượng sẽ được giải thích ngắn gọn, những thảo luận sâu hơn nằm ngoài phạm vi chuyên mục này.
UML không bài trừ bất kỳ phương pháp hay quy trình phát triển phần mềm đặc biệt nào; nó chỉ tiêu chuẩn hoá dạng thức ký pháp. Tuy nhiên, nhiều phương pháp phát triển lại kết hợp với UML. Một trong những phương pháp đó là Quy trình thống nhất Rational (RUP- Rational Unified Process); Một phương thức khác là phát triển theo đặc tính (FDD - feature-driven development). Các sơ đồ tuần tự UML, do bản chất trực giác và đa dụng linh hoạt của chúng, đã trở thành một phần không thể tách rời của các hoạt động mô hình hoá mặt trước của các quy trình này. Sơ đồ tuần tự được sử dụng để mô hình hoá các thứ sau đây:
- Các kịch bản ca sử dụng
- Các giao thức trong một khung công tác
- Các hệ thống con
- Các lớp
- Lôgic của phương thức
Giải thích sơ lược về từng chức năng nói trên đây sẽ được trình bày theo thứ tự.
Đối với ứng dụng mẫu của chúng ta, chúng ta sẽ sử dụng các sơ đồ tuần tự để mô hình hoá một kịch bản ca sử dụng. Ca sử dụng là một nhiệm vụ đơn lẻ được thực hiện bởi một tác nhân khi tương tác với ứng dụng của bạn nhằm đến một mục tiêu đã chỉ rõ. Một tác nhân là bất kỳ người sử dụng cuối cùng nào, tổ chức nào, hay hệ thống nào mà tương tác với, nhưng lại ở bên ngoài, ứng dụng của bạn. (Xem phần Về các cá thể tác nhân để tìm hiểu về bốn cá thể tác nhân; để nhận được thảo luận sâu hơn về các kịch bản ca sử dụng, xin xem phần Tài nguyên.)
Các giao thức trong một khung công tác
Một giao thức được đặt giữa một khung công tác và các thành phần có thể thay thế lẫn nhau được gọi là các quần thể (ensembles). Việc hiểu biết về các tương tác mà một khung công tác đòi hỏi sẽ giúp đỡ cho việc phát triển các quần thể mới. Sơ đồ tuần tự thường được sử dụng để làm tư liệu dẫn chứng cho các tương tác này.
Các dự án lớn được phân chia thành các mảnh nhỏ hơn, dễ quản lý hơn gọi là các hệ thống con. Các giao diện giữa các hệ thống con là rất quan trọng đối với việc tích hợp đúng đắn chúng vào cái tổng thể lớn hơn, đó là hệ thống. Sơ đồ tuần tự được sử dụng để xác định tương tác giữa các lớp trên biên giới của các hệ thống con.
Một số lớp (như Socket và
InetAddress) đòi hỏi một chuỗi tuần tự phức tạp
các lời gọi phương thức để tương tác một cách thích hợp. Các chuỗi tuần tự
này tạo ra các giao thức để tương tác với một lớp hoặc tập hợp các lớp như
vậy. Sơ đồ tuần tự có thể được sử dụng để mô tả việc sử dụng một lớp hoặc
nhóm các lớp tương tác với nhau, bằng cách đó mô tả các giao thức cần
thiết để tương tác.
Các sơ đồ tuần tự là tuyệt vời để làm tư liệu dẫn chứng cho logic của phương thức. Trên thực tế, một số công cụ CASE, khi cho trước một phương thức Java, sẽ tự động tạo ra một sơ đồ tuần tự. Việc lập sơ đồ tuần tự có thể dùng để thiết kế một phương thức trong tương lai hoặc để làm tư liệu dẫn chứng cho dòng xử lý của một phương thức hiện hành.
Chúng ta sẽ tìm hiểu về cách lập sơ đồ tuần tự với sự giúp đỡ của một ứng dụng xử lý vay nợ mẫu. Do chuyên mục này tập trung vào việc mô hình hoá, không phải là vào phương thức, chúng ta cần đi thẳng vào việc lập sơ đồ, như vậy chúng ta sẽ vẫn để các chi tiết của ứng dụng khá lỏng lẻo. Các chức năng căn bản mà chúng ta sẽ lập sơ đồ cho ứng dụng xử lý vay nợ như sau:
Ca sử dụng: Nộp yêu cầu vay nợ (Submit loan request)
- Một người đứng đơn hoàn tất và trình nộp một đơn xin vay nợ qua Internet tới ngân hàng.
- Hệ thống kiểm tra tính hợp lệ của thông tin trên đơn xin vay, kiểm tra xem nó đã chính xác và đầy đủ nhất chưa.
- Hệ thống chuyển tiếp yêu cầu vay tiền đến một phòng tín dụng bên ngoài để nhận được một báo cáo tín dụng của người đứng đơn.
- Hệ thống tính toán điểm số tín dụng của người đứng đơn dựa trên báo cáo tín dụng đã trả về.
Bước đầu tiên để tạo ra một sơ đồ tuần tự là xác định xem sơ đồ đó có biểu diễn một tương tác với một thực thể bên ngoài hay bên trong hệ thống. Nếu bạn đang mô hình hoá một kịch bản ca sử dụng, các sơ đồ tuần tự của bạn thường sẽ biểu diễn một tương tác với một thực thể bên ngoài. Nếu bạn đang mô hình hoá các giao thức trong một khung công tác, các sơ đồ này có thể biểu diễn một tương tác bên ngoài hoặc bên trong. Các sơ đồ cho các hệ thống con, các lớp, và logic của một phương thức riêng lẻ thường chỉ biểu diễn các thực thể bên trong. Dù đó là trường hợp nào thì kiểu tương tác mà bạn đang mô hình hoá sẽ xác định phần tử đầu tiên (và ở ngoài cùng bên trái) trong sơ đồ tuần tự đó.
Một tương tác với một thực thể bên ngoài chỉ rõ rằng một tác nhân sẽ là một
bên của tương tác đó. Một tương tác bên trong có thể được một tác nhân
kích hoạt (nếu các ca sử dụng hệ thống con là cơ sở của tương tác), nhưng
rất có thể nó sẽ được kích hoạt bởi một lớp chung gọi là
Sender (bên gửi). Nếu một tác nhân khởi động
tương tác này, tác nhân đó sẽ rơi vào loại hình tác nhân khởi tạo, một
trong bốn cá thể tác nhân phổ biến (xin xem Về các cá thể tác nhân
(About actor personalities) để biết thêm chi
tiết).
Chúng ta sẽ tập trung vào việc lập sơ đồ một kịch bản cho ứng dụng xử lý
vay nợ của chúng ta: đó là ca sử dụng nộp yêu cầu vay nợ phác thảo
trên đây. Hãy chú ý tới các thay đổi với sơ đồ tuần tự của chúng ta khi
một người đứng đơn hoàn tất một đơn vay tiền trực tuyến và trình nộp nó
trên Internet. Trong kịch bản này, người đứng đơn là bên ngoài so với hệ
thống và do đó được đại diện bởi một tác nhân. Chúng ta sẽ bắt đầu bằng
cách thêm tác nhân này, Applicant, vào sơ đồ,
như trong Hình 1.
Hình 1. Thêm vào người đứng đơn
Khi tác nhân khởi tạo của tương tác đã sẵn sàng, bước tiếp theo là thêm vào các đối tượng mà tác nhân này sẽ tương tác với chúng theo diễn biến của kịch bản. Tên của các đối tượng này sẽ phản ánh hành vi của các lớp hay cá thể. (Việc lựa chọn các lớp hay chọn cá thể đối tượng mang lại một ý nghĩa riêng biệt cho sơ đồ tuần tự, nhưng tôi sẽ để dành lại việc thảo luận về sự khác biệt giữa hai lựa chọn đó cho lần sau).
Đối với kịch bản mẫu, chúng ta sẽ thêm vào hai lớp:
LoanApplication và
LoanRequest. Một đơn xin vay tiền là bắt buộc
phải có khi xin vay tiền. Nó chứa thông tin về người làm đơn và khoản tiền
muốn vay. Một yêu cầu vay tiền là một mẫu biểu ngân hàng gửi đến một phòng
tín dụng sau khi nhận được đơn xin vay tiền. Nó chứa một số thông tin từ
đơn xin vay tiền, cũng như một yêu cầu nhận các thông tin về lịch sử tín
dụng của người đứng đơn. Việc thêm hai lớp này vào sơ đồ tuần tự được thể
hiện trong Hình 2.
Hình 2. Thêm vào hai lớp tương tác
Nối các nét chấm -- , nét gạch
Các sơ đồ tuần tự có tính trực giác đối với hầu hết các nhà phát triển phần mềm. Chúng ánh xạ các đối tượng và các tác nhân (trục ngang) với thời gian (trục đứng). Các thông điệp kết nối các đối tượng, đi từ đối tượng này đến đối tượng khác xuôi xuống theo trục đứng như khi các thông điệp xuất hiện theo thời gian. Các thông điệp này được nối với một đường thẳng đứng, nét đứt, bắt nguồn từ điểm giữa đáy của đối tượng hay tác nhân. Đường này gọi là dây treo (lifeline). (N.D: không biết có phải người đặt ra thuật ngữ này dựa vào một liên tưởng khá bất ngờ sau đây hay không? Những người làm việc trên cao phải đeo một dây an toàn móc ở thắt lưng, buông thõng xuống theo chiều thẳng đứng, nó gọi là (lifeline)).
Trên trục ngang, chúng ta biểu diễn thông điệp bằng các mũi tên đôi khi gọi
là các mũi tên cuộc gọi hay mũi tên thông điệp. Một mũi tên
thông điệp hướng từ bên gửi (đuôi) đến bên nhận (đầu). Các mũi tên này sử
dụng bắt giữ hành vi động của hệ thống. Các cuộc gọi thường bắt đầu từ bên
trái và đi về hướng bên phải. Nghĩa là, mũi tên ban đầu trong một tương
tác thường đến từ bên trái. Khi chúng ta tạo ra một cá thể mới của một
lớp, chúng ta vẽ mũi tên trỏ đến chính lớp đó chứ không phải là đến dây
treo của nó. Bước đầu tiên trong kịch bản của chúng ta là tạo ra một đơn
xin vay tiền mới, vì vậy chúng ta sẽ vẽ một mũi tên giữa
Applicant và
LoanApplication. Bởi vì việc tạo ra một cá thể
mới trong Java bao gồm việc gọi hàm tạo (constructor), chúng ta có thể gán
nhãn mũi tên này bằng tên hàm tạo và có thể gồm cả các đối số của nó.
Chúng ta vẫn đang trong giai đoạn phân tích của vòng đời phát triển phần
mềm, vì vậy chúng ta cần bao gồm thêm thông tin phân tích càng nhiều càng
tốt. Một trong những nhà phân tích nghiệp vụ của chúng ta đã nói rằng
chúng ta gọi hành động tạo ra một đơn xin vay tiền mới là "hoàn tất đơn
xin vay". Nếu chúng ta muốn thật sát đúng đối với sơ đồ tuần tự đang xây
dựng này, chúng ta có thể triển khai thực hiện
complete như là một phương thức tĩnh công cộng
(public static), trong đó sẽ gọi hàm tạo
LoanApplication như Hình 3.
Hình 3. Tạo ra LoanApplication
Khi một lớp hoặc cá thể nhận được một thông điệp, nó tạo ra một hộp trên dây treo của đối tượng tiếp nhận; việc này gọi là một kích hoạt.Một kích hoạt biểu diễn dòng điều khiển trong phương thức của bên nhận. Khi một thông điệp dẫn đến việc tạo ra một đối tượng, kích hoạt đầu tiên biểu diễn cho logic của hàm tạo. Các thông điệp sau đó sẽ dẫn đến việc tạo ra các kích hoạt mới.
Sau khi nhận được một thông điệp, đối tượng nhận có thể, đến lượt mình, gửi các thông điệp đến chính nó hoặc đến các đối tượng khác. Điều này thể hiện bằng đuôi của các mũi tên, trình bày các thông điệp xuất phát từ kích hoạt đó và kết thúc tại các kích hoạt mới. Khi một đối tượng gọi chính nó, kích hoạt mới được đặt lên trên kích hoạt cũ.
Trong kịch bản của chúng ta, người đứng đơn tương tác với đơn xin vay tiền
hai lần, đầu tiên là để hoàn tất nó, và lần thứ hai là để gửi nộp. Khi
LoanApplication nhận được thông điệp
submit nó tự kiểm tra hợp lệ bằng cách gửi một thông điệp
validate đến chính nó. Nếu hợp lệ, nó sẽ tạo ra một
LoanRequest mới để gửi đến phòng tín dụng. Hình
4 cho thấy việc kiểm tra hợp lệ
LoanApplication.
Hình 4. Kiểm tra hợp lệ LoanApplication
Khi mũi tên bay: Cho biết thời gian trôi qua
Chúng ta sử dụng một mũi tên nghiêng để biểu thị đã trôi qua một quãng thời gian đáng kể giữa khoảng thời gian một thông điệp được gửi đi và thời gian nó được tiếp nhận. Ký pháp này sử dụng để cho biết rằng một cuộc gọi không phải là nguyên tử (N.D: tức là có thể phân chia được). Ví dụ về các cuộc gọi không nguyên tử là các lời gọi phương thức thông qua CORBA hoặc RMI, hoặc các thông điệp gửi qua mạng.
Trong ví dụ của chúng ta, phòng tín dụng là một hệ thống bên ngoài, một tác nhân có cá thể máy chủ (xin xem Về các cá thể tác nhân để biết thêm chi tiết). Các máy chủ thường không phát ra thông điệp, mà đúng hơn là yêu cầu thông điệp gửi đến chúng -- trong trường hợp này là yêu cầu về một báo cáo tín dụng, được gửi bởi bộ kiểm tra tín dụng. Bộ kiểm tra tín dụng đại diện cho phòng tín dụng. Nó theo dõi và chuyển tiếp các yêu cầu đến phòng tín dụng, theo dõi và nhận phản hồi, và mặt khác thiết lập các kết nối giữa ứng dụng xử lý vay nợ và phòng tín dụng. Phòng tín dụng sẽ nhận yêu cầu này và xử lý nó theo lịch biểu riêng của mình. Chúng ta sử dụng mũi tên nghiêng này để biểu diễn thời gian trôi qua, như Hình 5 dưới đây.
Khi kết thúc một kích hoạt, phần trả về cho bên gọi là ẩn. Tuy nhiên, trong
một số trường hợp, bạn có thể muốn làm cho phần trả về hiện ra tường minh.
Các lời gọi trả về tường minh được thể hiện bằng một mũi tên nét đứt có
đuôi là bên nhận và đầu là bên gửi. Mũi tên trả lại tường minh thường được
gắn nhãn bằng giá trị mà cuộc gọi trả về. Đối với ví dụ của chúng ta,
chúng ta đã thêm vào một mũi tên tường minh giữa
CreditBureau và
CreditChecker. Mũi tên này có thể được gắn nhãn
CreditReport, vì đó là đối tượng được trả lại
từ phương thức requestCreditReport.
Hình 5. Nhận một CreditReport
Còn những gì nữa
Như tôi đã nêu ở phần đầu chuyên mục này, các
sơ đồ tuần tự là hữu ích đối với việc mô tả hành vi bên trong của một hệ
thống theo thời gian. Trong bài viết này, tôi đã đưa bạn qua các bước đầu
tiên của việc xây dựng sơ đồ tuần tự bằng việc mô hình hoá các tương tác
giữa các đối tượng. Trong phần tiếp theo, tôi sẽ giới thiệu hai dạng sơ đồ
tuần tự (chung và cá thể) và giải thích vai trò của logic điều kiện trong
việc lập sơ đồ tuần tự, bằng cách sử dụng các ví dụ rút ra từ các phương
thức Java đơn giản. Hẹn gặp bạn sau!
- Martin Fowler (tác giả của
UML Distilled)
đưa ra
một cái
nhìn của người trong cuộc
về lịch sử khởi đầu của UML.
- Nếu bạn nghiêm túc muốn tìm hiểu về UML bạn nên bắt đầu bằng bài viết
gốc của ba người bạn (Booch, Jacobson, Rumbaugh):
Hướng dẫn
sử dụng Ngôn ngữ Mô hình hoá thống nhất
(loạt bài về Công nghệ Đối tượng của Addison Wesley, 1998).
- Tiếp theo trong danh sách cốt yếu cần đọc là
Đặc tả Ngôn ngữ
Mô hình hoá thống nhất
của OMG (bản 1.4 tính đến 02.2001).
- Trang Tài nguyên UML
của Rational cung cấp thông tin hiện tại về UML, RUP, và nhiều thứ
nữa.
- Một cuốn sách đáng đọc về phát triển theo đặc tính và Quy trình thống
nhất của Rational là
Mô hình hoá Java với màu sắc bằng UML
(Java Modeling in Color with UML) của Peter Coad, Eric Lefebvre, Jeff
DeLuca (Prentice Hall, 1999).
- • Một cuốn sách tốt nữa về RUP là
Quy trình thống nhất của Rational: Bài giới thiệu của
của Philippe Kruchten (Addison Wesley, 2000).
Granville có 13 năm kinh nghiệm trong cộng đồng hướng đối tượng. Ông là đồng tác giả của loạt bài Advanced Use Case Modeling (Mô hình hoá ca sử dụng nâng cao) và đã trình bày các bài hướng dẫn tại nhiều hội nghị công nghệ hướng đối tượng trên toàn thế giới. Cách tiếp cận thực hành đến việc phát triển hướng đối tượng của ông là kết quả quá trình làm việc của ông với các công ty, từ công ty khởi đầu trong giai đoạn non trẻ đến một số những người khổng lồ phần mềm tiếng tăm nhất. Ông hiện đang giảng dạy các xê mi na, phiên hướng dẫn, các lớp học về quy trình và phương pháp luận phát triển lanh lợi (agile), công nghệ Java, cũng như cố vấn và giúp đỡ để cung cấp các dự án năng nổ.