Chia sẻ các đối tượng DTO giữa các dịch vụ siêu nhỏ


15

TL; DR - Có thể chia sẻ thư viện POJO giữa các dịch vụ không?

Nói chung, chúng tôi muốn duy trì việc chia sẻ giữa các dịch vụ với giới hạn nghiêm ngặt nếu không có thể. Đã có một số tranh luận về việc dịch vụ chia sẻ dữ liệu có nên cung cấp thư viện khách cho khách hàng sử dụng hay không. Client-lib thường là tùy chọn cho một khách hàng của dịch vụ sử dụng và có thể sử dụng API theo bất kỳ cách nào họ muốn, có nên sử dụng lib-client hay sử dụng ngôn ngữ thay thế và sử dụng các khía cạnh chung của thư viện hay không.

Trong trường hợp của tôi - tôi đang xem xét một dịch vụ tạo ra một đối tượng dữ liệu. Giả sử đối tượng này là một PET. Nó KHÔNG phải là thực thể cơ sở dữ liệu, nhưng hoàn toàn là một POJO đại diện cho dữ liệu cơ bản. POJO này là những gì API đã xác định. Giả sử: Thú cưng - Tuổi, Trọng lượng, Tên, Chủ sở hữu, Địa chỉ, Loài, v.v.

Dịch vụ 1 - PetKeeper: Nó sẽ tạo ra thú cưng vì bất kỳ lý do gì và giữ lại tất cả dữ liệu và phải tham chiếu dịch vụ này để lấy thú cưng hoặc sửa đổi Pet, cho biết thay đổi tên hoặc thay đổi địa chỉ phải được thực hiện thông qua một API gọi đến dịch vụ này.

Dịch vụ 2 - PetAccessor: Dịch vụ này tập hợp thú cưng và kiểm tra xác thực

Dịch vụ 3,4 - Các cuộc gọi dịch vụ trung gian khác

Dịch vụ 5 - Inteface người dùng

Đây là rất tùy tiện nhưng điểm là đơn giản. Giao diện người dùng hoặc một số dịch vụ hướng tới người dùng muốn trình bày theo cách nào đó đối tượng "PET" này. Nó phải gọi qua API một dịch vụ, gọi một dịch vụ, gọi một dịch vụ, vv cho đến khi nó đến dịch vụ thu thập thông tin cần thiết và bắt đầu chuyển tiếp trở lại. Cuối cùng, dịch vụ UI có đối tượng PET để hiển thị.

Điều này khá phổ biến - nhưng với tâm lý tuyệt đối của chúng tôi, chúng tôi đã nhân đôi đối tượng PET trong mọi dịch vụ. Nguyên tắc DRY (không lặp lại chính mình) chỉ áp dụng cho mã bên trong một dịch vụ và không áp dụng trên các dịch vụ nhưng vấn đề vẫn còn đó. Điều gì xảy ra nếu chúng ta thêm một trường ... chúng ta phải sửa đổi 5 dịch vụ của POJO trong mỗi dịch vụ.

--OR-- Chúng tôi có thể cung cấp Thư viện đối tượng thú cưng chứa một số pojo từ API và mỗi dịch vụ có thể nhập / phụ thuộc vào thư viện. Không có sự phụ thuộc vào (các) dịch vụ, mà chỉ là thư viện chung. Tôi thích ý tưởng này để mỗi dịch vụ có cùng loại đối tượng và cập nhật dễ dàng hơn. Nhưng tôi lo ngại về các đối tượng của Chúa.

Các pro / con - thiết kế tốt nhất là gì? Bạn đã làm gì để truyền dữ liệu giữa các dịch vụ để giảm thiểu việc lặp lại các lớp POJO tương tự trong khi vẫn không kết nối?


Thần-đối tượng? en.wikipedia.org/wiki/God_object

@DaiKaixian: Chắc chắn bạn không gợi ý rằng OP đi với một đối tượng Chúa, phải không? Đó thường xuyên được coi là một mô hình chống.
Makoto

Tôi đồng ý với câu trả lời của @javaguy.

Và tôi cũng muốn nói, bạn có thể xem xét mô hình khách truy cập. vi.wikipedia.org/wiki/Visitor_potype . Tạo tất cả trường và setter / getter trong POJO và chia sẻ nó giữa microservice. Nếu bạn muốn thực hiện một số thao tác trên POJO trong các dịch vụ micros micros khác nhau, hãy viết một số khách truy cập.

Cảm ơn. Sự do dự của tôi khi có 'thư viện chung' này là nó sẽ phát triển. Và sẽ có những đối tượng trong đó chỉ có các dịch vụ 1 & 3 quan tâm, hoặc 2 & 4, hoặc tất cả, hoặc bất kỳ sự kết hợp nào ở đó. Một loại gói thư viện DTO chung có tất cả các DTO cho dù tôi sử dụng mẫu vistor hay DTO POJO đơn giản hay không. Điều này có được chấp nhận để bao gồm tất cả các đối tượng này nhưng để cố gắng duy trì nó tốt nhất có thể? Ít nhất các đối tượng được cung cấp cho bất kỳ ai cần chúng NẾU họ muốn sử dụng chúng ...

Câu trả lời:


5

Thiết kế nào tốt nhất?

Bạn có thể sử dụng lại cùng một đối tượng Pet DTO trong số các dịch vụ phụ trợ (xử lý logic nghiệp vụ điển hình), nhưng khi nói đến tầng trình bày (Giao diện người dùng), nói chung nên sử dụng FormBean (một loại đậu khác với các trường được thêm vào đối với logic trình bày) do đó sẽ có sự tách biệt rõ ràng giữa logic trình bày và logic kinh doanh .

Điều này là bắt buộc vì các dịch vụ phải được sử dụng lại và một dịch vụ có thể được hiển thị / tái sử dụng bởi nhiều điểm cuối / khác nhau (như frontend hoặc có thể là một dịch vụ web khác nhau, v.v.) và mỗi điểm cuối đó có thể yêu cầu các trường bổ sung sẽ được đưa vào bởi Bộ điều khiển hoặc lớp tương ứng (như bộ điều hợp) phía trên các dịch vụ.

Bạn đã làm gì để truyền dữ liệu giữa các dịch vụ để giảm thiểu việc lặp lại các lớp POJO tương tự trong khi vẫn không kết nối?

Nếu bạn sử dụng một bean duy nhất giữa các tầng kinh doanh và web thì bạn sẽ kết hợp chặt chẽ logic trình bày với logic nghiệp vụ , điều này không thực tế và cuối cùng bạn sẽ thay đổi các dịch vụ cho một yêu cầu trong Frontend (ví dụ như định dạng ngày khác để được hiển thị trong Giao diện người dùng). Ngoài ra, để thực hiện quá trình điền / sao chép dữ liệu này qua các bean (như DTO sang FormBean hoặc Viceversa), bạn có thể sử dụng các thư viện như Apache BeanUtils.copyProperties() hoặc Dozer để tránh mã soạn sẵn .


Tôi đồng ý lớp trình bày có lẽ nên giải tuần tự hóa tải trọng đến như một bean trình bày với các thuộc tính khác nhau khi cần. Nhưng nói chung, có thể sử dụng lại (các) đối tượng DTO tương tự trong tất cả các dịch vụ phụ trợ không? Chúng tôi thường cố gắng tách các gói DTO này thành các gói nhỏ hơn chỉ cho một vài dịch vụ cần chúng. Tôi mệt mỏi vì có một số ngăn kéo của gói thư viện DTO có DTO dành cho hơn 75 dịch vụ siêu nhỏ mà tất cả các dịch vụ đều phụ thuộc. Trừ khi điều đó ổn vì nó chỉ là các đối tượng DTO là tùy chọn ở nơi đầu tiên?

Có, rõ ràng bạn có thể sử dụng lại cùng một đối tượng DTO trên tất cả các loại dịch vụ phụ trợ giống như của bạn PetServicesđể tránh trùng lặp. Nhưng quan điểm của tôi là không kết hợp chặt chẽ giữa phụ trợ và frontend, đó là nó.
nhà phát triển

4

Nếu DTO đại diện cho cùng một thực thể kinh doanh trong tất cả các dịch vụ siêu nhỏ thì sẽ chỉ có một lớp, được chia sẻ giữa các dịch vụ. Nó (hầu như) không bao giờ đúng khi có mã trùng lặp cho cùng một đối tượng.


3
Chia sẻ DTO trên microservice là một cơn ác mộng. "Phiên bản này đã có lĩnh vực này chưa? Có lẽ nào?" Bạn sẽ kết thúc với một mớ hỗn độn thực sự sau một thời gian. Mã trùng lặp là tốt trong trường hợp này.
Mejmo

1

Cách tôi dự định thực hiện bây giờ, là mỗi gói dịch vụ chỉ có các DTO và đưa chúng vào Nexus dưới dạng jar lib. Khi dịch vụ khác cần những dịch vụ đó, nó sẽ nhận được DTO lib (s) dưới dạng phụ thuộc trong manve / gradle. Nếu phiên bản DTO mới được phát hành trên một dịch vụ, thì miễn là phiên bản cũ cũng được hỗ trợ cùng một lúc, vì vậy đừng phá vỡ tính tương thích ngược, phiên bản, v.v., vì vậy đây là khu vực phụ trợ. Ngoài ra, để ngăn chặn sự phụ thuộc tuần hoàn, tốt hơn hết bạn nên tách dịch vụ khỏi bao bì dto

Bây giờ hãy nhìn vào backend-to-frontend và ngược lại tôi không đồng ý với các nhận xét trước đó rằng UI là lớp trình bày là khác nhau. KHÔNG PHẢI VẬY!!! UI chỉ là một dịch vụ siêu nhỏ khác đối với tôi cũng tiêu thụ và tạo ra các sự kiện.

Hướng từ cuối đến đầu trước Những gì tôi làm là chuyển đổi POJO (dtos) sang giao diện và gói bản in thành NPM và tải chúng vào Nexus. Dự án dựa trên UI nodejs sau đó tiêu thụ và sử dụng chúng. Đây là cách phục vụ cho UI.

Hướng Frontend-to-backend Đối với UI cho các sự kiện của lớp dịch vụ Tôi chuyển đổi giao diện Typecript và chuyển đổi chúng thành POJO (dtos), đóng gói dưới dạng jar và tải lên Nexus (hoặc một số repo) dưới dạng jar để được sử dụng bởi các dịch vụ phụ trợ.

Các quy trình này được xử lý dễ dàng bởi các quy trình CI (Travis, Gitlab CI, v.v.)

Bất kỳ ý kiến ​​cho phương pháp này hoan nghênh.

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.