Trong mô hình MVC nên chứa mô hình phụ?


8

Một số nền tảng:

Một đồng nghiệp và bản thân tôi có những cách hiểu khác nhau về MVC, điều đó có nghĩa, với cùng một vấn đề, chúng tôi đang đưa ra các giải pháp hoàn toàn khác nhau. Anh ta đến từ nền Java, nơi mọi thành phần của MVC có thể mô hình hóa một đối tượng theo truyền thống và tôi đến từ nền Haskell và có ít hoặc không có kinh nghiệm với OOP.

Không gian vấn đề:

Vấn đề chúng tôi đang cố gắng để mô hình hóa hoạt động hơi giống như một môi trường máy tính để bàn. Chúng tôi có một khái niệm về phiên người dùng (có thể là thông tin đăng nhập, nền tảng máy tính để bàn của họ) và các quy trình trên máy tính để bàn của họ (ví dụ iTunes, Finder, v.v.) mà mỗi người có thuộc tính mô hình riêng (thu nhỏ, v.v.).

Chúng tôi đồng ý ở điểm sau: chúng tôi nghĩ rằng HMVC là đại diện tốt nhất. Chúng tôi đồng ý rằng chúng tôi có hai đối tượng MVC, Session(máy tính để bàn) và Process(ứng dụng) và chúng tôi không muốn Processcó một khái niệm về Sessionhoặc một liên kết ngược.

Tuy nhiên, khi chúng tôi không đồng ý với ý nghĩa cốt lõi của MVC và ảnh hưởng của nó đến nơi chúng tôi giữ danh sách các quy trình trên màn hình của người dùng .

Giải thích của anh ấy:

Ông lập luận một điểm rất hợp lệ mà theo truyền thống là dễ dàng mô hình hóa mã và trong hệ thống kết xuất của chúng tôi. Ông nói rằng danh sách các quy trình nên là một danh sách các ProcessControllerđối tượng trong SessionControllerđó lần lượt có các mô hình của chúng như các đối tượng riêng biệt bên trong chúng. Điều này có nghĩa là có một lượng đáng kể trạng thái trong cả hai SessionControllerSessionModelcó liên quan đến những gì SessionViewcần kết xuất.

Điều này dường như rất hài hòa với những gì chúng ta có thể đọc trên internet trong một tìm kiếm ngắn gọn.

Lời giải thích của tôi:

Giải thích của tôi đòi hỏi sự thay đổi kiến ​​trúc lớn nhất và có vẻ khó thực hiện hơn trong mã, nhưng tôi tin rằng nó đúng hơn về mặt khái niệm. Tôi muốn ai đó giải thích lý do tại sao không phải như vậy, hoặc đưa ra một mô hình khác (nếu không phải là MVC) phù hợp với cách giải thích này và nêu bật một số điểm mạnh và điểm yếu cho cả hai mẫu để chúng tôi có thể đưa ra quyết định sáng suốt nhất (không ai trong chúng tôi có một nền tảng vững chắc trong kiến ​​trúc phần mềm).

Tôi thấy MVC là một bộ ba với ba thành phần có thể hoán đổi cho nhau: the Model, the ControllerView. Điều này đồng ý với những gì tôi có thể đọc trên internet và một số nguồn sẽ nói những điều giống như 'lượt xem, bộ điều khiển và mô hình có cùng giao diện nên có thể thay thế cho nhau để tạo hiệu ứng khác nhau'. Cách tôi tưởng tượng điều này để làm việc như sau:

  • Khi bạn trao đổi mô hình, bạn đang thay đổi cách xác thực hoặc lưu trữ dữ liệu
  • Khi bạn trao đổi bộ điều khiển, bạn sẽ thay đổi cách trang hoạt động , nhưng không phải bất cứ điều gì có thể thay đổi nội dung dữ liệu nhận thức của trang
  • Khi bạn hoán đổi chế độ xem, bạn sẽ thay đổi cách hiển thị trang

Từ điều này, tôi lập luận rằng đưa ra bất kỳ ModelView, chỉ trao đổi bộ điều khiển không nên thay đổi dữ liệu mà trang ban đầu hiển thị vì bộ điều khiển chỉ thay đổi hành vi chứ không phải 'nội dung' của trang. Tôi nghĩ rằng điều này phù hợp với trực quan hóa khái niệm của bộ điều khiển như một 'bộ điều khiển trạm' trong hệ thống đường sắt, một kế hoạch của đường sắt như mô hình và biểu hiện vật lý thực tế và giao diện của các tuyến đường (theo các hương vị khác nhau, nói ' Real 'hoặc' Virtual 3D ') dưới dạng xem.

Đây là nơi chúng tôi không đồng ý:

Tôi lập luận rằng vì dữ liệu sẽ được hiển thị cho người dùng trong đó SessionViewbị thay đổi bởi các quy trình khác nhau trên máy tính để bàn (tôi mô hình hóa các quy trình là dữ liệu có liên quan ), SessionModelnên chứa danh sách các trường hợp ProcessModel. Điều này có nghĩa là việc sử dụng bất kỳ ngẫu nhiên nào SessionControllercó cùng một SessionViewkhái niệm sẽ hiển thị cùng một dữ liệu (các quy trình trên máy tính để bàn).

Ông lập luận rằng nó có ý nghĩa hơn đối với Modelviệc không bao giờ biết về một mô hình khác. Điều này có nghĩa là SessionControllersẽ có một danh sách các ProcessControllers bên trong nó và mỗi Controllerđối tượng có một liên kết đến mô hình của nó. Cho một SessionViewvà giống nhau SessionModelnhưng một SessionControllerdữ liệu khác nhau được hiển thị cho người dùng nên hoàn toàn khác nhau.

Vui lòng tranh luận cho / chống lại mỗi giải thích và giúp chúng tôi đạt được kết quả thông tin nhất.

Cảm ơn vì đã dành thời gian cho tôi!


1
Hoán đổi bộ điều khiển có thể khiến phương thức bộ điều khiển hiển thị một chế độ xem khác hoặc trả về một đối tượng khác. Vì vậy, đối số của bạn có thể chỉ có ý nghĩa nếu bộ điều khiển bạn đang trao đổi phù hợp với một giao diện / hợp đồng cụ thể. Do đó, không có gì đảm bảo rằng bộ điều khiển mới sẽ hiển thị cùng một dữ liệu cho chế độ xem; bộ điều khiển chỉ bắt buộc phải kết xuất hoặc trả về cái mà nó được lập trình để kết xuất hoặc trả về.
Robert Harvey

Vì vậy, điểm vào để kết xuất phải là bộ điều khiển chứ không phải khung nhìn (với bộ điều khiển làm đối số)?
kvanberendonck

1
Bạn, đến từ Haskell, nên liên quan đến các vấn đề sau: Tôi nghĩ rằng MVC chỉ là một mô hình trừu tượng về mối quan hệ giữa các phần của chương trình, nhưng phần nào nên đóng vai trò, mô hình hoặc bộ điều khiển phụ thuộc vào vấn đề bạn gặp phải . Tương tự, Lý thuyết Danh mục chỉ là một bộ quy tắc để giúp chính thức hóa mối quan hệ giữa các đối tượng, nhưng không có định nghĩa cứng nhắc nào về các đối tượng thực tế có thể được sử dụng với các quy tắc này. Bản thân CT có thể được chính thức hóa với CT. HMVC là một ví dụ điển hình cho ý tưởng đó, vì bạn có thể sử dụng MVC trong MVC (mặc dù nó không phải là loại đệ quy tương tự).
didierc

1
Ngoài ra còn có các quy tắc khác quy định cách viết mọi thứ: DRY, RẮN, KISS. Chúng không xung đột với MVC và chắc chắn nên được áp dụng nhiều (nếu không muốn nói là nhiều hơn).
didierc

Câu trả lời:


6

Chìa khóa trong việc hiểu MVC nằm ở sự phân tách trách nhiệm, vì MVC đơn giản là SRP được áp dụng cho mã UI. Nó phân tách dữ liệu nào sẽ được hiển thị, từ cách hiển thị dữ liệu đó, từ cách xử lý các sự kiện màn hình. Nhưng một chi tiết quan trọng (và thường bị bỏ qua) của định nghĩa ban đầu về MVC là nó được thiết kế cho mức độ chi tiết hơn nhiều. Chẳng hạn, bạn có các đối tượng ButtonModel, ButtonView và ButtonContoder, "chỉ" để hiển thị một nút duy nhất trên màn hình. Thiếu chi tiết này là nguyên nhân gây ra rất nhiều ý kiến ​​khác nhau về chủ đề này. Bạn có thể kiểm tra kiến trúc Java Swing để xem ý tôi là gì.

Quan điểm của MVC là cho phép thay đổi mã phục vụ cho từng trách nhiệm mà không ảnh hưởng đến mã cho các trách nhiệm khác. Chẳng hạn, bạn sẽ có thể chuyển đổi kết xuất (một thành phần trên) màn hình mà không cần phải chạm vào biểu diễn dữ liệu cũng như logic xử lý sự kiện. Vì vậy, ở một mức độ nào đó, điều này đi cùng với những gì bạn nói ở đây:

Từ điều này, tôi lập luận rằng đưa ra bất kỳ Mô hình và Chế độ xem nào, chỉ trao đổi bộ điều khiển không nên thay đổi dữ liệu mà trang ban đầu hiển thị vì bộ điều khiển chỉ thay đổi hành vi chứ không phải 'nội dung' của trang. Tôi nghĩ rằng điều này phù hợp với trực quan hóa khái niệm của bộ điều khiển như một 'bộ điều khiển trạm' trong hệ thống đường sắt, một kế hoạch của đường sắt như mô hình và biểu hiện vật lý thực tế và giao diện của các tuyến đường (theo các hương vị khác nhau, nói ' Real 'hoặc' Virtual 3D ') dưới dạng xem.

Tuy nhiên, trong ngữ cảnh của bạn, mức độ chi tiết bị tắt; bạn có một SessionView dường như chịu trách nhiệm cho toàn bộ màn hình. Ở cấp độ này, các trách nhiệm được kết hợp quá tách biệt hoàn toàn như dự định của MVC, do đó nó có thể không cung cấp đầy đủ lợi ích.

Vấn đề của bạn là phân tách ba trách nhiệm UI (kết xuất, dữ liệu và xử lý sự kiện) cho cả phiên và quy trình, tổng cộng là sáu. Do mức độ chi tiết của các thành phần (toàn màn hình), điều này trở nên không thể và gây ra sự bất hòa mà bạn thấy mình mắc phải.

Bạn muốn phân tách trách nhiệm kết xuất và xử lý sự kiện cho cả Phiên và Quy trình, nhưng bạn sẽ ghép dữ liệu của họ. Đồng nghiệp của bạn muốn tách dữ liệu, nhưng xử lý sự kiện.

Vì vậy, cuối cùng, đây là một vấn đề SRP. Cách của tôi là giảm mức độ chi tiết xuống đến mức bạn có thể tách biệt rõ ràng các Phiên từ Quy trình. Nếu bạn không thể làm điều đó do kinh tế, các bạn chỉ cần cân nhắc cả hai mặt của sự đánh đổi, chọn điều tồi tệ nhất và ký tắt nó là nợ kỹ thuật. Cuối cùng, đây là quyết định thiết kế nào. :)


Cảm ơn bạn đã dành thời gian và bình luận chu đáo. Chúng tôi có rất nhiều suy nghĩ về đây! Tôi hy vọng bạn không phiền nếu tôi bỏ ngỏ điều này một chút trước khi chọn câu trả lời vì không khuyến khích người khác chia sẻ POV của họ.
kvanberendonck

Tôi đã suy nghĩ về điều này ngày hôm nay và bắt gặp một câu hỏi thú vị: kết xuất sẽ trông như thế nào nếu các Quy trình nằm trong mô hình Phiên? Làm thế nào để một SessionView có quyền truy cập vào ProcessControllers để trao cho ProcessView?
kvanberendonck

1
Vâng, với MVC, hoặc bạn tách hoàn toàn các Phiên khỏi Quy trình (chi tiết hơn so với ví dụ của bạn) hoặc bạn tạo một Mô hình, Chế độ xem và Trình điều khiển duy nhất cho toàn màn hình, và coi các phiên và quy trình là một điều lớn (thô hơn). Vấn đề của bạn là mức độ chi tiết hiện tại của các đối tượng của bạn, nơi bạn cố gắng tách các thứ, nhưng nó không cho phép tách biệt rõ ràng. Các mẫu khác, chẳng hạn như MVP hoặc MVVM, hoạt động tốt hơn cho "toàn màn hình", trái ngược với MVC có nghĩa là cho các yếu tố nhỏ trên màn hình.
MichelHenrich
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.