Một trong những câu hỏi tôi luôn suy nghĩ trong đầu khi bắt đầu bước vào ngành phần mềm là làm thế nào để từ một bài toán thực tế ta có thiết kế ra được các thành phần bên trong một cách đúng đắn: DLL, class, property… Tôi tin rằng các bạn cũng có cùng câu hỏi như vậy, có một kiến thức tốt về thiết kế không chỉ giúp cho công việc hiện tại mà còn mở ra một chân trời mới trong con đường sự nghiệp của bạn.Loạt bài này sẽ giúp bạn có được những kiến thức vững chắc về thiết kế phần mềm, và vì có khá nhiều vấn đề liên quan đến thiết kế nên tôi sẽ viết ra thành nhiều bài theo thứ tự, các bạn chịu khó theo dõi nhé.
Trước khi bắt đầu, ta cần thống nhất với nhau vài điều:
– Kiến thức về OOP là bắt buộc, các phương pháp thiết kế ở đây đều yêu cầu một nền tảng tốt về OOP .
– Tôi sẽ không viết riêng cho một nền tảng hay ngôn ngữ nào, nhưng sẽ tập trung vào Java và .NET, cùng các ngôn ngữ là Java và C#. Đây là hai trong những nền tảng phổ biến và tốt nhất, đặc biệt cho việc xây dựng các ứng dụng lớn.
– UML: Bạn không cần biết trước về UML, nhưng nếu có kiến thức về nó sẽ rất tốt, đôi khi tôi có thể dùng nó để mô tả.
CÁC BƯỚC CƠ BẢN
Việc đầu tiên nhất khi xây dựng phần mềm là tìm ra những yêu cầu của bài toán, một ứng dụng lớn sẽ có rất nhiều câu hỏi cần được trả lời:
– Ai sẽ sử dụng hệ thống? hay nói chính xác hơn, những đối tượng nào từ bên ngoài sẽ tương tác với hệ thống. Như vậy, “ai” ở đây sẽ không chỉ là người nào, mà nó có thể là một hệ thống khác, khi bạn viết một web server, “ai” này có thể là trình duyệt, “ai” này cũng có thể là một hệ thống từ bên ngoài truy vấn dữ liệu để xây dựng các báo cáo… Hoặc thậm chí có thể là một khái niệm logic, ví dụ một user role. Ta gọi những người/hệ thống bên ngoài sẽ tương tác với hệ thống của chúng ta là actor.
– Các actor sẽ làm gì? Các actor sẽ thực hiện các tác vụ như: đăng nhập, xem báo cáo, nhập hàng vào kho, cập nhật trạng thái đơn hàng… Mỗi một tác vụ như vậy ta gọi là một usecase, thể hiện một mục đích sử dụng của actor. Người phân tích hệ thống sẽ phải thu thập thông tin từ khách hàng để xác định các usecase, cũng như các bước thực hiện một usecase, các bước này sẽ được viết thành bản mô tả. Bạn có thể đọc thêm về cách viết mô tả usecase ở bên dưới.
– Hệ thống có những yêu cầu và ràng buộc nào? Hệ thống có thể phục vụ cho bao nhiêu người dùng cùng lúc? Xác xuất chấp nhận lỗi khi tạo giao dịch là bao nhiêu? Khi xảy ra thảm họa (máy hỏng, ổ cứng hư…), hệ thống có khả năng phục hồi lại thế nào…
Việc lấy được những yêu cầu này cần cả một nghệ thuật, và có thể phải có sự tham gia của các BA (Business Analyst), thậm chí cả các chuyên gia trong lĩnh vực liên quan, vì có những nghiệp vụ rất phức tạp mà người ngoài không thể hiểu được. Các kỹ sư phần mềm có thể rất giỏi trong việc viết code, hay thiết kế ra các lớp, các sơ đồ… nhưng sẽ chẳng thể làm gì nếu họ không hiểu yêu cầu.
TÌM ACTOR
Như trên đã nói, actor là một đối tượng từ bên ngoài sẽ trực tiếp tương tác với ứng dụng. Nếu không có actor, sẽ chẳng có ai giao việc cho hệ thống của chúng ta, cũng chẳng có ai nhận kết quả trả về (thực ra cũng có làm gì đâu mà có kết quả).
VIẾT MÔ TẢ USECASE
Một usecase là một chuỗi hành động để hoàn thành một công việc nào đó, nó sẽ được bắt đầu bởi một actor. Một usecase đúng có thể là: Login, CreateCustomer, ResetPassword, ViewCart, UpdateCart… tức nó phải cụ thể, chứ không chung chung kiểu như: CustomerManagerment, hay ManageCart (*).
Với usecase ResetPassword, tôi có thể viết:1. Hệ thống hiển thị 1 textbox, cho phép người dùng nhập vào email hoặc số điện thoại.2. Hệ thống kiểm tra dữ liệu nhập vào có phải là email hoặc số điện thoại hợp lệ không, nếu không phải, hiển thị thông báo: “Bạn phải nhập email hoặc số điện thoại hợp lệ” và quay lại bước 1.3. Hệ thống kiểm tra xem có bản ghi người dùng nào có email hoặc số điện thoại trùng khớp không, nếu không có, hiển thị thông báo: “Không tìm thấy email/số điện thoại đã nhập” và quay lại bước 1.4. Hệ thống tạo ra một mã phục hồi ngẫu nhiên, lưu lại mã này và ID người dùng có email/điện thoại trùng khớp vào CSDL cùng với thời gian hợp lệ.5. Hệ thống xác định dữ liệu nhập vào là email hay số điện thoại, rồi gửi mã phục hồi đến cho người dùng thông qua phương thức tương ứng.
Một usecase liên quan là UpdatePasswordUsingResetCode:
1. Hệ thống hiển thị một textbox, cho phép người dùng nhập mã phục hồi (có thể tự động điền mã này thông qua liên kết người dùng nhấn vào).
2. Người dùng nhập vào mã phục hồi nhận được qua email hoặc số điện thoại.
3. Hệ thống kiểm tra trong CSDL, nếu không tìm thấy một mã phục hồi trùng khớp và còn trong thời gian hợp lệ, hệ thống sẽ hiển thị thông báo: “Mã phục hồi không hợp lệ hoặc đã hết hạn” và quay lại bước 1.
4. Hệ thống hiển thị 1 textbox cho phép người dùng nhập vào mật khẩu mới.
5. Hệ thống cập nhật mật khẩu mới sử dụng ID tương ứng.
Bạn sẽ thấy những gì viết ra mô tả từng bước cụ thể, ta không cần viết chi tiết đến mức: “Người dùng nhập số điện thoại và nhấn Enter” vì không cần thiết, thêm nữa chi tiết “nhấn Enter” về nguyên tắc sẽ làm mô tả thiếu đi tính tổng quát. Mỗi một bước mô tả ở trên sẽ là một hành động đơn, thể hiện một mục đích cụ thể để hoàn thành usecase.Nhớ là một usecase là một hoặc một chuỗi hành động luôn được bắt đầu bởi một actor, và khi kết thúc nó sẽ phải mang lại một kết quả nào đó.
Trong thực tế, không nhất thiết phải viết mô tả cho tất cả usecase, tuy nhiên hãy viết cho càng nhiều usecase càng tốt. Vì các bản mô tả này không chỉ giúp bạn và đội ngũ phát biết những gì cần làm, mà quan trọng hơn, nó giúp bạn và khách hàng/product owner có cùng một cách nhìn, cũng như thống nhất được cụ thể danh sách/chi tiết các chức năng.
Việc viết ra một bản mô tả sẽ mất rất ít công sức so với việc code ra một chức năng khách hàng không cần, hay sai so với yêu cầu thực sự.
Note:
– Trong hình minh họa (sử dụng UML), actor được mô tả là hình người, còn usecase là hình oval.(*)
– Trong thực tế bạn vẫn có thể thấy các usecase như ManageCart, tuy nhiên các usecase đó cũng phải được phân tích sâu thêm thành các usecase con: ViewCart, DeleteItem, UpdateItemQuantity…