Là một vấn đề quan trọng trong quy trình RUP, đáp ứng vấn đề quản lý thay đổi trong quy trình RUP. Phụ thuộc yêu cầu có nghĩa là trong quy trình RUP phân biệt rất nhiều loại yêu cầu từ mức thô sơ nhất (yêu cầu khách hàng-customer needs, tài liệu Vision,…vv), cho đến yêu cầu ở mức tinh lọc gần với hệ thống thực (use-case, các hỗ trợ đặc tả yêu cầu phần mềm, các giải pháp thiết kế,…vv). Từ đó tạo ra một hệ thống các yêu cầu ràng buộc chống chéo lên nhau, khó có thể theo dõi và quản lý. Mặt khác, do có sự ràng buộc liên quan nên khi một yêu cầu thay đổi thì kéo theo sự thay đổi của rất nhiều yêu cầu khác, ảnh hưởng đến đặc tính và tính chất của phần mềm. Vì vậy, vấn đề quản lý yêu cầu là rất quan trọng và nhất thiết yêu cầu phải có. Tuy nhiên để quản lý sự phụ thuộc chồng chéo như thế này thì rất khó, tốn thời gian và nhân lực. Tuy nhiên, trong quy trình RUP, vấn đề quản lý yêu cầu này được giải quết bằng công cụ Rational RequirePro rất hữu ích giải quết gần như trọn vẹn vấn đề này. Đây là một điểm rất mạnh của quy trình RUP là vốn có công cụ hùng hậu hỗ trợ, tăng khả năng đáng kể thuận lợi và sức mạnh của quy trình.
Trong dự án này, tôi sử dụng công cụ Rational RequirePro để quản lý phụ thuộc yêu cầu. Nó kết hợp với công cụ Rational Rose tạo nên sự nhất quán trong phân tích và quản lý yêu cầu. Các loại yêu cầu của dự án như sau:
Yêu cầu khách hàng (Cutomer Needs) Tính chất của sản phẩm (Feature).
Từ điển thuật ngữ nghiệp vụ của dự án (Glossary). Yêu cầu chức năng của phần mềm (Use-Cases).
Các hỗ trợ đặc tả yêu cầu phần mềm (Supplementary Requirements).
Với một yêu cầu thì có các tính chất: Tên yêu cầu.
Các lịch sử xét duyệt.
Các thuộc tính của yêu cầu (Attribute): rất qua trọng, một yêu cầu được cấu thành bởi rất nhiều thuộc tính.
Sự phụ thuộc yêu cầu (Traceability): mỗi thuộc tính của yêu cầu này phụ thuộc đến một số thuộc tính của các yêu cầu khác và ngược lại nó gây ảnh hưởng đến một số thuộc tính khác (vừa bị phụ thuộc lại vừa gây ra sự phụ thuộc).
Phân cấp yêu cầu (Hierachy), sự hiện thực hòa và khái quát hóa yêu cầu. Các xem xét (Discussion) cho các yêu cầu.
Các yêu cầu trên được theo dõi dựa trên ma trận theo dõi phụ thuộc yêu cầu, khi mà một yêu cầu thay đổi thì các yêu cầu khác sẽ được xem xét và thay đổi theo bằng ma trận theo dõi yêu cầu một cách nhất quán.
Hình 3-31 Ma trận theo dõi phụ thuộc yêu cầu 1.10.2. Giai đoạn lặp lần thứ hai (Iteration 2)
1.10.2.1. Mục tiêu
Giai đoạn lặp lần thứ nhất đã tập trung phân tích các khái niệm liên quan đến các Use-Case trong hệ thống mục đích là thống nhất các khái niệm trong các Use- Case trong hệ thống. Mục tiêu chính của giai đoạn lặp lần thứ hai là sử dụng các kết quả đã phân tích được từ giai đoạn lặp lần thứ nhất để tập trung vào phân tích thiết kế các đối tượng. Các hoạt động chính trong dự án này tôi thực hiện trong giai đoạn lặp lần thứ hai là:
Thiết kế các đối tượng trên cơ sở các lớp phân tích
Quan tâm đến các hỗ trợ đặc tả trong thiết kế các lớp. Do trong khâu phân tích Use-Case ở các giai đoạn trước hoàn toàn tập trung vào chức năng của hệ thống và phân tích các lớp cơ bản nhất đáp ứng các chức năng đó mà chưa tính đến các yêu cầu hỗ trợ kèm theo. Bắt đầu từ giai đoạn này khi thiết kế các lớp phải tính đến các yêu cầu hỗ trợ đó.
Sử dụng các công cụ UML trong thiết kế các lớp.
Để tham khảo thêm về tài liệu hỗ trợ đặc tả yêu cầu phần mềm bạn đọc có thể xem thêm trong tài liệu Hỗ trợ đặc tả yêu cầu phần mềm và các mẫu trong thiết kế có thể tham khảo thêm trong tài liệu tham khảo [3].
1.10.2.2. Kế hoạch của giai đoạn lặp lần thứ hai
Cũng tương tự như việc lập kế hoạch trong giai đoạn lần thứ nhất, tôi tiến hành lập kế hoạch cho giai đoạn lần thứ hai. Các công việc và tiến trình lập kế hoạch cũng hoàn toàn giống như việc lập kế hoạch cho giai đoạn lặp lần thứ nhất, tuy nhiên, trong phần này trọng tâm lại tập trung vào một số nội dung khác. Các bạn có thể tham khảo kế hoạch lặp cho giai đoạn lần thứ hai này trong tài liệu kèm theo chú ý đến mục tiêu của giai đoạn này như ở phần trên để có thể theo sát quá trình thực hiện dự án theo quy trình RUP.
1.10.2.3. Sử dụng các mẫu thiết kế (Design Pattern)
Do quy trình RUP là một quy trình công nghệ phần mềm chủ yếu dựa vào đối tượng, các dự án phần mềm áp dụng quy trình RUP phụ thuộc rất nhiều vào kỹ thuật hướng đối tượng. Do đó, yêu cầu các thành viên trong đội dự án tham gia quy trình RUP cần phải có các kỹ năng kinh nghiệm về kỹ thuật hướng đối để có thể hoàn thành tốt dự án Trong phần này tôi xin trình bày về sử dụng các mẫu thiết kế áp dụng vào trong dự án. Mục đích chính của sử dụng các mẫu thiết kế này là nhằm tăng cường khả năng tái sử dụng của hệ thống và tăng độ tin cậy của hệ thống thông qua các mẫu thiết kế đã được sử dụng rộng rãi và được kiểm nghiệm. Ở đây cần yêu cầu kỹ năng và kinh nghiệm của người thiết kế (Designer). Mẫu thiết kế là một điểm mạnh của kỹ thuật hướng đối tượng và đóng một vai trò khá quan trọng trong quy trình RUP, vì sử dụng các mẫu thiết kế tốt sẽ có khả năng tăng cường tính sử dụng lại của các đối tượng và tăng khả năng tin cậy của các đoạn mã và hệ thống nói chung. Tuy nhiên, còn một điều nói thêm rằng, không nhất thiết đội dự án phải thực hiện các mẫu thiết kế giống như ở đây và trong các tài liệu tham khảo. Là bởi vì các mẫu thiết kế là các gợi ý một cách nhanh chóng cho các nhà thiết kế tìm kiếm một giải pháp cho vấn đề chứ không phải là giải pháp thích hợp duy nhất hoặc tốt nhất. Điều đó có nghĩa là không nên áp dụng một cách máy móc các mẫu thiết kế đó. Tuy nhiên để làm được điều này yêu cầu người thiết kế phải có trình độ và kỹ năng tốt về các mẫu thiết kế.
Do đặc điểm của dự án này là sử dụng nhiều đến đồ hoạ và các đối tượng đồ hoạ. Tôi chủ yếu sử dụng mẫu thiết kế kết hợp (Composite Pattern) vào trong các
thiết kế của dự án, và có sử dụng thêm một số mẫu khác. Chi tiết các bạn có thể xem thêm trong mô hình thiết kế kèm theo của đồ án này, và các Pattern các bạn có thể tham khảo thêm trong tài liệu tham khảo [3]
CVPoint (from Points) CGlyph (from Graphs) CPoint3D Z : int (from Points) CGraph (from Graphs) +theCGlyph CCircle (from Geometrics) CRectangle Color : COLORREF (from Geometrics) CPoint2D (from Points) CLine (from Geometrics)
Hình 3-2 Mẫu thiết kế kiểu tổng hợp (Composite Pattern)
Một trong những mẫu thiết kế quan trọng nhất mà tôi áp dụng vào dự án này là mẫu thiết kế tổng hợp (Composite Pattern), vì nó đặc biệt thích hợp với kiến trúc đồ hoạ áp dụng trong chương trình. Trong chương trình tôi xây dựng một đối tượng ảo là thực thể đồ hoạ (Glyph). Thực thể đồ hoạ là khái niệm trừu tượng bao gồm nhiều đối tượng đồ hoạ cụ thể như Điểm (CVPoint), Đoạn thẳng (CLine), Hình chữ nhật (CRectangle), Hình tròn (CCircle). Mỗi đối tượng đồ hoạ đó là một loại của thực thể đồ hoạ (quan hệ kế thừa cha con ).
Thực chất hầu hết là trong chương trình thao tác chủ yếu với các đối tượng đồ hoạ tương đối phức tạp, có thể bao gồm nhiều thông tin, nhiều thực thể đồ hoạ trong đó. Một đối tượng đồ hoạ (CGraph) là tổng hợp của nhiều thực thể đồ hoạ. Trong chương trình của ta chủ yếu thao tác trên các đối tượng đồ hoạ này là chính. Có rất nhiều thao tác giống nhau cùng áp dụng với các thực thể khác nhau. Nếu như với mỗi đối tượng đồ hoạ ta lại phải viết lại các đoạn code mã gần tương tự nhau để cùng thực hiện một số hành vi nào đó thì rất mất công sức và tốn kém. Thí dụ như: Đối tượng đồ hoạ (CGraph) muốn thực hiện hành vi thêm các thực thể đồ hoạ (Hình chữ nhật, Điểm, Hình tròn, Đoạn thẳng, vv), thông thường ta phải viết như sau
class CVPoint; class CLine; class CRectangle; class CCircle; class CGraph {
AddPoint(CVPoint ); AddLine(CLine );
AddRectangle (CRectangle ); AddCircle (CCircle );
}
Khi có một đối tượng sử dụng đối tượng CGraph, ta phải lần lượt thực hiện hành vi thêm các thực thể đồ hoạ như sau
CFormRepresentation::OnDraw() { CGraph * _graph; CRectangle _rect; CLine _line; CPoint _point; _graph→AddRectangle(_rect); _graph→AddLine(_line); _graph→AddPoint(_point); }
Phần cài đặt lại lần lượt thực hiện các hành vi giống hệt nhau là thêm các thực thể đồ hoạ khác nhau vào trong đối tượng đồ hoạ CGraph. Như thể là rất tốn kém về thời gian và công sức và việc cài đặt các đoạn mã càng nhiều thì càng kém tin cậy
Giả sử bây giờ cần thiết phải thêm một thực thể đồ hoạ khác thí dụ như tam giác chẳng hạn (CTriangle). Ngoài việc xây dựng các thuộc tính và hành vi cho riêng đối tượng tam giác, ta vẫn cần thiết phải sửa lại tất các các đoạn mã của các đối tượng có liên quan đến đối tượng tam giác như đối tượng CGraph lại phải thực hiện lại hành vi
class CGraph {
AddTriangle(CTriangle ); }
Đối tượng Form cũng phải sửa đổi cài đặt nếu muốn sử dụng đối tượng CTriangle CFormRepresentation::OnDraw() { CGraph * _graph; CTriangle _triangle; graph→AddTriangle(_triangle);
}
Giải pháp sử dụng mẫu thiết kế ở đây như là sử dụng một đối tượng lớp cơ sở ảo đại điện cho tất cả các thực thể đồ hoạ CGlyph, và sử dụng tính chất liên kết động (dynamic binding) của ngôn ngữ lập trình hướng đối tượng C++
class CGlyph {
//Cac phuong thuc ao vitual
}
class CRectangle : public CGlyph {
//Cai dat lai mot so phuong thuc ao cua CGlyph }
class CLine : public CGlyph {
//Cai dat lai mot so phuong thuc ao cua CGlyph }
…vv
Trong đối tượng đồ hoạ chỉ cần sử dụng đến một phương thức Add cho tất cả các thực thể đồ hoạ, việc cài đặt ít mã này sẽ tin cậy hơn
class CGraph {
AddGlyph(CGlyph* );//Chu y la su dung con tro }
Khi đối tượng CFormRepresentation sử dụng đến đối tượng CGraph thì chúng chỉ chúng cũng không cần quan tâm đến các thực thể đồ hoạ khác nhau
CFormRepresentation::OnDraw() {
CGraph * _graph;
CRectangle _rect=new CRectangle(); CLine _line=new CLine();
CPoint _point=new CPoint(); _graph→AddGlyph(&_rect); _graph→AddGlyph(&_line); _graph→AddGlyph(&_point); }
Khi xây dựng thêm đối tượng CTriangle, ta chỉ quan tâm xây dựng đối tượng CTriangle, và bản thân nó là một loại CGlyph nên không cần phải cài đặt thêm các hành vi riêng rẽ với nó trong đối tượng CGraph và các đối tượng khác sử dụng nó
1.10.2.4. Thiết kế đáp ứng các yêu cầu phi chức năng (Supplementary Specification) Specification)
Trong quá trình phân tích từ các giai đoạn trước, nói chung quy trình RUP chỉ tập trung vào phân tích xây dựng các khía cạnh chức năng của hệ thống, làm thế nào đáp ứng được các yêu cầu có tính chức năng của hệ thống. Các yêu cầu phi chức năng chưa được để ý tới. Tuy nhiên, đến giai đoạn này, thì các yêu cầu phi chức năng phải được tính đến như là yêu cầu bắt buộc. Các yêu cầu phi chức năng bao gồm nhiều loại như: tính dễ sử dụng, mức độ bảo mật, độ tin cậy, khả năng thực thi, tốc đô, khả năng hỗ trợ, khả năng bảo trì sản phẩm sau này, vv. Việc áp dụng sử dụng các mẫu thiết kế ở trên cũng là một phần đáp ứng các yêu cầu phi chức năng đó. Do đó, để đáp ứng được các yêu cầu phi chức năng chủ yếu thực hiện ở khâu thiết kế này, bao gồm việc lựa chọn các giải thuật, các phương pháp, các giao diện, cân nhắc lựa chọn giữa hiệu năng và khả năng thực thi trong các thiết kế…vv thể hiện trên các thiết kế lớp và các hành vi để đáp ứng đúng chức năng của Use-Case và ngoài ra còn đáp ứng được các yêu cầu khác cũng rất quan trọng. Có một điều chú ý khi thiết kế Use-Case đáp ứng yêu cầu là chức năng của Use-Case thì không thể thay đổi, tuy nhiên có nhiều cách để thực hiện chức năng đó, hãy chọn một trong các cách đó thỏa mãn các yêu cầu trong phần hỗ trợ đặc tả yêu cầu.
Trong quá trình thiết kế các yêu cầu phi chức năng của các Use-Case, các nhà thiết kế căn cứ vào tài liệu đặc tả Use-Case để tiến hành phân tích thiết kế lớp cho Use-Case (phần hỗ trợ đặc tả yêu cầu -Supplementary Specification). Với Use-Case đăng nhập hệ thống (Login), phần hỗ trợ đặc tả yêu cầu như sau:
Tài liệu 3-8 Hỗ trợ đặc tả yêu cầu phần mềm (Use-Case Login)
Chức năng chính của Use-Case Login phải được đảm bảo có nghĩa là dùng một cơ chế bảo mật nào đó cho phép người dùng xác định được sử dụng hệ thống. Tuy nhiên, nó còn có rất nhiều các yêu cầu khác bắt buộc phải xem xét khi xây dựng chức năng. Với Use-Case này, ta thấy không yêu cầu tính chất bảo mật cao lắm, và có khả năng mở rộng tính chất bảo mật nếu cần thiết. Đồng thời, yêu cầu khả năng hồi đáp nhanh cho người sử dụng. Có một điểm lưu ý khi đặc tả các yêu cầu phần mềm là tránh xung khắc nhau. Thí dụ, nếu yêu cầu là mức độ bảo mật hệ thống đơn giản thì có thể có yêu cầu khả năng hồi đáp khi đăng nhập nhanh, nếu yêu cầu mức độ bảo mật thật cao và khả năng hồi đáp thật nhanh thì rất mâu thuẫn, trong thực tế rất khó khăn. Nói chung là trong khi thiết kế các yêu cầu phi chức năng này cần có sự thỏa hiệp giữa các yêu cầu. Nếu được yêu cầu này tốt thì nhất định một số yêu cầu khác không được tốt lắm. Nhiệm vụ của người thiết kế là tìm ra một giải pháp phù hợp thỏa hiệp các yêu cầu. Do đó, tôi thiết kế riêng một lớp chuyên để mã hóa và giải mã các Password cho hệ thống (CKey), tuy nhiên, thuật toán áp dụng mã hóa và giải mã rất đơn giản dùng mã dịch chuyển với hai tham số a và b, khóa mã và giải đối xứng nhau như sau đây.
3 UC5.4 Các yêu cầu đặc biệt (phi chức năng)
UC5.4.1 Yêu cầu về chức năng
Chức năng này phải hoạt động chính xác, mỗi User chỉ có một định danh duy nhất. Tốc độ cao.
UC5.4.2 Tính dễ sử dụng
Cần có hướng dẫn ngữ cảnh cụ thể cho việc đăng nhập hệ thống UC5.4.3 Mức độ bảo mật
Không yêu cầu cao, ở mức trung bình chấp nhận được. Sau này, có thể nâng cấp bằng các phương pháp mã hoá để tăng tính bảo mật nếu cần thiết.
UC5.4.4 Khả năng thực thi của hệ thống Tốc độ nhanh và tin cậy
Thời gian hồi đáp nhanh UC5.4.5 Khả năng hỗ trợ
Dế bảo trì và kiểm thử
Có khả năng mở rộng để thêm chức năng bảo mật nếu cần thiết. UC5.4.6 Yêu cầu về giao diện
Hình 3-32 Lớp CKey và mã hóa dích chuyển.
Nếu yêu cầu tính chất bảo mật cao, bắt buộc trong thiết kế phải thay đổi thuật toán và thiết kế lại lớp CKey, đấy là thiết kế có tính đến hỗ trợ đặc tả yêu cầu. Giả sử ta không sử dụng phương pháp mã hóa dịch chuyển mã sử dụng phương pháp mã hóa RSA chẳng hạn, thì các thuộc tính của lớp Ckey không phải là a và b nữa mà là các thuộc tính thỏa mãn cài đặt thuật toán RSA và tính chất khóa không còn đối xứng nữa (mã khóa công cộng và giải mã bí mật)…vv.
1.10.3. Giai đoạn lặp lần thứ ba (Iteration 3)
Nếu như trong giai đoạn khởi đầu và giai đoạn lặp lần thứ nhất là tập trung vào tìm kiếm phân tích yêu cầu của khách hàng đảm bảo rằng dự án đang thực