Thật trùng hợp, tôi đang làm việc trong một dự án WinForms được mô phỏng theo MVC. Tôi sẽ không gọi đây là một câu trả lời hoàn hảo, nhưng tôi sẽ giải thích thiết kế tổng thể của mình và hy vọng điều này có thể giúp bạn đưa ra ý kiến của riêng mình.
Dựa trên bài đọc tôi đã làm trước khi bắt đầu dự án này, dường như không có cách "đúng" nào để thực hiện điều này. Tôi đã tuân theo các nguyên tắc thiết kế OOP và MVC đơn giản và phần còn lại là bản dùng thử và lỗi khi tôi phát triển một quy trình công việc.
Có phải MVC đơn giản là một kiến trúc không phù hợp cho trường hợp sử dụng này?
Không ..? Không có đủ ngữ cảnh trong câu hỏi của bạn để cung cấp câu trả lời trực tiếp cho điều đó. Tại sao bạn sử dụng MVC ở nơi đầu tiên? Các yêu cầu không chức năng của dự án của bạn là gì? Dự án của bạn sẽ rất nặng UI? Bạn có quan tâm nhiều hơn về bảo mật và thay vào đó là một kiến trúc lớp? Các thành phần chính của dự án của bạn là gì? Có lẽ mỗi thành phần cần một mẫu thiết kế khác nhau. Tìm hiểu lý do tại sao bạn muốn sử dụng mẫu thiết kế này ở nơi đầu tiên và bạn có thể trả lời câu hỏi của riêng bạn;)
Lý do của tôi khi sử dụng MVC: đó là một mẫu thiết kế khá đơn giản để hiểu theo ý kiến của tôi và thiết kế của tôi dựa nhiều vào sự tương tác của người dùng. Cách MVC cho phép nhà phát triển tách biệt mối quan tâm là đủ cho ứng dụng của tôi. Điều này làm cho mã của tôi rất nhiều bảo trì và kiểm tra được.
Tôi cũng cho rằng tôi đang sử dụng nhiều hơn một thiết kế lai. Thông thường, khái niệm lý tưởng được trình bày trong công nghệ phần mềm không thực sự diễn ra trong thực tế. Bạn có thể sửa đổi thiết kế cho phù hợp với nhu cầu của dự án của bạn. Không cần phải bị cuốn vào những gì là đúng hay sai. Có những thực tiễn chung, nhưng các quy tắc luôn có thể bị bẻ cong hoặc phá vỡ miễn là bạn không tự bắn vào chân mình.
Việc triển khai của tôi bắt đầu với một thiết kế cấp cao cho tôi ý tưởng về những thành phần nào tôi sẽ cần. Tốt nhất của bạn để bắt đầu theo cách này và làm việc theo cách của bạn trong kiến trúc. Đây là sơ đồ gói cho dự án (được tạo trong StarUML):
Lưu ý mọi lớp đơn trừ lớp trình bày tùy thuộc vào Hệ thống nhắn tin. Đây là một "ngôn ngữ" phổ biến mà các lớp dưới và hệ thống phụ của các lớp đó sử dụng để giao tiếp với nhau. Trong trường hợp của tôi, đó là một phép liệt kê đơn giản dựa trên các thao tác có thể được thực hiện. Điều này đưa tôi đến điểm tiếp theo ...
Hãy nghĩ về các hoạt động hoặc các lệnh làm cơ sở cho việc thực hiện của bạn. Bạn muốn ứng dụng của bạn làm gì? Chia nó thành các hoạt động cơ bản nhất. Ví dụ: CreatProject, WriteNotes, SaveProject, LoadProject, v.v. GUI (hoặc các lớp Form) sẽ có một số sự kiện xảy ra (như nhấn nút). Mỗi hoạt động có một phương thức điều khiển liên quan đến nó. Trong trường hợp này, một cái gì đó như Thoát là quá đơn giản. Ứng dụng có thể được đóng lại từ lớp Form. Nhưng giả sử tôi muốn duy trì một số dữ liệu ứng dụng vào một tệp trước? Tôi sẽ gọi phương thức "Lưu" từ lớp trình điều khiển tương ứng trong phương thức nhấn nút của tôi.
Từ đó, bộ điều khiển sẽ gọi tập hợp hoạt động chính xác từ các lớp Service. Các lớp dịch vụ trong ứng dụng của tôi hoạt động như một giao diện cho lớp miền. Họ sẽ xác nhận đầu vào nhận được từ lệnh gọi phương thức điều khiển (và do đó từ GUI) và thao tác mô hình dữ liệu.
Khi xác thực và thao tác đối tượng tương ứng hoàn tất, phương thức dịch vụ sẽ trả về mã thông báo cho bộ điều khiển. Ví dụ , MessageCodes.SaveSuccess
. Cả hai lớp điều khiển và dịch vụ đều dựa trên các đối tượng miền và / hoặc tập hợp các hoạt động chung có thể được nhóm lại với nhau.
Ví dụ: FileMenuController
(hoạt động: NewProject, SaveProject, LoadProject) -> ProjectServices
(CreatProject, PersistProjectToFile, LoadProjectFromFile). Trường hợp Project
sẽ là một lớp miền trong mô hình dữ liệu của bạn. Các lớp Trình điều khiển và Dịch vụ trong trường hợp của tôi là các lớp không thể thực hiện được với các phương thức tĩnh.
Sau đó, bộ điều khiển nhận ra thao tác là hoàn thành un / thành công. Bây giờ, bộ điều khiển có hệ thống nhắn tin riêng mà nó sử dụng để tương tác với lớp trình bày, do đó phụ thuộc gấp đôi giữa các lớp Dịch vụ và Bản trình bày. Trong trường hợp này, một lớp được gọi ViewState
trong ViewModels
gói luôn được bộ điều khiển trả về GUI. Trạng thái này chứa thông tin như: " trạng thái bạn đã cố gắng đặt ứng dụng có hiệu lực không? ", " Một thông báo có thể đọc được của con người về hoạt động bạn đã cố thực hiện và tại sao nó lại hoặc không thành công (thông báo lỗi) " và một ViewModel
lớp.
Các ViewModel
lớp chứa dữ liệu có liên quan từ các lớp miền GUI sẽ sử dụng để cập nhật xem. Các mô hình khung nhìn này trông giống như các lớp miền nhưng trong trường hợp của tôi, tôi đã sử dụng các đối tượng rất mỏng . Về cơ bản, họ không có nhiều hành vi, chỉ chuyển tiếp thông tin về trạng thái cấp thấp hơn của ứng dụng. Nói cách khác, tôi KHÔNG BAO GIỜ sẽ tặng các lớp miền của mình cho lớp trình bày. Đây cũng là lý do tại sao Controllers
và Services
các gói chia lớp dịch vụ thành hai phần. Bộ điều khiển sẽ không bao giờ xử lý các lớp miền hoặc xác nhận trạng thái của chúng. Chúng chỉ hoạt động như một ranh giới chuyển đổi dữ liệu liên quan GUI thành dữ liệu liên quan đến miền mà các dịch vụ có thể sử dụng và ngược lại. Bao gồm logic dịch vụ trong bộ điều khiển sẽ dẫn đến rất béo bộ điều khiển, khó bảo trì hơn.
Tôi hy vọng điều này cung cấp cho bạn một điểm khởi đầu.