다중 상속이 단일 책임 원칙을 위반합니까?


18

두 개의 별개의 클래스에서 상속받은 클래스가 있다고해서 하위 클래스가 각 슈퍼 클래스에서 하나씩 적어도 2 가지를 자동으로 수행한다는 의미는 아닙니까?

인터페이스 상속이 여러 개인 경우 차이가 없다고 생각합니다.

편집 : 분명히, 여러 클래스를 서브 클래스 화하는 것이 SRP를 위반하면 여러 (마커 또는 기본 인터페이스 (예 : Comparable)) 인터페이스를 구현하면 SRP도 위반한다고 생각합니다.


분명히 여러 인터페이스 구현이 SRP를 위반한다고 생각하십니까?

여러 클래스의 서브 클래 싱이 SRP를 위반하면 여러 (마커가 아닌) 인터페이스 구현이 SRP도 위반한다고 생각합니다.
m3th0dman

나는이 질문을 찬성하지만 당신은 내가 동의하지 않는 질문에 당신의 의견을 포함 시켰습니다.
Nicole

1
@ NickC : 나는 내 의견을 말하지 않았다 (위의 의견을 읽었어야한다); 더 명확하게하기 위해 질문을 편집하겠습니다.
m3th0dman

1
@ NickC 나는 의견이 없기 때문에 내가 물었다. 나는 두 사람이 서로 관련이 있다고 말했다 (인터페이스 상속과 클래스 상속). 클래스 상속을 위반하면 인터페이스 상속도 위반합니다. 인터페이스 상속을 위반하면 둘 중 하나도 위반하지 않습니다. 그리고 나는 투표에 관심이 없습니다 ...
m3th0dman

답변:


17

매우 좁은 의미에서 답은 "예"입니다. 기본 클래스 또는 인터페이스가 단일 목적으로 설계되었다고 가정하면 두 클래스를 상속하면 여러 책임이있는 클래스가 만들어집니다. 그러나 "나쁜 것"인지 여부는 상속하는 클래스 또는 인터페이스의 특성에 따라 다릅니다.

클래스와 인터페이스를 두 가지 주요 그룹으로 나눌 수 있습니다. 하나는 시스템의 필수 복잡성을 해결하고 다른 하나는 실수로 복잡성을 해결합니다. 둘 이상의 "필수 복잡성"클래스에서 상속 받으면 나쁘다. 하나의 "필수"클래스와 하나 이상의 "사고"클래스를 상속 받으면 괜찮습니다.

예를 들어, 청구 시스템에서는 송장 및 청구주기를 나타내는 클래스 (필수 복잡성을 처리 함)와 객체를 유지하기위한 클래스 (우발적 인 복잡성을 처리 함)를 가질 수 있습니다. 이렇게 상속 받으면

class BillingCycleInvoice : public BillingCycle, public Invoice {
};

그것은 나쁘다 : 당신 BillingCycleInvoice은 시스템의 본질적인 복잡성과 관련하여 혼합 된 책임이있다.

반면에 이렇게 상속 받으면

class PersistentInvoice : public Invoice, public PersistentObject {
};

기술적으로는 한 번에 두 가지 문제를 처리하지만 그 중 하나만 필수이므로 우연한 것을 "사업 비용"으로 물려받을 수 있습니다.


3
두 번째 예는 Aspect 지향 프로그래밍에서 교차 절단 문제와 매우 유사합니다. 즉, 객체가 핵심 초점이 아닌 작업 (예 : 로깅, 액세스 제어 테스트 또는 지속)을 수행해야하며 다중 상속을 통해이를 수행 할 수 있다는 의미입니다. 그것은 도구를 적절히 사용하는 것입니다.

가장 간단한 방법은 새로운 인터페이스를 구현하기 위해 클래스 기능을 완료해야하는 경우에는 그렇지 않습니다. 그 새로운 책임을 추가하는 경우 종속성으로 SRP 위반하지 않습니다 주입하지만 다른 클래스와 인터페이스를 구현
Ramankingdom

9

SRP는 나쁜 신 클래스를 피하기위한 가이드 라인이지만 문자 그대로 받아 들일 수 있으며 프로젝트는 소수의 클래스를 결합하지 않으면 실제로는 아무것도 할 수없는 수많은 클래스로 시작됩니다. 다중 상속 / 여러 인터페이스는 클래스가 너무 커지고 있다는 신호일 수 있지만, 현재 작업에 초점이 너무 세분화되어 있고 솔루션이 과도하게 엔지니어링되었다는 신호일 수도 있습니다. 다중 상속에 대한 올바른 유스 케이스와 걱정은 없습니다.

소프트웨어 디자인은 과학만큼이나 예술이며 많은 경쟁 관계의 균형 잡힌 행동입니다. 우리는 우리가 알고있는 것들이 문제를 일으키는 한 방향으로 멀어지는 것을 피하는 데 도움이되는 규칙을 가지고 있지만, 그러한 규칙은 우리가 처음에 피하려고하는 것보다 나쁘거나 나쁜 곳으로 쉽게 우리를 데려 갈 수 있습니다.


4

약간. SRP의 주요 원칙에 중점을 두겠습니다.

수업은 한 가지 이유 만 변경해야합니다.

다중 상속은 이것을 강제하지 않지만 그것을 이끌어내는 경향이 있습니다. 클래스가 기본 클래스를 재정의하거나 구현하는 경우 변경해야 할 더 많은 이유가 있습니다. 이런 식으로 인터페이스 다중 상속은 클래스 상속보다 더 성가신 경향이 있습니다. 두 클래스가 상속되었지만 재정의되지 않은 경우 새 클래스가 아닌 기본 클래스에 변경 이유가 있습니다.

다중 상속이 SRP를 위반하지 않는 곳은 기본 유형 중 하나를 제외한 모든 유형이 클래스가 구현하는 것이 아니라 클래스가 갖는 특성으로 작동하는 경우입니다. IDisposableC #에서 고려하십시오 . 일회용 물건에는 두 가지 책임이 없으며 인터페이스는 특성을 공유하지만 결정적으로 다른 책임을 가진 클래스에 대한 시각으로 작용합니다.


2

내 의견으로는 아닙니다. 저에게있어 단일 책임은 "응용 프로그램의 사용자를 모델링"하는 것입니다. 웹 서비스를 통해 해당 데이터를 제공하고 관계형 데이터베이스에 저장해야 할 수도 있습니다. 몇 가지 믹스 인 클래스를 상속하여 해당 기능을 제공 할 수 있습니다.

그렇다고 수업에 세 가지 책임이 있다는 의미는 아닙니다. 이는 사용자를 모델링하는 책임의 일부가 직렬화 및 지속성을 지원해야 함을 의미합니다.


2

전혀. Java에서는 일종의 도메인 객체 (예 : Foo)를 나타내는 인터페이스를 사용할 수 있습니다. 다른 Foo 객체와 비교해야 할 수도 있으므로 Comparable (Comparator 클래스에서 외부화 된 비교 논리 사용)을 구현합니다. 이 객체는 네트워크를 통해 전송 될 수 있도록 직렬화 가능해야 할 수도 있습니다. 복제 가능해야 할 수도 있습니다. 따라서이 클래스는 3 개의 인터페이스를 구현하지만 Foo에서 지원하는 것 이상의 인터페이스를 지원할 수있는 로직이 없습니다.

즉, SRP를 극단적으로 취하는 것은 어리석은 일입니다. 클래스가 둘 이상의 메소드를 정의하는 경우 SRP를 위반합니까? 모든 Java 객체에는 toString () 메서드와 equals (Object) 메서드가 있습니다. 즉, Java의 모든 객체가 동등성과 자기 표현을 담당합니다. 그게 나쁜가요?


1

나는 그것이 당신이 책임을 어떻게 정의하는지에 달려 있다고 생각합니다. 전형적인 iostream 예제에서는 SRP를 위반하지 않습니다. IOstream은 하나의 양방향 스트림을 관리합니다.

원시적 인 책임을 다한 후에는 일반적인 진입 점의 책임을 어떻게 정의합니까? 책임은 '내 앱이하는 모든 것'이 아닌 '주요 진입 점'이어야합니다. 그렇지 않으면 SRP를 위반하지 않고 애플리케이션을 생성하는 것이 불가능합니다.

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