TL; DL
Việc thiếu các tính năng ngôn ngữ của Java so với C # cũng như các cân nhắc về khả năng khám phá đã khiến chúng tôi đưa các toán tử nguồn và trung gian vào các lớp lớn.
Thiết kế
Rx.NET ban đầu được phát triển trong C # 3.0 có hai tính năng quan trọng: phương thức mở rộng và lớp một phần. Cái trước cho phép bạn định nghĩa các phương thức cá thể trên các loại khác mà sau đó dường như là một phần của loại mục tiêu đó trong khi các lớp một phần cho phép bạn chia các lớp lớn thành nhiều tệp.
Cả hai tính năng này đều không có hoặc có trong Java, do đó, chúng tôi phải tìm cách để RxJava có thể sử dụng đủ tiện lợi.
Có hai loại toán tử trong RxJava: giống như nguồn được biểu thị bằng các phương thức tĩnh của nhà máy và giống như trung gian được biểu diễn bằng các phương thức thể hiện. Cái trước có thể sống trong bất kỳ lớp nào và do đó chúng có thể được phân phối dọc theo nhiều lớp tiện ích. Cái sau đòi hỏi một thể hiện để được làm việc trên. Về khái niệm, tất cả những thứ này có thể được thể hiện thông qua các phương thức tĩnh với ngược dòng là tham số đầu tiên.
Tuy nhiên, trên thực tế, việc có nhiều lớp nhập khiến người dùng mới phát hiện ra tính năng bất tiện (hãy nhớ rằng, RxJava phải đưa một khái niệm mới và mô hình lập trình vào Java) cũng như việc sử dụng các toán tử trung gian đó phần nào là một cơn ác mộng. Do đó, nhóm ban đầu đã đưa ra cái gọi là thiết kế API trôi chảy: một lớp chứa tất cả các phương thức tĩnh và cá thể và tự thể hiện một giai đoạn nguồn hoặc xử lý.
Do tính chất hạng nhất của lỗi, hỗ trợ đồng thời và bản chất chức năng, người ta có thể đưa ra tất cả các loại nguồn và biến đổi liên quan đến dòng phản ứng. Khi thư viện (và khái niệm) phát triển kể từ thời Rx.NET, ngày càng có nhiều toán tử tiêu chuẩn được thêm vào, điều này về bản chất làm tăng số lượng phương thức. Điều này dẫn đến hai khiếu nại thông thường:
- Tại sao có nhiều phương pháp?
- Tại sao không có phương pháp X giải quyết vấn đề rất đặc biệt của tôi?
Viết toán tử phản ứng là nhiệm vụ khó khăn không nhiều người thành thạo trong những năm qua; hầu hết người dùng thư viện điển hình không thể tự tạo toán tử (và thường thì họ không thực sự cần thiết để thử). Điều này có nghĩa là chúng ta, theo thời gian, thêm các toán tử tiếp theo vào bộ tiêu chuẩn. Ngược lại, chúng tôi đã từ chối nhiều nhà khai thác hơn do quá cụ thể hoặc đơn giản là sự tiện lợi không thể tự nâng trọng lượng của nó.
Tôi muốn nói rằng thiết kế của RxJava đã phát triển một cách hữu cơ và không thực sự tuân theo các nguyên tắc thiết kế nhất định như RẮN. Nó chủ yếu được điều khiển bởi việc sử dụng và cảm nhận về API thông thạo của nó.
Các mối quan hệ khác với Rx.NET
Tôi đã tham gia phát triển RxJava vào cuối năm 2013. Theo như tôi có thể nói, các phiên bản 0.x ban đầu phần lớn là sự tái hiện hộp đen trong đó tên và chữ ký của các Observable
nhà khai thác Rx.NET cũng như một vài quyết định kiến trúc được sử dụng lại. Điều này liên quan đến khoảng 20% các nhà khai thác Rx.NET. Khó khăn chính trước đó là độ phân giải của sự khác biệt về ngôn ngữ và nền tảng giữa C # và Java. Với nỗ lực rất lớn, chúng tôi đã quản lý để triển khai nhiều toán tử mà không cần nhìn vào mã nguồn của Rx.NET và chúng tôi đã chuyển các mã phức tạp hơn.
Theo nghĩa này, cho đến RxJava 0.19, chúng tôi Observable
tương đương với Rx.NET IObservable
và các Observable
phương thức mở rộng đồng hành của nó . Tuy nhiên, vấn đề được gọi là áp suất ngược đã xuất hiện và RxJava 0.20 bắt đầu phân kỳ khỏi Rx.NET ở cấp độ giao thức và kiến trúc. Các toán tử có sẵn đã được mở rộng, nhiều người đã biết áp lực và chúng tôi đã giới thiệu các loại mới: Single
và Completable
trong kỷ nguyên 1.x, không có đối tác trong Rx.NET như bây giờ.
Nhận thức về áp lực làm phức tạp mọi thứ một cách đáng kể và 1.x Observable
đã nhận nó như một suy nghĩ lại. Chúng tôi thề trung thành với khả năng tương thích nhị phân nên việc thay đổi giao thức và API hầu như không thể.
Có một vấn đề khác với kiến trúc của Rx.NET: không thể hủy bỏ đồng bộ vì để làm điều đó, người ta cần Disposable
phải trả lại trước khi toán tử bắt đầu thực thi. Tuy nhiên, các nguồn như Range
háo hức và không trở lại cho đến khi họ hoàn thành. Vấn đề này có thể được giải quyết bằng cách tiêm một Disposable
cái Observer
thay vì trả lại từ đó subscribe()
.
RxJava 2.x được thiết kế lại và thực hiện lại từ đầu dọc theo các dòng này. Chúng tôi có một loại nhận biết áp lực riêng biệt, Flowable
cung cấp cùng một bộ toán tử như Observable
. Observable
không hỗ trợ backpressure và có phần tương đương với Rx.NET Observable
. Trong nội bộ, tất cả các loại phản ứng tiêm xử lý hủy bỏ của họ cho người tiêu dùng của họ, cho phép hủy bỏ đồng bộ để làm việc hiệu quả.