Trong phần này chúng ta hãy áp dụng GRASP để gán trách nhiệm cho các lớp và tạo ra các biểu đồ cộng tác. Chúng ta thực hiện mẫu đối với ca sử dụng “Thanh toán
tiền mặt” và “Khởi động” (Start Up), sau đó thực hiện tương tự đối với những ca sử
dụng khác.
Khi thiết kế biểu đồ cộng tác, chúng ta hãy thực hiện theo những hướng dẫn sau: 1. Với mỗi thao tác (hoạt động chính) đã được mô tả trong các hợp đồng của hệ
thống nên tạo ra một biểu đồ riêng.
2. Nếu biểu đồ này phức tạp thì có thể chia nó thành những biểu đồđơn giản hơn. 3. Sử dụng các hợp đồng trách nhiệm, trong đó dựa vào những điều kiện cần
thoả mãn sau khi hoàn thành (post-condition) và các mô tả ca sử dụng để xác
định trách nhiệm của các đối tượng trong hệ thống theo mẫu gán trách nhiệm nhưđã nêu trên.
Để thực hiện ca sử dụng “Thanh toán tiền mặt và “Khởi động”, hệ thống phải thực hiện: enterItems() (nhập các mặt hàng), endSale() (kết thúc một phiên bán hàng),
makePayment() (thanh toán) và startUp() (khởi động). Theo hướng dẫn trên, chúng ta thiết kế các biểu đồ cộng tác cho những thao tác đó. Chúng ta bắt đầu từ bốn biểu đồ như hình 6-19. HBH enterItems() endSale() makePayment()
Hình 6-19 Các thao tác của hệ thống
Biểu đồ cộng tác cho enterItems()
Trước hết chúng ta xem lại hợp đồng thực hiện enterItems() để biết hệ thống phải làm những gì.
1. Hiển thị thông tin mô tả và giá bán của mặt hàng được nhập vào.
Nói chung, các đối tượng của hệ thống không có trách nhiệm hiển thị các thông tin. Những công việc này có thểđược các đối tượng giao diện đảm nhiệm bằng cách truy nhập vào CSDL về các mặt hàng và gửi các thông điệp chứa những thông tin tương ứng cho các đối tượng đang hoạt động.
2. Tạo lập phiên bán hàng mới.
Như trong hợp đồng đã nêu rõ: khi nhập vào mặt hàng đầu tiên của mỗi phiên bán hàng thì phải tạo lập phienBanHang mới. Trách nhiệm này được gán cho HBH và nó có nhiệm vụ là phải ghi lại các phiên bán hàng như thế.
Hơn nữa, mỗi khi phienBanHang được tạo mới thì nó là tập rỗng và sau đó được bổ sung thêm các dongBanHang mỗi khi nhập xong một mặt hàng.
Áp dụng các mẫu gán trách nhiệm nêu trên, gán việc tạo lập dongBanHang mới cho PhienBanHang là hợp lý.
3. Xác định các thông tin mô tả và giá bán.
Sau khi các dongBanHang được tạo lập thì phải được đưa bổ sung vào
phienBanHang đang hoạt động, do đó nó cần gửi thông điệp add() (bổ sung vào) cho những
dongBanHang đang được nhập vào. Những dongBanHang được đưa vào phienBanHang phải được xác định từDanhMucMatHang và sau đó là MoTaMatHang. Vậy để có được những thông tin trên thì HBH phải gửi thông điệp specification(upc), xác định mô tả mặt
enterItems() :HBH 1: ????() startUp() :HBH 1: ????() makePayment() :HBH 1: ????() endSale() :HBH 1: ????() HBH enterItems() endSale() makePayment() startUp()
hàng có mã là upc cho :DanhMucMatHang, đối tượng này lại gửi tiếp đi thông điệp
find(upc), để tìm trong tập các mô tả mặt hàng có mã upc.
Dựa vào những thảo luận như trên, biểu đồ cộng tác sẽđược xây dựng như sau:
Hình 6-20 Biểu đồ cộng tác cho enterItems()
Tầm nhìn của các lớp
Như đã khẳng định nhiều lần, các đối tượng trong hệ thống tương tác với nhau bằng cách trao đổi các thông điệp, cụ thể hơn như trong các biểu đồ tương tác là trao
đổi thông qua các lời gọi hàm. Trong biểu đồở hình 6-20, khi hệ thống cần xác định những thông tin về mặt hàng có mã upc cho trước, như giá bán chẳng hạn thì nó gửi tới cho :DanhMucMatHang lời gọi hàm specification(upc), đối tượng này lại gửi cho :MoTaMatHang lời gọi hàm find(upc).
Một đối tượng muốn có được những thông tin từ những đối tượng khác thì đối tượng đó phải có khả năng nhìn thấy được những gì mà nó cần thiết. Một cách hình thức hơn,
Trong thiết kế hướng đối tượng, sự liên kết có liên quan chặt chẽ với khái niệm
khả năng nhìn thấy được của các đối tượng.
Nếu :A có thể nhìn thấy :B thì phải có một liên kết giữa hai đối tượng đó, nghĩa là giữa hai lớp tương ứng có quan hệ kết hợp.
Nếu giữa hai đối tượng :A và :B hiện thời có liên kết với nhau thì một trong hai đối tượng đó có một đối tượng nhìn thấy đối tượng kia.
Về sự trao đổi thông điệp giữa các đối tượng có thể phát biểu chính xác như sau: 2: mt := specification(upc) : DongBanHang enterItems(upc, n) : PhienBanHang :DanhMucMatHang 1: [new] create() 2.1: mt := find(upc) : HBH 3: makeLineItem(mt, n) : MoTaMatHang sLi: DongBanHang 1.1: create() 3.2: add(sLi) 3.1: create(mt,n)
Đểđối tượng :A có thể gửi một thông điệp cho đối tượng :B thì lớp A phải được liên kết với lớp B.
Đểđối tượng :A gửi được thông điệp cho đối tượng :B thì đối tượng :A phải nhìn thấy được đối tượng :B.
Có bốn cách để đối tượng A nhìn thấy được đối tượng :B.
1. Tầm nhìn thuộc tính: :B là thuộc tính của :A.
2. Tầm nhìn tham số: :B là tham số của một hàm nào đó của :A.
3. Tầm nhìn khai báo cục bộ: :B được khai báo là đối tượng cục bộ trong định nghĩa hàm của :B.
4. Tầm nhìn toàn cục: :B là toàn cục.
Dựa vào phạm vi quan sát của các đối tượng trong các biểu đồ để khai báo các
đặc tính private, protected, public cho các thuộc tính và hàm thành phân trong các lớp đối tượng.
Biểu đồ cộng tác cho endSale
Có thể chọn HBH đểđiều khiển thao tác này của hệ thống. Hợp đồng của thao tác này yêu cầu: PhienBanHang.isComplete được gán trị true khi kết thúc nhập dữ liệu.
Như vậy, hệ HBH có thể gửi thông điệp becomeComplete() cho PhienBanHang
đểđặt thuộc tính isComplelet nhận giá trị true.
Hình 6-21 Biểu đồ cộng tác thể hiện Kết thúc nhập dữ liệu endSale()
Biểu đồ cộng tác cho makePayment
Một lần nữa nhắc lại, chúng ta sẽ xem HBH như là bộ điều khiển. Trong phần thảo luận về mẫu gán trách nhiệm để đảm bảo mức độ móc nối giữa các lớp yếu, nhưng độ cố kết lại cao, chúng ta đã gán trách nhiệm tạo lập đối tượng ThanhToan
cho lớp PhienBanHang, chứ không gán cho lớp HBH (hình 6-16). Biểu đồ cộng tác mô tả thao tác makePayment() được vẽ lại như sau:
becomeComplete(){ isComplete = true; } :HBH endSale() :PhienBanHang becomeCompelete() makePayment(soTien) :HBH 1: makePayment(soTien) :PhienBanHang :ThanhToan 1.1: create(soTien) Theo mẫu móc nối yếu Qua bộđiều khiển
Hình 6-22 Biểu đồ cộng tác cho makePayment() Biểu đồ này đáp ứng những điều kiện sau:
Một đối tượng của lớp ThanhToan đảm nhận việc thanh toán, ThanhToanđược kết hợp với PhienBanHang
ThanhToan.soluong = soTien.
Ghi nhận những phiên bán hàng đã kết thúc
Mỗi khi kết thúc một phiên bán hàng, theo yêu cầu trong hoạt động kinh doanh của Công ty, hệ thống phải ghi lại ký sự của những phiên bán hàng đó. Theo kinh nghiệm của chuyên gia, ta có thể gán trách nhiệm này, trách nhiệm addSale() cho
CuaHang sau khi đã gán trách nhiệm makePayment() cho PhienBanHang. Biểu đồ ở
hình 6-22 được bổ sung thành:
Hình 6-23 Biểu đồ cộng tác cho makePayment() và ghi nhận thông tin đã bán
Biểu đồ cộng tác cho ca sử dụng StartUp
Phần lớn các hệ thống (nhưng không phải tất cả) đều có ca sử dụng “Khởi động”
và một số thao tác liên quan đến việc khởi tạo các giá trị cho một ứng dụng khi bắt đầu thực thi. Mặc dù thao tác này thường là thao tác đầu tiên hệ thống phải thực hiện, nhưng chúng ta để lại thiết kế sau để đảm bảo mọi thông tin liên quan đến các hoạt
động sau này của hệ thống đều đã được phát hiện.
Biểu đồ cộng tác của StartUp chỉ ra những gì có thể xảy ra khi đối tượng của miền ứng dụng được tạo ra. Nghĩa là trong hệ thống bán hàng phải gán trách nhiệm
create() cho những lớp chính, đó là HBH hoặc CuaHang.
Chúng ta chọn CuaHang bởi vì HBH đã được chọn làm bộ điều khiển cho các hoạt động của cả hệ thống.
Căn cứ vào hợp đồng của StartUp và những thảo luận ở trên, ta có thể thiết kế
biểu đồ cộng tác cho StartUp như sau: makePayment(soTien) 2: addSale(s) 2.1: add(s) :HBH 1: makePayment(soTien) s: PhienBanHang :ThanhToan 1.1: create(soTien) :CuaHang daBan: PhienBanHang
1. Bắt đầu gửi thông điệp create() cho CuaHang,
2. Để tạo ra đối tượng thuộc lớp HBH và cho phép những đối tượng đó gửi được các thông điệp cho DanhMucMatHang để yêu cầu các thông tin về các mặt hàng (xem biểu đồ cộng tác của enterItems) thì trước tiên nó cần phải tạo ra các đối tượng DanhMucMatHang.Nghĩa là nó gửi thông điệp create() trước cho DanhMucMatHang, sau đó mới gửi cho HBH thông điệp tương tự. 3. Khi một đối tượng DanhMucMatHang đã được tạo lập thì nó sẽ yêu cầu tạo
lập MoTaMatHang và sau đó bổ sung vào danh sách các mô tả mặt hàng,
đồng thời bản thân nó tự nạp những thông tin mô tả những mặt hàng tiếp theo. Biểu đồ này được vẽ như hình 6-24.
Hình 6-24 Biểu đồ cộng tác cho StartUp
Sự khác biệt giữa phân tích và thiết kế
Trong biểu đồ cộng tác cho startUp mới chỉ thể hiện việc tạo ra một đối tượng đại diện cho một điểm bán hàng đầu cuối. Trong khi ở mô hình khái niệm ở pha phân tích, nó được xây dựng để mô hình cho những cửa hàng thực tế có thể có nhiều điểm bán hàng đầu cuối, nghĩa là khi hệ thống hoạt động thì sẽ có nhiều đối tượng của HBH
được tạo ra.
Từđó có thể thấy có một sốđiển chênh lệch giữa kết quả phân tích và thiết kế: 1. Đối tượng :CuaHang trong các biểu đồ không phải là cửa hàng thực, nó là đối
tượng mềm,
1.1: create()
DanhMucMatHang:: loadProdSpec(){ do{
ps = new DanhMucMatHang(upc, price, descrip); Collection(MoTaMatHang).add(ps); }while NotFinished; } create() pc: DanhMucMatHang ps: MoTaMatHang 1.2: loadProdSpec() :CuaHang :HBH :MoTaMatHang 2: create(pc) 1: create() 1.2.2:*add(ps)
2. Đối tượng :HBH trong các biểu đồ không phải là điểm bán hàng đầu cuối cụ
thể, nó là đối tượng mềm,
3. Biểu đồ cộng tác thể hiện mối quan hệ tương tác giữa một đối tượng :CuaHang và :HBH.
4. Tổng quát hoá từ một đối tượng của HBH sang nhiều đối tượng đòi hỏi
CuaHang phải tạo ra nhiều thể hiện. Và những sự tương tác giữa các đối tượng HBH với nhiều đối tượng khác cần phải được đồng bộ hoá đểđảm bảo sự toàn vẹn trong việc chia sẻ các thông tin trong hệ thống. Điều này dẫn đến tính toán đa hoặc tính toán tương, vấn đề này vượt ra ngoài phạm vi của đề tài
đang thảo luận ởđây.