Tôi nên đặt yêu cầu API ở đâu trong MVC?


25

Tôi đang xây dựng một ứng dụng web bằng cách sử dụng một mô hình MVC. Theo kiểu kiến ​​trúc này, chúng ta có thể thấy rằng tất cả các phương thức được sử dụng để tương tác với cơ sở dữ liệu đều được triển khai trong mô hình .

Nhưng điều gì xảy ra nếu tôi phải gọi một dịch vụ được tiếp xúc bởi những người khác trên web? Ví dụ: tôi muốn truy cập API Facebook để có được tất cả người theo dõi trang của mình, vậy tôi sẽ đặt các phương thức này ở đâu?

Rõ ràng khung nhìn không phải là một ý tưởng tốt vì mô-đun này được dành riêng cho bản trình bày, bộ điều khiển không nên được sử dụng để truy xuất dữ liệu nhưng mô hình thường chỉ dành riêng cho tương tác với cơ sở dữ liệu.

Vì vậy, bạn có thể cho tôi một số gợi ý về điều đó? Và làm ơn, bạn có thể cho tôi biết nếu tôi đang mắc một số lỗi về kiến ​​trúc MVC không?


2
Tôi nghĩ mọi người sẽ có thể cung cấp câu trả lời tốt hơn nếu bạn liệt kê một số thư viện và khung mà bạn đang sử dụng để hỗ trợ ứng dụng MVC của mình. Trong khi mô hình MVC là bất khả tri về công nghệ, không phải tất cả các khung đều tuân theo nó một cách rõ ràng. Hơn nữa, hầu hết các khung trưởng thành đã có tài liệu nổi bật và biết bạn đang sử dụng cái nào sẽ giúp bạn dễ dàng hướng dẫn bạn đến một lời giải thích có sẵn theo dòng suy nghĩ của bạn.
CLW

2
Cơ sở dữ liệu? Nguồn dữ liệu? Nó chỉ là dữ liệu.

2
Có rất nhiều ý kiến ​​về "MVC" được cho là gì, rằng câu hỏi này quá trừu tượng để trả lời.
RemcoGerlich

2
Ngoài ra, hãy xem xét việc gọi API từ mã Javascript frontend của bạn và hoàn toàn không để nó chạm vào công cụ "MVC" phụ trợ của bạn.
RemcoGerlich

@Remcogerlich đó là lý do tại sao tôi đề xuất bổ sung việc triển khai thực tế mà anh ấy đang xem xét. Anh ta có thể đối phó với một phụ trợ và triển khai mvc. Chúng ta có thể có một mô hình khác tại chỗ cũng giải thích rõ hơn những khác biệt này.
CLW

Câu trả lời:


37

Mô hình không giới hạn tương tác với cơ sở dữ liệu, mô hình chịu trách nhiệm lấy và thao tác dữ liệu.

Vì vậy, theo quan điểm và bộ điều khiển của bạn, sẽ không có gì khác biệt, nếu dữ liệu đến từ cơ sở dữ liệu hoặc từ dịch vụ web hoặc thậm chí là hoàn toàn ngẫu nhiên, do đó bạn nên thực hiện theo mô hình.

MVC là một mẫu trình bày, chỉ tách các lớp biểu diễn khác nhau.

Điều đó không có nghĩa, mô hình đó phải là một mớ hỗn độn của mã spaghetti. Bản thân mô hình của bạn cũng có thể được xếp lớp, nhưng bộ điều khiển không nên biết, dữ liệu đến từ đâu.

Một phương thức công khai trong mô hình của bạn có thể được cấu trúc như thế này (Mã giả), có thể được gọi bởi bộ điều khiển của bạn:

public MyDataClass getData(int id) {
    WebServiceData wsData = WebService->getData(id);
    DatabaseData dbData = ORM->getData(id);
    return new MyDataClass(wsData, dbData);
}

WebServiceORMcó thể cần phải là các phiên bản của giao diện có thể được thay thế bằng giả thông qua việc tiêm phụ thuộc, nhưng bộ điều khiển và khung nhìn của bạn không phải thay đổi cho mục đích thử nghiệm.


8
Mô hình không nên có bất kỳ logic nào và do đó không được tương tác trực tiếp với bất cứ điều gì. Mẫu MVC rõ ràng yêu cầu tất cả logic được đặt vào bộ điều khiển. Các bộ điều khiển này nên liên hệ với DB, API, v.v ... và cập nhật mô hình khi cần thiết. Điều này giữ cho công nghệ mô hình của bạn không tin tưởng và đảm bảo nó hoạt động không khác gì một cơ chế lưu trữ có thể được chuyển đến các chế độ xem khác nhau để trình bày và bộ điều khiển để thao tác bổ sung.
CLW

3
@CLW: Mô hình! = Mô hình dữ liệu. Thông tin chi tiết có thể được tìm thấy ở một nơi khác, ví dụ stackoverflow.com/a/14045514/124983
Residuum

2
@CLW: logic nghiệp vụ không nên có trong M, V hoặc C. Mô hình là sự trừu tượng hóa của một kho lưu trữ dữ liệu, các khung nhìn và bộ điều khiển là giao diện người dùng của bạn. Chúng là thiết bị ngoại vi của ứng dụng thực tế mà bạn đang xây dựng, phải là "chỉ mã", mà không cần phải biết về những thứ như cơ sở dữ liệu và web.
RemcoGerlich

2
Phần "mô hình" được diễn giải theo hàng trăm cách khác nhau. Tôi luôn được dạy rằng một mô hình là một đại diện. Một mô hình tàu hỏa là một đại diện của một chuyến tàu thực sự, với các bộ phận chuyển động nhỏ di chuyển giống như một chiếc xe lửa thực sự. Tương tự, mô hình trong ứng dụng của bạn là đại diện cho các hệ thống và quy trình bạn đang xây dựng phần mềm của mình để thay thế. Như vậy, mô hình có hành vi . Hành vi đó kết hợp "logic kinh doanh" của bạn. Do đó, khi bạn bỏ qua quyền truy cập, giao diện người dùng và giao diện dữ liệu CRUD thuần túy, những gì còn lại có lẽ là "mô hình" của bạn - các lớp miền, quy tắc kinh doanh, v.v.
anaximander

1
@RemcoGerlich Tôi không nói gì về logic kinh doanh. Tôi chỉ đơn giản tuyên bố rằng vì hầu hết các cách hiểu về cuộc gọi MVC cho mô hình không có gì khác hơn là một cấu trúc đơn giản đại diện cho trạng thái ứng dụng của bạn, rằng không nên đặt trách nhiệm liên hệ với DB, API, v.v. logic miễn phí. Nhiệm vụ của giao tiếp với cơ sở dữ liệu phải thuộc về bộ điều khiển hoặc đối tượng khác do bộ điều khiển quản lý.
CLW

12

Có một sự hiểu lầm chung (cố ý?) Về M, V và C là gì. Không phải về vai trò họ đảm nhận, nhưng họ gì .

Trong định nghĩa GUI gốc của máy tính để bàn về MVC, chúng là các mô-đun . Thông thường, một ứng dụng có một vài trong số chúng, đôi khi hoạt động theo bộ ba, đôi khi có nhiều khung nhìn và mô hình khác nhau mà một vài bộ điều khiển có thể trộn và khớp.

Trong các khung web, OTOH, chúng có xu hướng được xem như là các lớp , trong đó chúng chỉ là một lớp và chủ yếu đề cập đến việc bao gồm một mức độ trừu tượng phụ: "lớp mô hình trừu tượng hóa cơ sở dữ liệu", "lớp khung nhìn thực hiện trình bày", "trình điều khiển lớp xử lý đầu vào của người dùng ".

Vì vậy, tôi muốn nói rằng bạn đã có một mô hình, dành riêng cho việc tương tác với cơ sở dữ liệu và bây giờ chỉ cần tạo một mô hình khác , để đối phó với API nguồn của bạn. Nếu bạn làm cho chúng giống nhau nhất có thể, thì hầu hết bộ điều khiển và mã xem có thể hoạt động trơn tru với một trong hai mô hình.


1
Đồng ý: (Các) mô hình luôn được coi là toàn bộ miền vấn đề. Trong các ứng dụng phức tạp, nó luôn được coi là phần lớn của mã. Chúng bao gồm tất cả các mã sẽ không thay đổi nếu bạn thay đổi Giao diện người dùng (giả sử, từ trang web sang GUI hoặc thậm chí ứng dụng dòng lệnh). Hãy nghĩ về một trình biên dịch. Chỉ một phần rất nhỏ của mã sẽ thay đổi nếu bạn đi từ UI dòng lệnh sang GUI hoặc thậm chí là giao diện người dùng web. Tất cả can đảm của một ứng dụng như vậy là các mô hình.
Kevin Cathcart

1
Trong thuật ngữ sử dụng Smalltalk ban đầu, mọi điều khiển UI trong giao diện đều có mô hình, khung nhìn và bộ điều khiển riêng.
RemcoGerlich

5

Một phần của khó khăn với bất kỳ cuộc thảo luận nào về MVC là các nhóm khác nhau đã đồng ý chọn nó để có nghĩa là những thứ khác nhau. Việc triển khai MVC được sử dụng trong một ứng dụng Rails sẽ gần như không thể nhận ra đối với người viết ứng dụng Swing. Trong phạm vi mà MVC vẫn là một thứ được xác định rõ ràng, nó tập hợp nhiều hơn các nguyên tắc hướng dẫn (tách ứng dụng cốt lõi khỏi biểu diễn trực quan của nó, cung cấp các cơ chế linh hoạt để cho phép cả hai được kết nối với nhau), có thể được thực hiện theo nhiều cách khác nhau cách.

Thật vậy, có xu hướng đặt cho các thiết kế khác nhau có nguồn gốc từ MVC khác nhau (xem bài viết này của Martin Fowler để biết một số thảo luận về điều này), hoặc thậm chí từ bỏ việc đặt tên chính xác - ví dụ, AngularJS tự mô tả như là một Model-View-Any khuôn khổ.

Vì vậy, thật khó để trả lời mà không biết bạn đang làm việc với phiên bản "MVC" nào. Tuy nhiên, một yêu cầu API thường là một phần của ứng dụng cốt lõi (phần không nên thay đổi nếu bạn quyết định sử dụng một biểu diễn trực quan khác), trong nhiều triển khai sẽ được chứa hoàn toàn trong mô hình.


2

Ở đây , mô hình được mô tả như thế này:

Một mô hình lưu trữ dữ liệu được truy xuất đến bộ điều khiển và hiển thị trong khung nhìn. Bất cứ khi nào có sự thay đổi dữ liệu, nó sẽ được cập nhật bởi bộ điều khiển.

Tôi muốn nói rằng bộ điều khiển bao gồm logic gọi dịch vụ hoặc gọi một Serviceđối tượng riêng biệt . Nếu dịch vụ là riêng biệt, bạn có thể dễ dàng tạo các thử nghiệm hơn, giả sử, nếu không có kết nối với dịch vụ qua mạng, một số TestServicecó thể cung cấp phản hồi từ Serviceđịa phương.

Ngoài ra kiểm tra câu trả lời này cho thấy Bộ điều khiển gọi dịch vụ.


2

Mô hình của bạn sẽ không bao giờ chứa bất kỳ mã thực tế nào và nên được xem như là một thông điệp hoặc một cấu trúc được sử dụng để quản lý nội dung được điều khiển bởi bộ điều khiển và được hiển thị bởi khung nhìn.

Bộ điều khiển của bạn phải chịu trách nhiệm liên hệ với bất kỳ API, cơ sở dữ liệu, dịch vụ, v.v ... yêu cầu thay đổi và quản lý mọi cập nhật cần thiết cho mô hình.

Toàn bộ sức mạnh của mẫu MVC là nó tách logic (bộ điều khiển) khỏi chế độ xem và trạng thái (mô hình). Khi làm như vậy, bây giờ bạn được đảm bảo rằng chỉ có mã trong bộ điều khiển có thể tạo hiệu ứng phụ vì chế độ xem và mô hình đơn giản là không được phép thực hiện thay đổi.

Nó cũng cho phép tái sử dụng mã tốt hơn vì một mô hình có thể được chia sẻ giữa các bộ điều khiển và khung nhìn khác nhau.


4
Tôi nghĩ khi bạn nói "mô hình" ở đây, bạn đang đề cập đến "viewmodel", IMO là một điều riêng biệt. Chế độ xem đưa dữ liệu từ bộ điều khiển vào chế độ xem và như vậy là chi tiết triển khai của Chế độ xem hoặc khía cạnh giao tiếp giữa Chế độ xem và Trình điều khiển không thực sự phù hợp với (tùy thuộc vào cách bạn nhìn thấy). "Mô hình" trong MVC đề cập đến một mô hình hệ thống - đại diện cho hệ thống kết hợp dữ liệu, cấu trúc và hành vi của nó. Mô hình là trạng thái và logic; Bộ điều khiển là nguyên nhân khiến logic chạy và trạng thái thay đổi khi Chế độ xem được thao tác.
anaximander

@anaximander Không, tôi đang đề cập đến Mô hình theo cách hiểu khá nghiêm ngặt về MVC (xem Wikipedia, Microsoft MVC, các mẫu Thiết kế Đầu tiên, v.v.) Trong các trường hợp đó, Mô hình không có gì khác hơn là một cấu trúc đơn giản để truyền dữ liệu xung quanh và không có thứ gọi là viewmodel. Mặc dù triển khai Microsoft MVC có thêm các thuộc tính khác nhau cho mô hình, nhưng điều này là thuận tiện hơn bất cứ điều gì. Cuối cùng, mục đích của mẫu MVC là tạo điều kiện thực hành tốt việc tách mã và hạn chế các tác dụng phụ.
CLW

1

Có thể thoát khỏi đây, nhưng đây là cách tôi cảm nhận về WebApps và làm việc với API từ xa [phức tạp] trong nhiều trường hợp:

Tôi sẽ làm cho nó một lớp (tức là một thư viện các phương thức giảm thiểu dữ liệu) thay vì mô hình (nghĩa là ngăn xếp các hàm giảm thiểu dữ liệu). Có vẻ như nó sẽ hoạt động minh bạch hơn, logic / lược đồ hơn và bạn có thể sử dụng nó bất cứ nơi nào mà không cần tải-> gọi chính mô hình / bộ điều khiển mỗi khi bạn muốn sử dụng nó. Logic vẫn được tách ra, datapoint vẫn linh hoạt và dường như mở rộng hơn cho khả năng tương tác trong các trường hợp lạ như xếp chồng clientAJAX-> appJSON-> appLIB-> remoteAPI-> remoteJSON vv để thăm dò điểm cuối một cách gián tiếp.

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.