2011-09-26 1 views
64

동일한 종류의 객체 (쿼리 결과)를 반환하지만 공통된 속성이나 메서드가없는 함수가 있습니다. 공통 유형을 가지기 위해 빈 인터페이스를 반환 유형으로 사용하고 두 가지 모두에서이를 구현했습니다.빈 인터페이스 코드의 냄새가 있습니까?

그건 당연하지. 나는 언젠가 그 수업이 공통점을 가질 것이라는 희망을 품을 때만 자신을 위로 할 수 있습니다. 그리고 나는 그 공통된 논리를 빈 인터페이스로 옮길 것입니다. 그러나 나는 만족스럽지 않고 두 가지 다른 방법이 있어야하고 조건부로 다음에 전화해야하는지에 대해 생각하지 않습니다. 그것이 더 나은 접근 방법이 될 수 있을까요?

.NET Framework에서 태그 지정을 위해 빈 인터페이스를 사용한다고도 들었습니다.

제 질문은 : 빈 인터페이스가 디자인 문제의 강력한 징후입니까, 아니면 널리 사용되는 것입니까?

EDIT : 관심있는 사람들을 위해 차별화 된 기능 언어의 노동 조합이 내가 달성하려고 시도한 것에 대한 완벽한 해결책이라는 것을 알게되었습니다. C#은 그 개념에 아직 친숙하지 않습니다.

EDIT :이 문제점에 대해 longer piece (흠호)을 작성하여 자세히 설명합니다.

+14

이들은 [마커 인터페이스] (http://en.wikipedia.org/wiki/Marker_interface_pattern)라고하며 분명히 널리 사용됩니다. – BoltClock

+3

이 http://msdn.microsoft.com/en-us/library/ms182128%28v=vs.80%29.aspx (제 의견은 다른 방법이 필요합니다) – V4Vendetta

+1

비슷한 줄에 뭔가 http : // stackoverflow. com/questions/835140/using-marker-classes-to-control-logic-flow – V4Vendetta

답변

39

그 사용 사례에 대한 디자인 패턴 (많은 경우 "마커 인터페이스"를 언급 했음)이 있지만, 나는 그러한 연습의 사용이 코드 냄새의 표시라고 생각합니다. 가장 작은).

V4Vendetta 게시 @으로

이 대상으로하는 정적 분석 규칙이있다 : http://msdn.microsoft.com/en-us/library/ms182128(v=VS.100).aspx

당신의 디자인 유형, 당신은 아마 마커와 같은 인터페이스를 사용하여 구현 할 것으로 예상되거나 빈 인터페이스를 포함하는 경우 유형 그룹을 식별하는 방법.이 ID가 런타임에 발생하는 경우이를 수행하는 올바른 방법은 사용자 지정 특성을 사용하는 것입니다. 대상 유형을 식별하기 위해 속성의 존재 유무 또는 속성의 특성을 사용하십시오. 컴파일 타임에 식별이 발생해야하는 경우 빈 인터페이스를 사용할 수 있습니다.

이것은 인용 MSDN 추천 :

인터페이스를 제거하거나 구성원을 추가 할 수 있습니다. 빈 인터페이스를 사용하여 유형 세트에 레이블을 지정하는 경우 인터페이스를 사용자 정의 속성으로 바꾸십시오.

위 목록은 이미 게시 된 위키 백과 링크의 비평 섹션을 반영합니다.

마커 인터페이스의 주요 문제점은 인터페이스가 클래스를 구현하기위한 계약을 정의하고 해당 계약이 모든 하위 클래스에 상속된다는 것입니다. 즉, 마커를 "구현할 수 없음"을 의미합니다. 주어진 예에서 직렬화하지 않으려는 하위 클래스를 작성하는 경우 (일시적인 상태에 달려 있기 때문일 수도 있음), NotSerializableException (ObjectOutputStream docs 당)을 명시 적으로 throw해야합니다.

+1

내 사용 사례에서 (두 클래스 만 있고 파생되지는 않을 것이라고 생각합니다.) 괜찮아 보입니다. 내 설명 편집을 참조하십시오. –

+0

답변으로 받아들입니다. 다른 대답이 귀중한 정보를 제공하기는하지만이 방법으로 잠재적 인 문제에 대해 가장 많은 것을 자세히 설명합니다. –

+1

다른 곳에서 지적한 바와 같이, '속성'은이를 수행하는 '정확한'방법이지만 구현 및 사용하는 것이 더 어색하며 실제 사용에서는 효과가 없습니다. – nicodemus13

6

당신은 자신의 질문에 대답했습니다 ... "어떤 경우에 따라 완전히 다른 객체를 반환하는 함수가 있습니다."... 왜 완전히 다른 객체를 반환하는 동일한 함수를 원하겠습니까? 나는 이것이 유용 할 이유를 알 수 없습니다. 아마도 좋은 것을 가지고 있습니다. 어떤 경우에는 공유하십시오.

편집 : 설명을 고려하면 실제로 마커 인터페이스를 사용해야합니다. "완전히 다른"은 "같은 종류"와는 완전히 다릅니다. 완전히 다른 경우 (공유 된 구성원이 없다는 것만이 아니라) 코드 냄새가 날 것입니다.

+0

이것은 더 나은 후보자처럼 보입니다. 의견을 말하면 내 질문에 설명 부분을 추가했습니다. 다른 것이 필요한지 물어보십시오. –

7

marker interface으로 사용하지 않으면 코드 냄새라고 말할 수 있습니다.

인터페이스는 구현자가 준수하는 계약을 정의합니다. 리플렉션 오버 (마커 인터페이스와 마찬가지로)를 사용하지 않는 빈 인터페이스가있는 경우 Object을 (이미 존재하는) 기본 유형.

+1

'object'는 너무 일반적이어서 반환 "kind"에 힌트를 제공하지 않습니다. 인터페이스를 사용하면 함수의 반환 값 해석에 대한 옵션을 좁힐 수 있습니다. 하지만 내가 반환하는 대상의 유사성에 대한 설명이 부족하다는 의견에 대해 귀하의 의견을 이해합니다. –

+0

@ssg - 꽤. 하나의 메소드에 전달하여 조작하려면 _something_과 유사해야합니다. 그렇지 않으면 별도의 메소드가 있어야합니다. – Oded

9

귀하의 기능은 "특정 사례를 기반으로 완전히 다른 객체를 반환합니다"라고 명시하고 있지만 그 차이점은 무엇입니까? 하나는 스트림 작성자, 다른 하나는 UI 클래스, 다른 하나는 데이터 객체일까요? 아니 ... 나는 그것을 의심한다!

개체에는 일반적인 방법이나 속성이 없지만 역할이나 용도가 비슷할 수 있습니다. 이 경우 marker interface이 전적으로 적합합니다.

+0

그들은 다른 유형의 쿼리 결과이지만 두 쿼리 결과, 예. –

+1

OK - 공통 속성을 갖고 있지는 않지만 공통된 역할을한다고 생각했습니다. 마커 인터페이스처럼 들리 네요. – ColinE

3

많은 사람들이 이미 말했듯이, 빈 인터페이스는 "마커 인터페이스"로서 유효한 사용법을 가지고 있습니다.

아마 내가 생각할 수있는 가장 좋은 용도는 도메인의 특정 하위 집합에 속한 개체를 해당하는 리포지토리로 처리하는 것입니다. 데이터를 가져올 다른 데이터베이스가 있고 각각에 대해 리포지토리 구현이 있다고 가정 해보십시오. 특정 리포지토리는 하나의 하위 집합 만 처리 할 수 ​​있으며 다른 하위 집합의 개체 인스턴스를 제공해서는 안됩니다.

//Every object in the domain has an identity-sourced Id field 
public interface IDomainObject 
{ 
    long Id{get;} 
} 

//No additional useful information other than this is an object from the user security DB 
public interface ISecurityDomainObject:IDomainObject {} 

//No additional useful information other than this is an object from the Northwind DB 
public interface INorthwindDomainObject:IDomainObject {} 


//No additional useful information other than this is an object from the Southwind DB 
public interface ISouthwindDomainObject:IDomainObject {} 

귀하의 저장소는 다음 ISecurityDomainObject, INorthwindDomainObject 및 ISouthwindDomainObject에 일반 될 수 있으며, 다음 코드는 보안을 통과하는 것을 시도하지 않는 것이 컴파일 시간 체크를해야 : 도메인 모델은 다음과 같을 수 Northwind DB (또는 다른 순열) 개체. 이와 같은 상황에서 인터페이스는 구현 계약을 제공하지 않더라도 클래스의 본질에 관한 중요한 정보를 제공합니다.