태그 보관물: class-design

class-design

RxJava 클래스 Flowable이 합법적으로 460 개의 메소드를 가질 수 있습니까? 아닌 Microsoft

Java의 ReactiveX 구현 인 RxJava ( RxReactive Extensions 라고도 함)를 막 시작했습니다 . 실제로 나를 놀라게 한 것은 RxJava의 Flowable 클래스 거대한 크기였습니다 . 460 개의 메소드가 있습니다!

공정하게 :

  • 오버로드 된 메소드가 많으므로 총 메소드 수에 상당한 영향을 미칩니다.

  • 아마도이 클래스는 분리되어야하지만 RxJava에 대한 나의 지식과 이해는 매우 제한적입니다. RxJava를 만든 사람들은 분명히 매우 똑똑하며, 많은 방법으로 Flowable 을 만들기 위해 유효한 인수를 제공 할 수 있습니다 .

반면에 :

  • RxJava이의 Java 구현 마이크로 소프트의 반응성 확장 , 그리고 심지어이없는 유동성 이 맹목적으로 기존의 클래스를 포팅하고 자바를 구현하는 경우가 아니라, 그래서 클래스를.

  • [ 업데이트 : 이탤릭체의 이전 요점은 사실 부정확합니다. 400 개가 넘는 메서드를 가진 Microsoft의 Observable 클래스가 RxJava의 Observable 클래스 의 기초로 사용되었으며 FlowableObservable 과 비슷 하지만 대량의 데이터에 대한 역 압력을 처리합니다. RxJava 팀 기존 클래스를 포팅했습니다. 이 포스트는 RxJava의 Flowable 클래스가 아닌 Microsoft 의 Observable 클래스 의 원래 디자인에 도전 한 것 입니다.]

  • RxJava는 3 년이 조금 넘었 기 때문에 ( SOLID ) 클래스 디자인 원칙 에 대한 지식이 부족하여 코드가 잘못 디자인 된 예는 아닙니다 ( Java의 초기 릴리스와 마찬가지로).

Flowable 만큼 큰 클래스 의 경우 디자인이 본질적으로 잘못된 것처럼 보이지만 그렇지 않을 수도 있습니다. 이 SE 질문에 대한 답변 하나 의 클래스 메소드 수에 대한 제한은 무엇입니까? 그 대답은 ” 필요한 방법이 많다 “는 것입니다.

언어에 관계없이이를 지원하기 위해 정당한 수의 메소드가 필요한 클래스가 분명히 있습니다. 클래스는 더 작은 것으로 쉽게 분류되지 않고 상당한 수의 특성과 속성을 갖기 때문입니다. 예를 들어 문자열, 색상, 스프레드 시트 셀, 데이터베이스 결과 세트 및 HTTP 요청입니다. 클래스가 그러한 것들을 표현할 수있는 수십 개의 메소드를 가지고 있다고해서 무리가없는 것 같습니다.

그러나 Flowable에는 실제로 460 개의 메소드가 필요 합니까 , 아니면 너무 클 경우 클래스 설계가 잘못 되었습니까?

[분명히 말하면 :이 질문은 일반적으로 God 객체가 아닌 RxJava의 Flowable 클래스 와 관련이 있습니다 .]



답변

TL; DL

C #에 비해 Java의 언어 기능이 부족하고 검색 가능성을 고려하여 소스 및 중간 연산자를 큰 클래스에 배치했습니다.

디자인

원본 Rx.NET은 확장 메서드와 부분 클래스라는 두 가지 중요한 기능이있는 C # 3.0으로 개발되었습니다. 전자를 사용하면 다른 유형에서 인스턴스 메소드를 정의한 다음 해당 유형의 대상으로 보이는 반면 부분 클래스를 사용하면 큰 클래스를 여러 파일로 분할 할 수 있습니다.

이러한 기능 중 어느 것도 Java에 존재하지 않거나 존재하지 않으므로 RxJava를 충분히 편리하게 사용할 수있는 방법을 찾아야했습니다.

RxJava에는 정적 팩토리 메소드로 표시되는 소스와 인스턴스 메소드로 표시되는 중간과 같은 두 종류의 연산자가 있습니다. 전자는 어떤 클래스에도 살 수 있었기 때문에 여러 유틸리티 클래스에 배포 될 수있었습니다. 후자는 인스턴스 작업이 필요합니다. 개념적으로,이 모든 것은 업스트림을 첫 번째 매개 변수로 사용하는 정적 메소드를 통해 표현 될 수 있습니다.

그러나 실제로는 여러 엔트리 클래스를 사용하면 새로운 사용자가 기능을 발견하는 데 불편 함 (RxJava가 새로운 개념과 프로그래밍 패러다임을 Java로 가져와야 함)과 악의적 인 중간 연산자의 사용법을 기억해야합니다. 따라서 원래 팀은 모든 정적 및 인스턴스 메소드를 보유하고 소스 또는 처리 단계를 자체적으로 나타내는 하나의 클래스 인 유창한 API 디자인을 고안했습니다.

오류, 동시성 지원 및 기능적 특성의 첫 번째 클래스 특성으로 인해 반응성 흐름과 관련된 모든 종류의 소스 및 변환이 발생할 수 있습니다. Rx.NET 시절부터 라이브러리 (및 개념)가 발전함에 따라 점점 더 많은 표준 연산자가 추가되어 기본적으로 메소드 수가 증가했습니다. 이로 인해 두 가지 일반적인 불만이 발생합니다.

  • 왜 그렇게 많은 방법이 있습니까?
  • 내 특별한 문제를 해결하는 방법 X가없는 이유는 무엇입니까?

반응성 연산자를 작성하는 것은 수년 동안 많은 사람들이 마스터하지 않은 어려운 작업입니다. 가장 일반적인 라이브러리 사용자는 독자적으로 연산자를 만들 수 없으며 종종 시도 할 필요가 없습니다. 이것은 때때로 표준 세트에 다른 연산자를 추가한다는 것을 의미합니다. 대조적으로, 우리는 너무 구체적이거나 단순히 자체 무게를 견딜 수없는 편의로 인해 더 많은 운영자를 거부했습니다.

RxJava의 디자인은 유기적으로 성장했지만 실제로는 SOLID와 같은 특정 디자인 원칙을 따르지 않았습니다. 유창한 API의 사용법과 느낌에 의해 구동됩니다.

Rx.NET과의 다른 관계

2013 년 말에 RxJava 개발에 합류했습니다. 제가 알 수 있듯이 초기 초기 0.x 버전은 Rx.NET Observable운영자 의 이름과 서명과 몇 가지 아키텍처 결정이 재사용 되는 블랙 박스 재 구현 이었습니다. 여기에는 Rx.NET 운영자의 약 20 %가 참여했습니다. 당시의 주요 어려움은 C #과 Java의 언어 및 플랫폼 차이 해결이었습니다. 많은 노력을 기울여서 Rx.NET의 소스 코드를 보지 않고도 많은 연산자를 구현할 수 있었고 더 복잡한 연산자를 이식했습니다.

이러한 의미에서 RxJava 0.19까지는 Rx.NET 및 그와 관련된 확장 방법 과 Observable동일했습니다 . 그러나 소위 역압 문제가 나타 났으며 RxJava 0.20은 프로토콜 및 아키텍처 수준에서 Rx.NET과 분기되기 시작했습니다. 사용 가능한 연산자 exteneded하고, 많은 사람들이 배압 인식되었고, 우리는 새로운 유형의 도입 : 그리고 지금의로 Rx.NET에는 대응이없는 1.x의 시대,있다.IObservableObservableSingleCompletable

배압 인식은 사물을 상당히 복잡하게하고 1.x Observable는 그것을 사후 생각으로 받았습니다. 우리는 바이너리 호환성에 대한 충성을 맹세했기 때문에 프로토콜과 API를 변경할 수 없었습니다.

Rx.NET의 아키텍처에는 또 다른 문제가 있습니다 : 동기 취소는 불가능하기 때문에 Disposable, 연산자가 실행을 시작하기 전에 반환해야합니다. 그러나 같은 소스 Range는 간절했고 끝날 때까지 돌아 오지 않습니다. 이 문제는 에서 하나를 반환 Disposable하는 Observer대신에 a 를 삽입하여 해결할 수 있습니다 subscribe().

RxJava 2.x는 이러한 라인을 따라 처음부터 새롭게 디자인되고 다시 구현 되었습니다. 우리는와 Flowable동일한 연산자 세트를 제공 하는 별도의 역압 인식 유형을 가지고 Observable있습니다. Observable역압을 지원하지 않으며 Rx.NET과 다소 동일합니다 Observable. 내부적으로 모든 반응 유형은 취소 핸들을 소비자에게 주입하여 동기식 취소가 효율적으로 작동하도록합니다.


답변

나는 도서관에 익숙하지 않다는 것을 인정하지만, 문제 의 Flowable 클래스 를 살펴 보았고 그것은 일종의 허브처럼 행동하는 것처럼 보입니다. 즉, 프로젝트에서 입력을 확인하고 그에 따라 호출을 분배하는 클래스입니다.

그러므로이 계급은 모든 것을 시도하는 신의 대상이기 때문에 실제로 신의 대상으로 간주되지는 않을 것이다. 이것은 논리적 인 측면에서 거의 수행되지 않습니다. 단일 책임의 관점에서, 수업의 유일한 직업은 도서관 전체에서 업무를 위임한다고 할 수 있습니다.

따라서 자연스럽게 이러한 Flowable클래스에는이 컨텍스트에서 클래스에 필요한 모든 가능한 작업에 대한 메소드가 필요합니다 . 자바 스크립트에서 jQuery 라이브러리와 동일한 유형의 패턴을 볼 수 있습니다. 여기서 변수 $에는 라이브러리에서 호출을 수행하는 데 필요한 모든 함수와 변수가 있습니다 (jQuery의 경우 코드는 단순히 위임되지는 않지만 좋은 논리입니다) 내에서 실행됩니다.

나는 당신이 이와 같은 수업을 조심해야한다고 생각하지만, 개발자가 그것이 단지 허브 일 뿐이므로 천천히 신의 대상으로 변환하지 않는 한 그 자리를 차지합니다.


답변

.NET의 RX FlowableObservable 과 동일합니다 . 또한 모든 메소드가 있지만 확장 메소드 로 정적이며 사용할 수 있습니다 . RX의 주요 요점은 구성이 유연한 인터페이스를 사용하여 작성된다는 것 입니다.

그러나 자바가 유창한 인터페이스를 갖기 위해서는 정적 메소드가 잘 구성되지 않고 정적 메소드를 구성 할 수있는 확장 메소드가 없기 때문에 인스턴스 메소드가되어야합니다. 따라서 실제로 유창한 인터페이스 구문을 사용하지 않는 한 이러한 모든 메소드를 정적 메소드로 만들 수 있습니다.


답변