저는 많은 구성 요소와 종속성이있는 다소 큰 프로젝트에서 작업하는 팀이 처음입니다. 모든 구성 요소에 interfaces
대해 해당 구성 요소에 대한 노출 된 인터페이스가 배치 되는 패키지가 있습니다. 이것이 좋은 습관입니까?
나의 일상적인 관행은 항상 인터페이스와 구현이 동일한 패키지로 이동하는 것이 었습니다.
저는 많은 구성 요소와 종속성이있는 다소 큰 프로젝트에서 작업하는 팀이 처음입니다. 모든 구성 요소에 interfaces
대해 해당 구성 요소에 대한 노출 된 인터페이스가 배치 되는 패키지가 있습니다. 이것이 좋은 습관입니까?
나의 일상적인 관행은 항상 인터페이스와 구현이 동일한 패키지로 이동하는 것이 었습니다.
답변:
인터페이스와 구현을 모두 배치하는 것은 흔한 일이며 문제가되지 않는 것 같습니다.
예를 들어 Java API를 예로 들어 보겠습니다. 대부분의 클래스에는 동일한 패키지에 포함 된 인터페이스와 구현이 모두 있습니다.
예를 들어 java.util
패키지를 살펴보십시오 .
그와 같은 인터페이스를 포함 Set
, Map
, List
또한 구현하면서 같은 HashSet
, HashMap
및 ArrayList
.
또한 Javadocs는 패키지 내용을 표시 할 때 문서를 인터페이스 및 클래스 보기 로 분리하므로 이러한 조건에서 잘 작동하도록 설계되었습니다 .
인터페이스가 엄청나게 많은 경우가 아니라면 인터페이스 전용 패키지를 갖는 것은 실제로 약간 과도 할 수 있습니다. 그러나 그렇게하기 위해 인터페이스를 자체 패키지로 분리하는 것은 나쁜 습관처럼 들립니다.
인터페이스 이름을 구현과 구별해야하는 경우 인터페이스를보다 쉽게 식별 할 수 있도록 명명 규칙을 사용할 수 있습니다.
인터페이스 이름 앞에 I
. 이 접근 방식은 .NET 프레임 워크의 인터페이스를 사용합니다. 그것이 IList
목록에 대한 인터페이스 라고 말하는 것은 상당히 쉬울 것 입니다.
- able
접미사를 사용합니다 . 이 방법은 같은 자바 API에서 자주 볼 Comparable
, Iterable
그리고 Serializable
몇 가지 이름을.
모든 언어에 대해 동일한 패키지에 함께 넣는 것이 좋습니다. 중요한 것은 외부 세계에 노출되는 것과 외부에서 어떻게 보이는지입니다. 구현이 동일한 패키지에 있는지 여부를 알거나 신경 쓰지 않을 것입니다.
이 특정 인스턴스를 살펴 보겠습니다.
하나의 패키지에 모든 공개 항목이 있고 공개적으로 노출되지 않은 다른 패키지에는 비공개 항목이있는 경우 라이브러리의 클라이언트는 하나의 패키지를 봅니다. 공개적으로 노출 된 항목이있는 패키지로 비공개 항목을 이동하지만 패키지 내에서 노출하지 않는 경우 클라이언트는 정확히 동일한 항목을 보게됩니다.
따라서 이것은 정당한 이유가없는 규칙의 냄새가납니다. 공개적으로 보이는 것에 영향을 미치지 않고 공개적으로 보이는 것에 기반하여 결정을 내리는 것입니다.
즉, 특정 인스턴스에서 인터페이스와 구현을 별도의 패키지로 분할하는 것이 좋은 생각 인 것 같으면 바로 진행하여 수행하십시오. 이 작업을 수행하는 이유는 패키지가 거대하거나 표준 구현 대신 링크 할 수있는 대체 구현이 있기 때문입니다.
friend
(C ++) 또는 internal
(C #)에 해당하는 것이 없습니다 .
인터페이스를 다른 패키지에 넣는 한 가지 주장은 제품 또는 서비스 소비자에게 배포 할 수있는 'api'jar를 만드는 것이 더 쉽다는 것입니다. 인터페이스와 구현을 함께 사용하여이 작업을 완벽하게 수행 할 수 있지만 다른 패키지에있는 경우 스크립트가 더 간단합니다.
Practical Software Engineering : A Case-Study Approach 라는 책 은 별도의 프로젝트 / 패키지에 인터페이스를 배치하는 것을 옹호합니다.
이 책에서 말하는 PCMEF + 아키텍처는 다음과 같은 원칙을 가지고 있습니다.
원칙 # 3 및 # 7에 대한 설명은 이것이 좋은 생각 인 이유를 설명합니다.
Neighbor Communication Principle은 패키지가 인접 패키지와 만 직접 통신 할 수 있도록 요구합니다. 이 원칙은 시스템이 상호 통신하는 물체의 비압축성 네트워크로 분해되지 않도록합니다. 이 원칙을 시행하기 위해 인접하지 않은 객체 사이의 메시지 전달은 위임을 사용합니다 (9.1.5.1 단원). 더 복잡한 시나리오에서는 아는 사람 패키지 (9.1.8.2 절)를 사용하여 인터페이스를 그룹화하여 먼 패키지와 관련된 협업을 지원할 수 있습니다.
지인 패키지 원칙은 이웃 커뮤니케이션 원칙의 결과입니다. 아는 사람 패키지는 메서드 호출에 대한 인수에서 구체적인 개체 대신 개체가 전달하는 인터페이스로 구성됩니다. 인터페이스는 모든 PCMEF 패키지에서 구현 될 수 있습니다. 이를 통해 인접하지 않은 패키지 간의 통신을 효과적으로 허용하면서 종속성 관리를 단일 아는 사람 패키지로 중앙 집중화 할 수 있습니다. 아는 사람 패키지의 필요성은 9.1.8.2 절에 설명되어 있으며 다음에 PCMEF 컨텍스트에서 다시 논의됩니다.
이 링크를 참조하십시오 : http://comp.mq.edu.au/books/pse/about_book/Ch9.pdf
예, 특정 구현을 게시하지 않고도 인터페이스를 게시 할 수 있기 때문에 매우 좋은 방법입니다. 즉, 외부 인터페이스를 게시 할 필요가없는 경우 구현과 동일한 패키지에 인터페이스 정의를 넣는 데 문제가 없습니다.
Java 경험은 많지 않지만 인터페이스를 구현하는 구체적인 클래스가있는 어셈블리가 클라이언트는 웹 서비스 시나리오에서 중개인 공장이나 유선을 통해 프록시되기 때문입니다.
나는 프로젝트에서 이것을하고 있으며 다음과 같은 이유로 잘 작동합니다.
별도로 패키징 된 인터페이스 및 구현은 다양한 유형의 Map 또는 Set과 다른 사용 사례를위한 것입니다. 나무만을위한 패키지 (java.util.tree.Map, java.util.tree.Set)를 가질 이유가 없습니다. 이는 표준 데이터 구조이므로 다른 데이터 구조와 함께 사용하십시오. 그러나 정말 간단한 디버그 인터페이스와 예쁜 프로덕션 인터페이스가있는 퍼즐 게임을 다루는 경우 프런트 엔드의 일부로 com.your.app.skin.debug 및 com.your.app이있을 수 있습니다. .skin.pretty. 나는 그것들을 같은 패키지에 넣지 않을 것입니다. 왜냐하면 그것들은 다른 일을하기 때문이며, 동일한 패키지에 있다면 두 사람에 대한 비공식 네임 스페이스를 생성하기 위해 SmurfNamingConvention (DebugAttackSurface, DebugDefenceSurface, PrettyAttackSurface 등)에 의지 할 것이라는 것을 알고 있습니다.
별도의 패키지에있는 관련 인터페이스 및 구현을 찾는 문제에 대한 해결 방법은 내 패키지에 대한 명명 구성을 채택하는 것입니다. 예를 들어 com.your.app.skin.framework에 모든 인터페이스를 가질 수 있으며 동일한 수준의 패키지 트리에있는 다른 패키지가 구현이라는 것을 알 수 있습니다. 단점은 이것이 색다른 관습이라는 것입니다. 솔직히 6 개월 만에이 대회가 얼마나 좋은지 보겠습니다. :)
나는이 기술을 종교적으로 사용하지 않습니다. 특정 구현에서만 의미가있는 인터페이스가 있습니다. 나는 그것들을 프레임 워크 패키지에 붙이지 않는다. 40 개의 다른 구현 클래스를 만들 것 같지 않은 패키지가 있으므로 신경 쓰지 않습니다.
내 응용 프로그램은 guice를 사용하고 인터페이스가 매우 많습니다.
프로그램 설계에 대한 질문은 일반적으로 장단점을 수반하며 모든 답을 한 번에 해결할 수있는 것은 아닙니다. 왜 작은 200 라인 프로그램에서이 기술을 사용하겠습니까? 내 다른 아키텍처 선택을 고려할 때 내 특정 문제에 대해 의미가 있습니다. :)