Từ Edge Rational: Bài viết này giới thiệu sơ đồ thành phần, một sơ đồ cấu trúc trong các đặc tả kỹ thuật mới của Ngôn ngữ mô hình hoá thông nhất (Unified Modeling Language), phiên bản 2.0

Donald Bell, Chuyên gia IT, IBM

Donald Bell là một chuyên gia IT tại bộ phận Dịch vụ Toàn cầu IBM, nơi ông làm việc với các khách hàng của IBM để thiết kế và phát triển J2EE dựa trên các giải pháp phần mềm



26 03 2010

IllustrationĐây là bài viết tiếp theo trong loạt các bài viết về các sơ đồ chủ yếu được sử dụng trong ngôn ngữ mô hình hóa thống nhất, hay UML. Trong bài viết trước đây của mình về sơ đồ lớp của UML, (Rational Edge, tháng Chín, 2004), tôi đã mô tả tập hợp ký pháp của sơ đồ lớp là cơ sở cho tất cả các sơ đồ cấu trúc của UML 2 như thế nào. Tiếp tục bàn về sơ đồ cấu trúc của UML 2, bài viết này giới thiệu sơ đồ thành phần.

Mục đích của sơ đồ

Mục đích chính của sơ đồ thành phần là để hiển thị các mối quan hệ cấu trúc giữa các thành phần của một hệ thống. Trong UML 1.1, một thành phần biểu diễn các hạng mục triển khai thực hiện, chẳng hạn như các tệp tin và các tệp thi hành được. Thật không may, điều này lại xung đột với cách sử dụng phổ biến hơn của thuật ngữ thành phần, để nói đến những thứ như các thành phần COM (Component Object Model - mô hình đối tượng thành phần). Với thời gian và sau nhiều lần phát hành kế tiếp của UML, ý nghĩa ban đầu của UML về các thành phần bị mất đi hầu hết. UML 2 đã chính thức thay đổi ý nghĩa chủ yếu của khái niệm thành phần; trong UML 2, các thành phần được xem là các đơn vị có tính tự trị, được gói gọn trong một hệ thống hoặc hệ thống con mà cung cấp một hoặc nhiều giao diện. Mặc dù đặc tả kỹ thuật của UML 2 không tuyên bố nghiêm ngặt điều này, nhưng các thành phần là các đơn vị thiết kế lớn hơn, biểu diễn những thứ thông thường sẽ được thực hiện bằng cách sử dụng các mô đun thay thế được". Nhưng, không giống như UML 1.x, bây giờ các thành phần hoàn toàn là các cấu kiện lôgic trong khi thiết kế. Ý tưởng là bạn có thể dễ dàng tái sử dụng và/hoặc thay thế bản triển khai thực hiện thành phần khác trong các thiết kế của bạn vì một thành phần gói gọn hành vi và thực hiện các giao diện đã quy định.1

Trong việc phát triển dựa trên thành phần (CBD - Component-based development), các sơ đồ thành phần cung cấp cho các kiến trúc sư một định dạng tự nhiên để bắt đầu mô hình hoá một giải pháp. Các sơ đồ thành phần cho phép một kiến trúc sư xác minh rằng các chức năng cần có của một hệ thống đang được thực hiện bởi các thành phần, như vậy bảo đảm rằng hệ thống cuối cùng sẽ được chấp nhận.

Ngoài ra, các sơ đồ thành phần là các công cụ trao đổi thông tin hữu ích cho các nhóm khác nhau. Các sơ đồ có thể được xuất trình cho các bên tham gia dự án then chốt và các nhân viên thực hiện. Trong khi sơ đồ thành phần thường được hướng tới các nhân viên thực hiện của một hệ thống, thì sơ đồ thành phần cũng thường làm cho bên liên quan cảm thấy thoải mái bởi vì các sơ đồ thể hiện sự hiểu biết sớm về hệ thống tổng thể đang được xây dựng.

Các nhà phát triển phần mềm thấy rằng sơ đồ thành phần rất hữu ích vì nó cung cấp cho họ một khung nhìn về mặt kiến trúc, ở mức cao về hệ thống mà họ sẽ xây dựng, nó giúp các nhà phát triển bắt đầu chính thức hóa một lộ trình thực hiện, và đưa ra quyết định về phân bổ nhiệm vụ và/hoặc cải tiến các kỹ năng cần thiết . Các nhà quản trị hệ thống thấy rằng sơ đồ thành phần rất hữu ích, vì họ có được một khung nhìn sớm về những thành phần phần mềm lôgic sẽ được chạy trên hệ thống của mình. Mặc dù các quản trị viên hệ thống sẽ không có khả năng xác định các máy vật lý nào hay các tệp thi hành được nào từ sơ đồ, sơ đồ thành phần vẫn sẽ được chào đón bởi vì nó cung cấp thông tin sớm về các thành phần và các mối quan hệ của chúng (cho phép các quản trị viên hệ thống lập trước một kế hoạch một cách sơ bộ).


Ký pháp

Bây giờ tập hợp các ký pháp của sơ đồ thành phần làm cho nó trở thành một trong những sơ đồ UML dễ vẽ nhất. Hình 1 là một sơ đồ thành phần đơn giản, sử dụng ký pháp của UML phiên bản 1.4 trước đây; ví dụ cho thấy một mối quan hệ giữa hai thành phần: Thành phần Order System (Hệ thống đơn đặt hàng) sử dụng thành phần Inventory System (Hệ thống kiểm kê). Như bạn có thể thấy, một thành phần trong UML 1.4 được vẽ bằng một hình chữ nhật với hai hình chữ nhật nhỏ nhô ra từ phía bên trái của nó.

Figure 1

Hình 1: Sơ đồ thành phần đơn giản này cho thấy các phụ thuộc chung của thành phần Order System bằng cách sử dụng ký pháp của UML 1.4

Ký pháp UML 1.4 ở trên vẫn còn được hỗ trợ trong UML 2. Tuy nhiên, tập hợp ký pháp của UML 1.4 không phù hợp trong một hệ thống lớn hơn. Vì lý do đó, UML 2 cải tiến căn bản tập hợp ký pháp của sơ đồ thành phần, như chúng ta sẽ thấy trong suốt phần còn lại của bài viết này. Tập hợp ký pháp của UML 2 phù hợp hơn, và các ký pháp cũng mang lại nhiều thông tin hơn trong khi vẫn duy trì tính dễ hiểu.

Chúng ta hãy xem lần lượt các thành phần cơ sở của sơ đồ thành phần trong UML 2.


Các thành phần cơ sở

Bây giờ việc vẽ một thành phần trong UML 2 rất giống với vẽ một lớp trong một sơ đồ lớp. Thực vậy, trong UML 2 một thành phần chỉ là một phiên bản chuyên biệt của khái niệm lớp. Điều đó có nghĩa là các quy tắc ký pháp được áp dụng cho phân loại (classifier) lớp cũng được áp dụng cho phân loại thành phần. (Nếu bạn đã đọc và hiểu bài viết trước của tôi tại địa chỉ [http://www.ibm.com/developerworks/vn/bell/index.html] về sơ đồ cấu trúc nói chung, và về sơ đồ lớp nói riêng, thì bạn đã sẵn sàng để hiểu được sơ đồ thành phần.)

Trong UML 2, một thành phần được vẽ bằng một hình chữ nhật với các ngăn tùy chọn được xếp chồng lên nhau theo chiều dọc. Khung nhìn ở mức cao, trừu tượng hoá của một thành phần trong UML 2 có thể được mô hình hoá chỉ bằng một hình chữ nhật với tên của thành phần và nhãn chữ của bản mẫu thành phần (stereotype's text) và/hoặc một biểu tượng. Nhãn chữ của bản mẫu thành phần là «component» và biểu tượng của thành phần là một hình chữ nhật với hai hình chữ nhật nhỏ nhô ra bên trái của nó (yếu tố ký pháp của UML 1.4 cho một thành phần). Hình 2 cho thấy ba cách khác nhau có thể để vẽ một thành phần, sử dụng đặc tả UML 2.

Figure 2

Hình 2: Các cách khác nhau để vẽ một ngăn chứa tên của một thành phần

Khi vẽ một thành phần trên một sơ đồ, điều quan trọng là bạn phải luôn luôn điền nhãn chữ của bản mẫu thành phần (chữ <<component>> nằm ở bên trong cặp dấu ngoặc góc, như trong hình 2) và/hoặc biểu tượng của thành phần. Lý do tại sao ta phải làm như vậy? Trong UML thì hình chữ nhật không có bất kỳ nhãn chữ của bản mẫu thuộc phân loại nào sẽ được diễn giải như là phần tử lớp. Các nhãn chữ của bản mẫu và/hoặc biểu tượng sẽ phân biệt hình chữ nhật này như là một phần tử thành phần.

Mô hình hóa các giao diện được cung cấp/ được yêu cầu của một thành phần

Tất cả các thành phần Order (Đơn hàng) được vẽ trong hình 2 biểu diễn các phần tử ký pháp hợp lệ, tuy nhiên, một sơ đồ thành phần tiêu biểu bao gồm nhiều thông tin hơn. Một phần tử thành phần có thể có các ngăn bổ sung được xếp chồng lên nhau ở bên dưới ngăn tên. Như tôi đã đề cập trước đây, một thành phần là một đơn vị tự trị, cung cấp một hoặc nhiều giao diện công cộng. Các giao diện được cung cấp biểu diễn các hợp đồng dịch vụ chính thức mà thành phần cung cấp cho người tiêu dùng/trình khách của nó. Hình 3 cho thấy thành phần Order có ngăn thứ hai biểu thị những giao diện nào mà thành phần Order cung cấp và yêu cầu. 2

Figure 3

Hình 3: Ngăn bổ sung ở đây cho thấy các giao diện mà thành phần Order cung cấp và yêu cầu.

Trong ví dụ về thành phần Order trong hình 3, thành phần này cung cấp các giao diện OrderEntry và AccountPayable. Ngoài ra, thành phần đó cũng yêu cầu thành phần khác cung cấp cho nó giao diện Person (người).3

Các tiếp cận khác để mô hình hoá các giao diện của một thành phần

Một cách tiếp cận khác để mô hình hóa các giao diện của một thành phần UML 2 cũng đã giới thiệu một cách khác để hiển thị các các giao diện được cung cấp và được yêu cầu của một thành phần. Cách thứ hai này là vẽ một hình chữ nhật duy nhất, với tên của thành phần trong hình chữ nhật đó, và đặt vào cái mà đặc tả kỹ thuật của UML 2 gọi là ký hiệu giao diện, nối với bên ngoài của hình chữ nhật. Cách tiếp cận thứ hai được minh hoạ trong hình 4.

Figure 4

Hình 4: Một cách tiếp cận khác (so sánh với hình 3) để hiển thị các giao diện được cung cấp/được yêu cầu của một thành phần bằng cách sử dụng các ký hiệu giao diện

Trong phương pháp tiếp cận thứ hai, các ký hiệu giao diện với một vòng tròn đầy đủ ở một đầu, biểu diễn một giao diện mà thành phần cung cấp - biểu tượng chiếc kẹo que này là hình tốc ký (rút gọn) cho một mối quan hệ nhận biết của một phân loại là giao diện. Ký hiệu giao diện với nửa vòng tròn tại một đầu của nó (cũng gọi là ổ cắm) biểu diễn một giao diện mà thành phần này yêu cầu (trong cả hai trường hợp, tên của giao diện được đặt gần chính ký hiệu giao diện đó). Mặc dù hình 4 trông rất khác với hình 3, thì cả hai hình cung cấp cùng một thông tin - tức là thành phần Order cung cấp hai giao diện: OrderEntry và AccountPayable, và thành phần Order yêu cầu giao diện Person.

Mô hình hóa các mối quan hệ của một thành phần

Khi hiển thị các mối quan hệ của một thành phần với các thành phần khác, thì ký pháp chiếc kẹo que và hình ổ cắm cũng phải bao gồm một mũi tên phụ thuộc (như được sử dụng trong sơ đồ lớp). Trên một sơ đồ thành phần với hình kẹo que và ổ cắm, bạn lưu ý rằng mũi tên phụ thuộc đi ra từ ổ cắm tiêu thụ (yêu cầu) và đầu mũi tên của nó nối với hình kẹo que của nhà cung cấp, như trong hình 5.

Figure 5

Hình 5: Một sơ đồ thành phần cho thấy thành phần Order System phụ thuộc vào thành phần khác như thế nào

Hình 5 cho thấy thành phần Order System phụ thuộc vào cả hai thành phần Customer Repository và Inventory System. Trong hình 5 hãy lưu ý các tên trùng lặp của các giao diện CustomerLookup và ProductAccessor. Nếu ở ví dụ này, sự lặp lại có vẻ là không cần thiết, thì ký pháp này thực sự cho phép có các giao diện khác (và với tên gọi khác đi) trên mỗi thành phần, phụ thuộc vào sự khác biệt của từng bản triển khai thực hiện (ví dụ: một thành phần cung cấp một giao diện là một lớp con của một giao diện nhỏ hơn được yêu cầu).

Các hệ thống con

Trong UML 2 phân loại hệ thống con là một phiên bản chuyên biệt của phân loại thành phần. Với lý do đó, các phần tử ký pháp của hệ thống con kế thừa tất cả các quy tắc như các phần tử ký pháp thành phần. Sự khác biệt duy nhất là phần tử ký pháp của hệ thống con dùng từ khóa subsystem (hệ thống con) thay vì component (thành phần), như thấy trong hình 6.

Figure 6

Hình 6: Một ví dụ về phần tử hệ thống con

Đặc tả kỹ thuật của UML 2 khá mơ hồ về việc một hệ thống con khác với một thành phần như thế nào. Từ phối cảnh mô hình hoá, đặc tả kỹ thuật không xử lý khác nhau chút nào khi đó là một thành phần hay là một hệ thống con. So với UML 1.x, sự lập lờ về mô hình hoá này của UML 2 là một điều mới. Nhưng có lý do của nó. Trong UML 1.x, hệ thống con được coi là một gói, và ký pháp của gói này đã gây nhầm lẫn cho nhiều người thực hành; do đó UML 2 đã xếp hệ thống con như là một thành phần chuyên biệt, vì rằng đây là cách mà phần lớn những người sử dụng UML 1.x hiểu về nó. Sự thay đổi này làm cho bức tranh trở nên có tính mờ, nhưng tính mờ này là một sự phản ánh thực tế nhiều hơn, chứ không phải là lỗi trong đặc tả kỹ thuật của UML2.

Vì vậy, ngay bây giờ bạn có thể gãi đầu tự hỏi khi nào thì sử dụng một phần tử thành phần thay cho một phần tử hệ thống con. Thành thật mà nói, tôi không có câu trả lời ngay cho bạn. Tôi có thể nói với bạn rằng các đặc tả kỹ thuật của UML 2 nói rằng quyết định khi nào thì sử dụng một thành phần thay cho một hệ thống con là tuỳ thuộc vào phương pháp luận của nhà tạo mô hình. Cá nhân tôi thích câu trả lời này vì nó giúp đảm bảo rằng UML là độc lập về phương pháp luận, giữ cho nó có thể được sử dụng mọi nơi trong việc phát triển phần mềm.


Ngoài những điều cơ sở

Sơ đồ thành phần là một trong những sơ đồ dễ hiểu hơn cả, do đó không có gì nhiều để thảo luận ngoài những điều cơ sở. Tuy nhiên, có một điểm mà bạn có thể xem xét kỹ hơn một chút.

Hiển thị cấu trúc bên trong của một thành phần

Sẽ có những lúc việc hiển thị cấu trúc bên trong của một thành phần trở nên có ý nghĩa. Trong bài viết trước của tôi về sơ đồ lớp, tôi đã chỉ ra cách làm thế nào để mô hình hoá cấu trúc bên trong của một lớp; ở đây tôi sẽ tập trung vào cách làm thế nào để mô hình hoá cấu trúc bên trong của một thành phần khi nó bao gồm các thành phần khác.

Để hiển thị cấu trúc bên trong của một thành phần, bạn chỉ đơn thuần là vẽ những thành phần lớn hơn bình thường và đặt các bộ phận bên trong của nó bên trong ngăn chứa tên của thành phần bao chứa. Hình 7 cho thấy cấu trúc bên trong của thành phần Store (kho hàng).

Figure 7

Hình 7: Cấu trúc bên trong của thành phần này bao gồm các thành phần khác.

Sử dụng ví dụ trong hình 7, thành phần Store cung cấp giao diện OrderEntry và yêu cầu giao diện Account (tài khoản). Thành phần Store được tạo ra từ ba phần thành: Order (Đơn đặt hàng), Customer (Khách hàng) và Product (Sản phẩm). Hãy lưu ý rằng các ký hiệu giao diện OrderEntry và Account của thành phần Store có một hình vuông trên cạnh của thành phần này. Hình vuông này được gọi là cổng. Nói theo cách đơn giản, các cổng cung cấp một cách để mô hình hóa các giao diện được cung cấp/được yêu cầu liên hệ với các bộ phận bên trong của nó như thế nào.4 Bằng cách sử dụng cổng, sơ đồ của chúng ta có thể tách các bộ phận bên trong của thành phần Store khỏi các thực thể bên ngoài. Trong hình 7, cổng OrderEntry uỷ thác việc xử lý cho giao diện OrderEntry của thành phần Order. Ngoài ra giao diện Account được yêu cầu của thành phần Customer bên trong được uỷ thác đến cổng giao diện Account được yêu cầu của thành phần Store. Bằng cách kết nối tới cổng Account, các thành phần bên trong của thành phần Store (Ví dụ như thành phần Customer) có thể có một biểu diễn nội bộ của một số thực thể bên ngoài chưa được biết, mà chúng sẽ thực hiện giao diện của cổng. Giao diện Account được yêu cầu sẽ được thực hiện bởi một thành phần bên ngoài của thành phần Store. 5

Bạn cũng nhận thấy trong hình 7 rằng các kết nối lẫn nhau giữa các thành phần bên trong khác với những kết nối được thể hiện trong hình 5. Đó là do những miêu tả cấu trúc bên trong ấy thực sự là các sơ đồ hợp tác được lồng bên trong phân loại (là một thành phần trong trường hợp của chúng ta), vì rằng sơ đồ hợp tác hiển thị các cá thể hoặc vai trò của các phân loại. Mối quan hệ được mô hình hoá giữa các thành phần bên trong được vẽ bằng những cái mà UML gọi là bộ nối lắp ráp (assembly connector). Bộ nối lắp ráp gắn kết một giao diện được cung cấp của một thành phần với một giao diện được yêu cầu của một thành phần khác. Các bộ nối lắp ráp được vẽ bằng các ký hiệu chiếc kẹo que và ổ cắm ở bên cạnh nhau. Việc vẽ các bộ nối lắp ráp theo cách này làm cho các biểu tượng kẹo que và ổ cắm trở nên rất dễ đọc.


Kết luận

Sơ đồ thành phần là một sơ đồ rất quan trọng mà các kiến trúc sư sẽ thường tạo ra sớm trong một dự án. Tuy nhiên, tính hữu dụng của sơ đồ thành phần kéo dài suốt cuộc đời của một hệ thống. Sơ đồ thành phần là vô giá vì chúng tạo mô hình và cung cấp tư liệu cho kiến trúc của một hệ thống. Vì rằng sơ đồ thành phần cung cấp tư liệu cho kiến trúc của hệ thống, nên các nhà phát triển và nhà quản trị hệ thống sau này của hệ thống thấy rằng sản phẩm này là trọng yếu trong việc giúp cho họ hiểu được hệ thống.

Sơ đồ thành phần cũng phục vụ như là đầu vào của sơ đồ triển khai một hệ thống phần mềm, đây sẽ là chủ đề của phần tiếp theo trong loạt bài viết này của tôi.


Ghi chú

1 Các hạng mục vật lý mà UML1.x gọi là thành phần hiện nay được gọi là "các tạo phẩm" trong UML 2. Một tạo phẩm là một đơn vị vật lý, chẳng hạn như một tập tin, một tệp thực thi, kịch bản lệnh, cơ sở dữ liệu, vv…. Chỉ có các tạo phẩm tồn tại trên các nút vật lý; các lớp và các thành phần không có "vị trí" của mình. Tuy nhiên, một tạo phẩm có thể biểu hiện các thành phần và các phân loại khác (tức là các lớp). Một thành phần duy nhất có thể được biểu hiện bằng nhiều tạo phẩm, các tạo phẩm này có thể ở trên cùng một nút hoặc trên các nút khác nhau, do đó, một thành phần duy nhất có thể được thực hiện một cách gián tiếp trên nhiều nút.

2 Mặc dù các thành phần là các đơn vị tự trị, chúng có thể vẫn phụ thuộc vào các dịch vụ được cung cấp bởi các thành phần khác. Do đó, việc cung cấp tư liệu về các giao diện được yêu cầu của một thành phần là hữu ích.

3 Hình 3 không hiển thị thành phần Order trong bối cảnh đầy đủ của nó. Trong một mô hình thế giới thực, các giao diện OrderEntry, AccountPayable và Person sẽ được biểu diễn trong mô hình của hệ thống.

4 Trên thực tế, các cổng được áp dụng đối với bất kỳ phân loại nào (tức là tới một lớp hoặc một phân loại khác nào đó mà mô hình của bạn có thể có). Để làm cho bài viết này trở nên đơn giản, tôi chỉ nói đến các cổng đang được sử dụng trong các phân loại thành phần.

5 Thông thường thì khi bạn vẽ một mối quan hệ phụ thuộc giữa một cổng và một giao diện, giao diện phụ thuộc (yêu cầu) sẽ xử lý tất cả các logic về xử lý tại thời điểm thực thi. Tuy nhiên, đây không phải là một quy tắc cứng nhắc và nhanh – điều này hoàn toàn có thể chấp nhận được cho việc chứa đựng thành phần (tức là các thành phần Store trong ví dụ của chúng tai) để có lôgic xử lý của riêng nó thay vì chỉ đơn thuần là uỷ thác việc xử lý cho giao diện phụ thuộc.

Bình luận

developerWorks: Đăng nhập

Các trường được đánh dấu hoa thị là bắt buộc (*).


Bạn cần một ID của IBM?
Bạn quên định danh?


Bạn quên mật khẩu?
Đổi mật khẩu

Bằng việc nhấn Gửi, bạn đã đồng ý với các điều khoản sử dụng developerWorks Điều khoản sử dụng.

 


Ở lần bạn đăng nhập đầu tiên vào trang developerWorks, một hồ sơ cá nhân của bạn được tạo ra. Thông tin trong bản hồ sơ này (tên bạn, nước/vùng lãnh thổ, và tên cơ quan) sẽ được trưng ra cho mọi người và sẽ đi cùng các nội dung mà bạn đăng, trừ khi bạn chọn việc ẩn tên cơ quan của bạn. Bạn có thể cập nhật tài khoản trên trang IBM bất cứ khi nào.

Thông tin gửi đi được đảm bảo an toàn.

Chọn tên hiển thị của bạn



Lần đầu tiên bạn đăng nhập vào trang developerWorks, một bản trích ngang được tạo ra cho bạn, bạn cần phải chọn một tên để hiển thị. Tên hiển thị của bạn sẽ đi kèm theo các nội dung mà bạn đăng tải trên developerWorks.

Tên hiển thị cần có từ 3 đến 30 ký tự. Tên xuất hiện của bạn phải là duy nhất trên trang Cộng đồng developerWorks và vì lí do an ninh nó không phải là địa chỉ email của bạn.

Các trường được đánh dấu hoa thị là bắt buộc (*).

(Tên hiển thị cần có từ 3 đến 30 ký tự)

Bằng việc nhấn Gửi, bạn đã đồng ý với các điều khoản sử dụng developerWorks Điều khoản sử dụng.

 


Thông tin gửi đi được đảm bảo an toàn.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=70
Zone=Rational
ArticleID=477503
ArticleTitle=Căn bản UML: Sơ đồ thành phần
publish-date=03262010