계층화 된 소프트웨어 아키텍처에서 동일한 계층의 개체간에 종속성을 갖는 것이 문제가됩니까?


12

n- 계층 아키텍처와 의존성 주입을 가진 중간 규모의 소프트웨어를 고려할 때, 계층에 속하는 객체는 하위 계층의 객체에 의존 할 수 있지만 상위 계층의 객체에는 의존하지 않을 수 있습니다.

그러나 같은 레이어의 다른 객체에 의존하는 객체에 대해 어떻게 생각 해야할지 모르겠습니다.

예를 들어, 3 개의 레이어와 이미지의 레이어와 같은 여러 객체가있는 애플리케이션을 가정 해 봅시다. 분명히 하향식 종속성 (녹색 화살표)은 괜찮고 상향식 (빨간색 화살표)은 괜찮습니다. 그러나 같은 레이어 내부의 종속성 (노란색 화살표)은 어떻습니까?

여기에 이미지 설명을 입력하십시오

순환 종속성을 제외하고 발생할 수있는 다른 문제 와이 경우 계층 구조가 얼마나 위반되고 있는지 궁금합니다.


당신은 사이클이없는 경우, 당신은 horysontal 링크가 계층 만이 하위 계층으로 분할 레이어 사이에 종속성이 존재
max630

답변:


10

예, 한 계층의 오브젝트는 서로간에 직접적인 종속성을 가질 있으며 때로는 순환적인 오브젝트도 있습니다. 즉, 직접 종속성이 허용되지 않거나 엄격한 종속성이있는 다른 계층의 오브젝트간에 허용되는 종속성과 핵심 차이를 만드는 것입니다. 방향.

그러나 그렇다고해서 임의의 방식으로 이러한 종속성이 있어야한다는 의미는 아닙니다. 실제로는 레이어가 나타내는 것, 시스템의 크기 및 부품의 책임에 달려 있습니다. "계층화 된 아키텍처"는 모호한 용어이며, 실제로 다른 종류의 시스템에서 의미하는 바에는 큰 차이가 있습니다.

예를 들어 데이터베이스 계층, 비즈니스 계층 및 UI (사용자 인터페이스) 계층이있는 "가로 계층 시스템"이 있다고 가정합니다. UI 계층에는 수십 가지의 서로 다른 대화 클래스가 포함되어 있습니다.

어떤 대화 클래스가 다른 대화 클래스에 직접 의존하지 않는 디자인을 선택할 수 있습니다. "메인 대화 상자"와 "하위 대화 상자"가 존재하고 "메인"대화 상자에서 "하위"대화 상자에 직접적인 종속성 만있는 디자인을 선택할 수 있습니다. 또는 기존 UI 클래스가 동일한 계층의 다른 UI 클래스를 사용 / 재사용 할 수있는 디자인을 선호 할 수 있습니다.

이것들은 가능한 모든 디자인 선택입니다. 아마도 여러분이 구축하고있는 시스템의 유형에 따라 다소 합리적이지만 시스템의 "계층화"가 유효하지 않습니다.


UI 예제를 계속하면서 내부 의존성을 갖는 장단점은 무엇입니까? 재사용이 쉬워지고 주기적 종속성이 발생한다는 것을 알 수 있습니다. 이는 DI 방법에 따라 문제가 될 수 있습니다. 다른 거있어?
bracco23

@ bracco23 : "내부"종속성을 갖는 장단점은 임의의 종속성을 갖는 장단점과 동일합니다. "단점"은 특히 다른 구성 요소와 분리하여 구성 요소를 재사용하기 어렵고 테스트하기 어렵게 만듭니다. 장점은 명시 적 종속성으로 인해 응집력이 필요한 것을보다 쉽게 ​​사용, 이해, 관리 및 테스트 할 수 있다는 것입니다.
Doc Brown

14

레이어에 속하는 객체가 하위 레이어의 객체에 의존 할 수 있다고 말하는 것이 편안합니다.

솔직히 말해서, 당신이 그것에 익숙하지 않다고 생각합니다. 사소한 시스템 이외의 것을 다룰 때는 모든 계층이 다른 계층의 추상화에만 의존하도록하는 것이 목표입니다. 낮고 높음.

예를 들어에 Obj 1의존해서는 안됩니다 Obj 3. 그것은 예를 들어 의존 IObj 3해야하며 런타임에 작동 할 추상화의 구현을 알아야합니다. 정보를 제공하는 것은 해당 종속성을 매핑하는 것이므로 모든 수준과 관련이 없어야합니다. IoC 컨테이너 일 수 있습니다. 예를 들어 main순수 DI를 사용하는 사용자 지정 코드 입니다. 또는 푸시에서 서비스 로케이터 일 수도 있습니다. 어쨌든, 그 사이에 매핑이 제공 될 때까지 레이어간에 종속성이 존재하지 않습니다.

그러나 같은 레이어의 다른 객체에 의존하는 객체에 대해 어떻게 생각 해야할지 모르겠습니다.

나는 이것이 당신 이 직접적인 의존성 을 가져야 할 유일한 시간이라고 주장합니다 . 이는 해당 레이어의 내부 작업의 일부이며 다른 레이어에 영향을주지 않고 변경할 수 있습니다. 따라서 유해한 커플 링이 아닙니다.


답변 해주셔서 감사합니다. 예, 레이어는 객체가 아닌 인터페이스를 노출해서는 안되지만, 이해를 돕기 위해 생략했습니다.
bracco23

4

이것을 실제로 살펴 보자

여기에 이미지 설명을 입력하십시오

Obj 3이제 Obj 4존재한다는 것을 안다 . 그래서 무엇? 우리는 왜 걱정합니까?

말한다

"높은 수준의 모듈은 낮은 수준의 모듈에 의존해서는 안됩니다. 둘 다 추상화에 의존해야합니다."

그러나 모든 객체 추상화가 아닙니까?

복각은 또한 말한다

"추상은 세부 사항에 의존해서는 안된다. 세부 사항은 추상화에 의존해야한다."

그러나 객체가 올바르게 캡슐화되어 있으면 세부 정보가 숨겨지지 않습니까?

어떤 사람들은 모든 객체에 키워드 인터페이스가 필요하다고 맹목적으로 주장하기를 원합니다. 나는 그들 중 하나가 아닙니다. 나는 당신이 그것들을 지금 사용하지 않는다면 나중에 그들과 같은 것을 필요로하는 계획이 필요하다고 맹목적으로 주장하고 싶다.

모든 릴리스에서 코드를 리팩터링 할 수있는 경우 나중에 필요한 경우 인터페이스를 추출 할 수 있습니다. 다시 컴파일하고 싶지 않은 인터페이스를 통해 코드를 게시하고 인터페이스를 통해 대화하기를 원하는 경우 계획이 필요합니다.

Obj 3Obj 4존재한다는 것을 안다 . 그러나 구체적인 Obj 3것인지 아십니까 Obj 4?

이것이 바로 여기 new어디에나 퍼지지 않는 것이 좋은 이유 입니다. 만약 Obj 3알고하지 않습니다 Obj 4나중에에 몰래 설정되어있는 경우 그 다음, 그것을 작성하지 않은 것 때문에, 콘크리트입니다 Obj 4추상 클래스에 Obj 3상관하지 않을 것입니다.

그렇게 할 수 있다면 Obj 4완전히 추상적 인 것입니다. 처음부터 그들 사이에 인터페이스를 만드는 유일한 방법은 누군가 Obj 4가 현재 구체적으로 제공하는 코드를 실수로 추가하지 않을 것이라는 확신입니다 . 보호 된 생성자는 해당 위험을 완화 할 수 있지만 다른 질문이 발생합니다.

Obj 3과 Obj 4는 같은 패키지에 있습니까?

객체는 종종 패키지, 네임 스페이스 등의 방식으로 그룹화됩니다. 그룹화 할 때 그룹 전체가 아닌 그룹 내에서 영향을 미칠 가능성이 더 높습니다.

기능별로 그룹화하고 싶습니다. 경우 Obj 3Obj 4같은 그룹 및 레이어에있는 당신이 하나를 출판뿐만 아니라 다른 하나를 변경할 필요가 동안을 리팩토링 할거야 매우 가능성이 있습니다. 즉, 이러한 객체는 명확한 요구가 있기 전에 객체 사이에 추상화를 적용하면 이점이 적습니다.

그룹 경계를 넘어 서면 양쪽의 객체가 독립적으로 변하게하는 것이 좋습니다.

간단하지만 불행히도 Java와 C #은 이것을 복잡하게 만드는 불행한 선택을했습니다.

C #에서는 I접두어로 모든 키워드 인터페이스의 이름을 지정하는 것이 일반적 입니다. 이를 통해 고객은 키워드 인터페이스와 대화하고 있음을 알 수 있습니다. 그것은 리팩토링 계획을 어지럽 힙니다.

Java에서는 더 나은 이름 지정 패턴을 사용하는 것이 일반적입니다. FooImple implements Foo그러나 Java는 키워드 인터페이스를 다른 2 진으로 컴파일하기 때문에 소스 코드 레벨에서만 도움이됩니다. 즉 Foo, 한 문자의 코드 만 변경 될 필요가없는 구체적 클라이언트에서 추상 클라이언트로 리팩토링 할 때 여전히 다시 컴파일해야합니다.

사람들이 실제로 필요할 때까지 공식적인 추상화를 할 수 없도록하는 것은이 특정 언어의 버그입니다. 사용중인 언어는 말하지 않았지만 이러한 문제가없는 언어가 있다는 것을 이해하십시오.

사용중인 언어를 말하지 않았으므로 언어와 상황을 신중하게 분석하여 모든 곳에서 키워드 인터페이스가 될 것이라고 결정하기를 촉구합니다.

YAGNI 원칙은 여기서 중요한 역할을합니다. 그러나 "발로 자신을 쏠 수 없도록하십시오".


0

위의 답변 외에도 다른 관점에서 그것을 보는 것이 도움이 될 것이라고 생각합니다.

예를 들어, 종속성 규칙 관점에서. DR은 Robert C. Martin이 유명한 Clean Architecture에 대해 제안한 규칙 입니다.

그것은 말한다

소스 코드 종속성은 더 높은 수준의 정책을 향해 안쪽으로 만 향해야합니다.

하여 높은 수준의 정책 , 그 의미 높은 수준의 추상화를. 구체적인 클래스 또는 데이터 구조와 달리 인터페이스 또는 추상 클래스와 같이 구현 세부 정보에서 유출되는 구성 요소.

문제는 규칙이 계층 간 종속성으로 제한되지 않는다는 것입니다. 위치 또는 계층에 관계없이 코드 조각 간의 종속성 만 지적합니다.

따라서 동일한 계층의 요소간에 종속성을 갖는 것은 본질적으로 잘못된 것이 없습니다. 그러나 안정적인 의존성 원리 를 전달하기 위해 의존성을 여전히 구현할 수 있습니다 .

또 다른 관점은 SRP입니다.

디커플링은 유해한 종속성을 해제하고 종속성 전환 (IoC)과 같은 모범 사례를 전달하는 방법입니다. 그러나 변경 사유를 공유하는 요소는 변경 사유가 동일한 요소가 동시에 (매우) 변경되어 동시에 배포되기 때문에 디커플링 사유를 제공하지 않습니다. 그 사이에 사건의 경우 Obj3Obj4다음, 다시 한 번, 본질적으로 아무 문제가 없습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.