mẫu để chia sẻ các đối tượng giữa API và ứng dụng


9

Tôi đang có những nghi ngờ nghiêm trọng về thiết kế cho ứng dụng Web của mình.

Tôi muốn tách logic nghiệp vụ khỏi giao diện vì vậy tôi đã tạo một API Web xử lý tất cả các yêu cầu tới cơ sở dữ liệu.

Đó là API Web ASP.NET với khung Entity và một đơn vị công việc và mẫu kho lưu trữ chung. Cho đến nay, mọi thứ đều tốt.

VẤN ĐỀ

Nơi tôi cần trợ giúp là tôi không thể tìm ra cách chia sẻ đối tượng hiệu quả giữa API và ứng dụng.

Tôi không muốn tuần tự hóa trực tiếp đối tượng thực thể, tôi nghĩ rằng đó sẽ là một thực tiễn tồi bởi vì nếu mô hình thực thể thay đổi, tôi có thể kết thúc việc tuần tự hóa các đối tượng lớn mà không có lý do.

Làm thế nào nó được thực hiện bây giờ

Vì giao diện của tôi là ứng dụng ASP.NET Web trong C # và API của tôi ở C #, tôi đã tạo một thư viện chung với định nghĩa về tất cả các lớp mà tôi muốn chia sẻ giữa chúng.

Tôi biết rằng giải pháp đó sẽ không hoạt động khi tôi sẽ phát triển một ứng dụng Android, tôi sẽ phải tạo lại các lớp của mình trong Java nhưng đó không phải là vấn đề lớn nhất của tôi.

Vấn đề là tôi cảm thấy như tôi luôn chuyển đổi các đối tượng của mình.

THÍ DỤ

Đây là một ví dụ về quy trình làm việc của tôi:

Tôi bắt đầu với một mô hình với tất cả các đối tượng và chú thích dữ liệu cho biểu mẫu của mình sau đó người dùng sẽ POST mô hình đó cho bộ điều khiển.

Trong bộ điều khiển tôi phải chuyển đổi mô hình này thành một lớp trong thư viện chung sau đó gửi đối tượng đó đến API của tôi.

Sau đó, một bộ điều khiển trong API của tôi bắt cuộc gọi và chuyển đổi đối tượng đó thành đối tượng thực thể để cập nhật cơ sở dữ liệu.

Vậy là tôi có 3 lớp.

  1. Mô hình cho chế độ xem với tất cả chú thích dữ liệu để xác thực (Máy khách)
  2. Các lớp thư viện chung để chia sẻ các đối tượng (DLL)
  3. Các lớp thực thể (API)

Tôi có cảm giác rằng tôi làm điều gì đó thực sự sai. Có điều gì thanh lịch hơn? Tôi muốn đảm bảo rằng tôi có một giải pháp tốt cho vấn đề này trước khi dự án trở nên quá lớn.


Nếu câu hỏi của tôi không rõ ràng, đừng ngần ngại đặt câu hỏi.
Marc

Đối với tôi không rõ bạn đã triển khai kiến ​​trúc nào (có thể đó là từ ngữ .net đánh đố tôi) - đó có phải là kiến ​​trúc 3 tầng: máy khách, máy chủ, db không?
Andy

Có, tôi có một ứng dụng web sử dụng API Web. API là cái có logic nghiệp vụ với cơ sở dữ liệu.
Marc

Câu trả lời:


12

Tôi biết có vẻ như bạn đang chuyển đổi các đối tượng qua lại mọi lúc giữa các đối tượng cơ sở dữ liệu, các đối tượng truyền dữ liệu, các đối tượng khách của bạn với logic xác thực, v.v. nhưng tôi nói rằng không, bạn không làm gì sai cả .

Mỗi đối tượng này có thể đại diện cho cùng một đơn vị thông tin, nhưng chúng có trách nhiệm rất khác nhau. Đối tượng cơ sở dữ liệu là giao diện giao tiếp của bạn với cơ sở dữ liệu và nên được giữ trong lớp cơ sở dữ liệu vì nó có thể có hoặc không có các chú thích siêu dữ liệu cơ sở dữ liệu khác nhau và / hoặc các chi tiết không cần thiết về việc triển khai cơ sở dữ liệu trong đó.

Đối tượng chuyển dữ liệu của bạn là giao diện giao tiếp với người tiêu dùng API của bạn. Chúng nên càng sạch càng tốt để tạo điều kiện cho việc tiêu thụ dễ dàng từ các ngôn ngữ / nền tảng khác nhau. Điều này có thể áp đặt một số hạn chế nhất định về cách những giao diện này hoạt động và tùy thuộc vào những gì người tiêu dùng API bạn muốn hỗ trợ.

Các đối tượng khách hàng của bạn với logic xác thực thực sự không phải là một phần của dự án API của bạn, chúng là một phần của dự án tiêu dùng của bạn. Chúng không thể giống như các đối tượng truyền dữ liệu trong trường hợp này vì bạn đang thêm logic cụ thể của máy khách (trong trường hợp này là thuộc tính xác thực) trên chúng mà máy chủ không biết gì về (và không nên biết gì về!) đếm những đối tượng này như một phần của API của bạn, bởi vì chúng thực sự không phải vậy. Chúng là ứng dụng dành riêng cho người tiêu dùng và một số ứng dụng sử dụng API của bạn thực sự có thể không cần tạo các đối tượng này và cũng có thể tồn tại trên các đối tượng truyền dữ liệu của bạn. Ví dụ: nếu bạn không có nhu cầu xác thực, bạn sẽ không cần thêm một lớp đối tượng hoàn toàn giống với các đối tượng truyền dữ liệu của bạn.

Đối với tôi, có vẻ như mỗi trong số ba loại đối tượng ánh xạ rất độc đáo đến một trách nhiệm duy nhất là mã hóa sạch và thực hành tốt. Đáng buồn thay, mã sạch và thực hành tốt đôi khi có nghĩa là bạn đang viết rất nhiều mã bổ sung và nhảy qua các vòng bổ sung "chỉ vì". Và trong khi mã hóa, có thể khó đánh giá cao giá trị mà nó mang lại cho bạn - nhưng ngay khi bạn phát hành ứng dụng của mình và bắt đầu hỗ trợ hoặc thêm các tính năng mới cho phiên bản tiếp theo thì có lẽ bạn sẽ bắt đầu đánh giá cao rằng bạn đã dành thời gian để tách những mối quan tâm đúng cách ở nơi đầu tiên. (Không đề cập đến việc bạn '

Tôi cũng ghét viết mã chuyển đổi giữa các loại đối tượng khác nhau như thế này, nhưng giải pháp của tôi thường là một trong những điều sau đây:

  • Sử dụng một thư viện thực hiện hầu hết các chuyển đổi đối tượng nặng cho bạn - ví dụ: nếu bạn sử dụng C #, bạn có thể sử dụng thư viện AutoMapper tuyệt vời ( http://automapper.org/ ). Tôi tin rằng có một vài thư viện khác như thế này, nhưng AutoMapper là thư viện mạnh nhất mà tôi từng thấy cho đến nay.
  • Nếu bạn không thể tìm thấy thư viện giúp bạn chuyển đổi đối tượng, hãy viết một bộ phương thức tiện ích để chuyển đổi giữa chúng. Điều này có thể hấp dẫn, nhưng về lâu dài, hãy viết phương thức chuyển đổi vào lần đầu tiên bạn cần chuyển đổi thứ gì đó - đừng chờ đợi.

Cảm ơn bạn đã giải thích nhưng tôi vẫn thấy khó hiểu một cái gì đó. Tôi không hiểu tại sao lớp truyền dữ liệu không có bất kỳ xác nhận nào? Điều gì xảy ra nếu tôi quên một số xác nhận cho ứng dụng di động tiếp theo của mình? Ít nhất nó sẽ không xác nhận khi tôi gọi API thay vì thực hiện một ngoại lệ trong mô hình cơ sở dữ liệu của mình. Tôi không chắc là tôi hiểu.
Marc

1
Tôi không nói rằng bạn không nên xác nhận ở cấp API. Thành thật mà nói, đó là nơi quan trọng nhất để xác nhận. Xác thực trong ứng dụng của bạn chỉ là một "tính năng hay" để giúp người dùng của bạn không mắc lỗi, xác thực các đối tượng chuyển dữ liệu của bạn là để loại bỏ dữ liệu độc hại và sai sót. Vì đây là các trường hợp sử dụng khác nhau, tuy nhiên, bạn có thể cần sử dụng các khung xác thực khác nhau (bạn sẽ sử dụng các khung xác thực khác nhau nếu ứng dụng của bạn và api của bạn không được viết bằng cùng một ngôn ngữ) và bạn có thể xác thực những thứ hơi khác nhau ở mỗi cấp độ (Tiếp trong bình luận tiếp theo)
wasatz

1
Vì vậy, bạn nên xác nhận các đối tượng chuyển dữ liệu của bạn. Nhưng bạn cũng nên đảm bảo rằng cách bạn xác nhận chúng không vô tình đưa ra bất kỳ sự phụ thuộc nào vào bất kỳ khuôn khổ nào khác . Và tất nhiên, như tôi đã nói trước đó, bạn thực sự không thể chắc chắn rằng các đối tượng truyền dữ liệu của bạn đã được xác thực hoàn toàn hay chúng đã được xác thực bởi cùng một khung - vì vậy bạn phải "xác nhận hai lần".
wasatz

2
Chủ yếu, bạn nên cố gắng xem ứng dụng và API của mình là hai ứng dụng hoàn toàn khác nhau và riêng biệt. Bạn có thể làm lệch chúng cùng một lúc, và chúng có thể nằm trong cùng một dự án giải pháp / nhật thực trực quan. Nhưng chúng thực sự là hai chương trình hoàn toàn riêng biệt. Khi bạn đang làm việc trong ứng dụng của mình, hãy cố gắng "quên" rằng bạn là người đã tạo API và sử dụng nó giống như bạn làm với API bên thứ 3 bình thường. Bằng cách đó, bạn sẽ có cơ hội tốt hơn để xem người khác sẽ cảm thấy như thế nào khi sử dụng API của bạn và sửa những phần tồi tệ nhất từ ​​sớm.
wasatz

1
Và điều tương tự cũng đúng khi làm việc với dự án API của bạn, hãy thử tưởng tượng rằng bạn đang viết một dịch vụ mà nhiều nhà phát triển bên thứ 3 sẽ sử dụng. Cố gắng đừng suy nghĩ quá nhiều về ứng dụng hiện tại của bạn, mà hãy chú ý nhiều hơn đến "tôi đang cung cấp dịch vụ gì" và cho rằng mọi người đang sử dụng API của bạn (bao gồm cả chính bạn) là những kẻ xấu đang cố giết máy chủ của bạn và làm cho bạn xóa toàn bộ cơ sở dữ liệu của bạn.
wasatz
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.