의존성 주입으로 UI에서 엄청난 양의 인터페이스를 피하는 방법은 무엇입니까?


8

문제
최근에 싱글 톤이 나쁘고 의존성 주입 ( "인터페이스 사용"으로 이해)이 어떻게 더 좋은지에 대해 많이 읽었습니다. 콜백 / 인터페이스 / DI 로이 부분을 구현하고 인터페이스 분리 원칙을 준수했을 때 나는 결국 혼란스러워했습니다.

기본적으로 모든 하위 항목의 하위 항목이 결합 된 UI 상위 항목의 종속성으로 인해 UI 요소가 계층 구조를 위로 올라 갈수록 생성자가 더 부풀어졌습니다.

UI 계층 구조의 맨 위에는 현재 선택에 대한 정보와 변경 사항을 반영해야하는 3d 모델에 대한 참조가 포함 된 Application 클래스가 있습니다. 응용 프로그램 클래스는 8 개의 인터페이스를 구현하고 있으며 앞으로 나올 제품 (/ 인터페이스)의 5 분의 1에 불과했습니다!

나는 현재 선택을 유지하는 단일 톤과 UI 요소를 업데이트하는 기능을 가지고 있습니다. 이 함수는 UI 트리와 UI 요소를 속여서 필요에 따라 현재 선택 싱글 톤에 액세스합니다. 이 방법으로 코드가 더 깨끗해 보입니다.

질문
이 프로젝트에 싱글 톤이 적절한가요?
그렇지 않다면, DI를 생각하고 /하거나 구현하는 데 근본적인 결함이 있습니까?

프로젝트에 대한 추가 정보
유형 : 종소리와 휘파람이있는 아파트 용 쇼핑 바구니
크기 : 코드 및 UI의 경우 2 개월 개월
유지 관리 : 업데이트가 실행되지 않지만 나중에 "버전 2.0"일 수 있음
환경 : Entity를 사용하는 Unity에서 C # 사용 구성 요소 시스템

거의 모든 경우에 사용자 상호 작용은 여러 작업을 트리거합니다. 예를 들어, 사용자가 항목을 선택할 때

  • 해당 항목과 설명을 표시하는 UI 부분을 업데이트해야합니다. 이를 위해서는 가격을 계산하기 위해 3D 모델에서 일부 정보를 가져와야합니다.
  • UI를 더 높이려면 전체 총 가격을 업데이트해야합니다.
  • 변경 사항을 표시하려면 3D 모델의 클래스에서 해당 함수를 호출해야합니다.

DI는 단지 인터페이스를 사용하는 것이 아니라 단위 테스트 영역에서 특히 유용한 concretion을 교체 할 수있는 기능입니다.
Robbie Dee

1
또한 싱글 톤이 선호되는 문제를 아직 보지 못했습니다. 사람들이 항상 언급하는 표준 예제는 로그 라이터이지만 여기에서도 여러 가지 다른 로그 (오류, 디버그 등)에 쓰려고 할 수 있습니다.
로비 디

@RobbieDee 예, DI는 더 많은 것이지만 인터페이스 사용이 DI가 아닌 상황을 볼 수 없습니다. 그리고 싱글 톤이 선호되는 솔루션이 아니라면-선호하는 솔루션이 왜 그렇게 지저분합니까? 이것이 나의 주요 질문이지만, 때로는 일반적인 규칙이 적용되지 않으므로 공개적으로 유지하고 싶었습니다.
R. Schmitz

인터페이스 구성은 모의 프레임 워크의 특징이기도합니다. 그들은 또한 수십 년 동안 OO 언어로 사용되어 왔습니다.
Robbie Dee

나는 당신의 요점을 얻지 못합니다.
R. Schmitz

답변:


4

나는 그 질문이 해결책이 아니라 증상이라고 생각합니다.

나는 최근 싱글 톤이 나쁘고 의존성 주입 ( "인터페이스 사용"으로 이해)이 어떻게 더 좋은지에 대해 많이 읽었습니다. 콜백 / 인터페이스 / DI 로이 부분을 구현하고 인터페이스 분리 원칙을 준수했을 때 나는 결국 혼란스러워했습니다.

문제를 찾는 해결책; 잘못 이해하면 디자인이 손상 될 수 있습니다. DI vs Singleton, 다른 개념 에 대한 SO 질문을 읽었 습니까? 클라이언트가 싱글 톤을 처리 할 필요가 없으므로 싱글 톤을 래핑하는 것처럼 읽었습니다. 그것은 단지 좋은 오래된 캡슐입니다. 나는 그 자리에 있다고 생각합니다.


UI 요소의 계층 구조가 높을수록 생성자가 더 부풀어졌습니다.

더 작은 비트를 먼저 만든 다음 그들이 속한 것의 생성자로 전달하고 더 큰 것을 다음 큰 것의 생성자로 전달하십시오.

복잡한 시공 문제가있는 경우 팩토리 또는 빌더 패턴을 사용하십시오. 결론적으로 복잡한 구조는 다른 클래스를 깔끔하고 깨끗하며 이해하기 쉽게하기 위해 자체 클래스로 가져 왔습니다.


응용 프로그램 클래스는 8 개의 인터페이스를 구현하고 있으며 앞으로 나올 제품 (/ 인터페이스)의 5 분의 1에 불과했습니다!

확장 성이없는 것 같습니다. 핵심 디자인이 누락되어 모든 것이 맨 처음부터 시작됩니다. 더 많은 상향식 구성, 구성 및 상속이 있어야합니다.

당신의 디자인이 "최고 무겁다"고 생각합니다. 우리는 하나의 클래스를 모든 것이 될 수있는 것 또는 무엇이든 만들려고하는 것 같습니다. 비즈니스 도메인 클래스가 아닌 UI 클래스라는 사실은 실제로 우려의 분리에 대해 궁금해합니다.

처음부터 디자인을 다시 살펴보고 더 복잡하거나 다른 카테고리 제작을 위해 구축 할 수있는 견고하고 기본적인 제품 추상화가 있는지 확인하십시오. 그런 다음 이러한 것들에 대한 커스텀 컬렉션을 갖추는 것이 좋으므로 언급 한 "3 차 모델"과 같은 "컬렉션 레벨"기능을 사용할 수 있습니다.


... 변화를 반영해야하는 3D 모델.

이것의 대부분은 커스텀 컬렉션 클래스에 적합 할 수 있습니다. 깊이와 복잡성으로 인해 독립적 인 클래스 구조 일 수도 있습니다. 이 두 가지는 상호 배타적이지 않습니다.

방문자 패턴에 대해 읽으십시오. 기능의 전체 척을 서로 다른 유형으로 추상적으로 연결하는 아이디어입니다.


디자인과 DI

모든 의존성 주입의 90 %는 생성자 매개 변수 전달입니다. 책을 쓴 퀴는 이렇게 말합니다 . 수업을 잘 디자인하고 DI 컨테이너를 사용해야한다는 것에 대한 모호한 개념으로 사고 과정을 오염시키지 마십시오. 필요한 경우 디자인을 통해 제안 할 수 있습니다.


아파트 쇼핑 도메인 모델링에 중점을 둡니다.

제시카 심슨의 디자인 접근 방식을 피하십시오 . "그게 무슨 뜻인지는 모르겠지만 그것을 원합니다."

다음은 잘못되었습니다.

  • 나는 인터페이스를 사용해야합니다
  • 싱글 톤을 사용해서는 안됩니다
  • 나는 DI가 필요하다 (무엇이든)
  • 상속이 아닌 컴포지션을 사용해야합니다
  • 나는 상속을 피해야한다
  • 패턴을 사용해야합니다

나는 내가 사용한 모든 싱글 톤과 당신이 말한 것들 중 일부를 자동으로 제거하려고 시도했습니다. 나머지도 마찬가지입니다. 여러분의 조언을 구하고 방문자 패턴 등을 읽어 드리겠습니다.
R. Schmitz

한 가지 요점이며, 여기에서 뱀파이어가 되려고 노력하지는 않지만 원래 질문 일부였습니다. 싱글 톤을 사용하십시오. " '싱글 톤을 사용해서는 안된다'는 말이 잘못되었습니다."라고 쓴다.
R. Schmitz

내가 말하는 것은 "그것은 달려있다"입니다. 너무 자주 나는 말 그대로 최대 값을 보았습니다.
radarbob

3

"계급 계층 구조"는 약간 붉은 깃발입니다. 가설 : 5 개의 위젯이있는 웹 페이지. 이 페이지는 위젯의 조상이 아닙니다. 해당 위젯에 대한 참조를 보유 할 수 있습니다. 그러나 그것은 조상이 아닙니다. 계급 계층 구조 대신 구성 사용을 고려하십시오. 5 개의 위젯 각각은 다른 위젯이나 톱 페이지를 참조하지 않고 자체적으로 구성 할 수 있습니다. 그런 다음 최상위 페이지는 기본 페이지를 작성하고 전달 된 위젯 오브젝트 (컬렉션)를 레이아웃하기에 충분한 정보로 구성됩니다. 이 페이지는 레이아웃 등을 담당하지만 위젯의 구성 및 논리는 담당하지 않습니다.

컴포지션을 사용하면 DI가 가장 친한 친구입니다. DI를 사용하면 DI에서 정의한 버전 또는 위젯 유형에 따라 각 위젯을 교체 할 수 있습니다. 위젯 구성은 DI에서 캡처되며 맨 위 페이지와 별개입니다. 아마도 DI의 컬렉션 구성도 정의 할 수 있습니다. 맨 위 페이지는 전달 된 위젯을 기반으로 레이아웃을 수행합니다. 톱 페이지 생성자를 변경할 필요가 없습니다. 맨 위 페이지에는 위젯의 레이아웃을 수행하고 정의 된 인터페이스를 기반으로 위젯에 정보를 전달하는 로직 만 필요합니다.

컴포지션 체인 위아래로 리스너를 전달하는 대신 리스너 컬렉션을 필요한 위젯에 리스너 모음을 삽입하십시오. 컬렉션에 게시 할 수 있도록 컬렉션을 게시자에게 주입합니다. 리스너에 컬렉션을 삽입하여 컬렉션에 자신을 추가 할 수 있도록합니다. 이 컬렉션은 컴포지션 체인의 모든 객체를 잘라냅니다.


죄송합니다. "클래스 계층"은 잘못된 표현입니다. 실제로 클래스 계층 구조가 아니라 UI 계층 구조였습니다. '위젯'은 애플리케이션 클래스의 서브 클래스가 아니지만 '페이지'에는 UI 업데이트를 공개하기 위해 해당 페이지에 대한 참조가 있습니다. 이 구조로 테스트 할 수 있었지만 특히 생성자에는 많은 오버 헤드가 있었고 (UI) 자식에 대한 많은 리스너를 전달했습니다.
R. Schmitz

@ R.Schmitz : 오버 헤드가 문제가 되었습니까? UI가 느리고 당신이 묘사 한 디자인이 비난 되었습니까?
Robert Harvey

@ R.Schmitz "많은 청취자에게 전달"에 대해 자세히 설명해 주시겠습니까? 어쩌면 C #에서 DI에 대한 나의 경험은 낮지 만 적절한 디자인이 필요하지 않은 (적어도 생성자에서는) 필요하지 않은 것이 있습니다.
Katana314

@RobertHarvey 전혀 성능 손실이 없으며 가독성에 관한 것입니다.
R. Schmitz

@ Katana314 예를 들어, 항목이 추가 될 때 3dmodel을 업데이트해야하며 제품 범주에 속하지 않으므로 추가 / 제거 / 변경되는 항목을 수신하는 애플리케이션 클래스에서 참조됩니다. 결국 모든 제품 범주에서 거의 동일 할 것입니다. 다른 UI 부분도 반응하고 듣고 있지만 메시지는 3dmodel 참조와 실제 데이터 (또한 업데이트 됨)가있는 곳이므로 맨 위로 이동해야합니다.
R. Schmitz
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.