(Java) 패키지 구성에 대한 모범 사례가 있습니까? [닫은]


201

얼마 전, 세밀한 자바 패키지 구성에 관한 질문에 답했습니다. 예를 들어, my.project.util, my.project.factory, my.project.service등과

나는 지금 그것을 찾을 수 없으므로 질문을 할 수도 있습니다.

Java 패키지 구성과 관련하여 모범 사례가 있습니까?

Java 프로젝트에서 클래스를 어떻게 구성합니까?

예를 들어, 소수의 사람들과 함께 작업하는 프로젝트에는 bean이라는 패키지가 있습니다. 간단한 콩을 포함하는 프로젝트로 시작되었지만 (거의) 모든 것을 포함하는 (빈약 한 경험과 시간 부족으로) 끝났습니다. 팩토리 패키지 (빈을 생성하는 정적 메소드가있는 클래스)에 팩토리 클래스를 넣어서 약간 정리했지만 비즈니스 로직을 수행하는 다른 클래스와 검색과 같은 간단한 처리 (비즈니스 로직이 아닌)를하는 다른 클래스가 있습니다. 특성 파일의 코드에 대한 메시지

당신의 생각과 의견에 감사드립니다.


74
이 질문의 종결에 동의하지 않습니다. 모범 사례 질문이 거의 항상 경험과 의견에 근거한다는 데 동의하지 않지만 이러한 질문을 스택 오버플로에서 닫아야한다는 데 동의하지 않습니다. 이것은 모범 사례를 사용하고 최상의 솔루션을 찾는 것이 이러한 의견과 경험을 사용하는 훌륭한 프로그래밍의 요점입니다. 이 질문을 다시여십시오.
Cyntech

satisfice.com/blog/archives/5164 를 읽어 보시기 바랍니다 . TL; DR ... "모범 사례"에 대한 모든 아이디어가 깨졌습니다. 기껏해야 그것은 엄청나게 잘못된 이름이며, 최악의 경우 완전히 해 롭습니다.
Stephen C

답변:


174

패키지 구성 또는 패키지 구조화는 일반적으로 열띤 토론입니다. 다음은 패키지 이름 지정 및 구조화에 대한 간단한 지침입니다.

  • 자바 패키지 명명 규칙 준수
  • 기능적 역할 및 비즈니스 역할에 따라 패키지 구성
    • 기능 또는 모듈에 따라 패키지를 분류하십시오. 예 : com.company.product.modulea
    • 추가 분류는 소프트웨어의 계층을 기반으로 할 수 있습니다. 그러나 패키지에 클래스가 거의없는 경우에는 배 안에 가지 마십시오. 패키지에 모든 것이있는 것이 좋습니다. 예를 들어, com.company.product.module.web또는 com.company.product.module.util
    • 구조화를하지 말고, IMO는 긴급한 요구가없는 한 예외, 공장 등을 위해 별도의 포장을 피하십시오.
  • 프로젝트가 작은 경우 몇 개의 패키지로 간단하게 유지하십시오. 예를 들어 com.company.product.modelcom.company.product.util
  • Apache 프로젝트 에서 널리 사용되는 오픈 소스 프로젝트 중 일부를 살펴보십시오 . 다양한 규모의 프로젝트에 대해 구조화를 사용하는 방법을 확인하십시오.
  • 이름을 지정할 때 빌드 및 배포도 고려하십시오 (API 또는 SDK를 다른 패키지로 배포 할 수 있습니다 (서블릿 API 참조)).

몇 가지 실험과 시험을 마치고 나면 편안한 구조를 만들 수있을 것입니다. 하나의 규칙으로 고치지 말고 변경 사항을 공개하십시오.


답변 주셔서 감사합니다. 이것은 주로 우리가 포괄하려고 시도한 것이지만 많은 관련없는 코드가 bean 패키지에 들어갔습니다.
Cyntech

2
기능별 패키지가 가장 적합하다는 데 동의합니다. 한때 회사 사무실 구조와 관련하여 큰 비유를 들었습니다. 계층화 된 접근 방식에서, 회사의 각 레벨마다 개인, 즉 임원, 관리자, 관리자, 직원 / 직원은 모두 건물에서 별도의 섹션에 앉아 있습니다. 이 구조는 "기능"으로 구성된 접근 방식만큼 효과적이지 않을 수 있습니다. 즉, 영업 관리자가 영업 관리자와 함께 앉아있는 영업 사원과 함께 영업 관리자와 함께있는 경우입니다. 이것은 이런 방식으로 조직 될 때 부서간에 더 나은 응집력을 제공합니다.
alex

당신의 요점에 동의하십시오. 회사에서 인수 한 제품이 판매되는 경우가 종종 있습니다. 경영진이 회사 이름을 제거하려고합니다. 오버 헤드 일 수 있습니다.
Tushar D

183

패턴이나 구현 역할이 아닌 기능별로 패키지 구성 합니다. 패키지는 다음과 같습니다.

  • beans
  • factories
  • collections

잘못되었습니다.

예를 들어 선호합니다.

  • orders
  • store
  • reports

패키지 가시성을 통해 구현 세부 사항을 숨길 수 있습니다 . 주문 팩토리는 orders패키지에 있어야하므로 주문 작성 방법에 대한 세부 사항이 숨겨집니다.


10
이 게시물에서는 패키지 가시성에 대해 설명합니다. Java 패키지 범위가 사용되는 것을 본 적이 없지만 올바른 패키지 구조를 사용하면 개발자가 더 잘 활용할 수 있습니다.
Jpnh

23
이것은 정확하지만 개발자는 거의 없습니다. 패키지는 응집력있는 클래스 모음이어야하며, 일부는 패키지 내에서만 볼 수 있습니다. 그것은 서로 다른 기능과 관련되어 있기 때문에 결합해서는 안되는 클래스 간의 결합을 최소화합니다. 패키지 별 접근 방식은 패키지 가시성 수정자를 이용하지 않으며, 이러한 프로젝트의 패키지는 응집력이 낮고 패키지 간의 결합 정도가 높습니다.
네이트 리드

이것의 예가 있습니까? Spring은 config xml을 사용하기 때문에 Spring-MVC를 사용하고 있습니다. 기능 / 모듈별로 구성하기가 어렵다는 것을 알았습니다.
Eric Huang

2
@onof 또한 기능별로 코드를 구성하지만 모든 기능이 공유하는 기본 클래스의 모범 사례는 무엇입니까?
Marc

나는 첫 번째 스타일을 따르고 있었다. 그러나 이제 클래스로 작업 할 때 한 패키지에서 다른 패키지로 점프해야합니다. 실제로 나쁜 경험을합니다. 관련 클래스를 함께 따르는 것이 더 쉬울 것이라고 생각하기 때문에 이제 두 번째 스타일로 전환하고 있습니다.
M.kazem Akhgary

40

짧은 답변 : 모듈 / 기능 당 하나의 패키지 (하위 패키지 포함). 밀접하게 관련된 것들을 같은 패키지에 넣습니다. 패키지 간의 순환 종속성을 피하십시오.

긴 대답 : 이 기사의 대부분에 동의합니다


2
하위 패키지는 캡슐화를 중단합니다. "하위 패키지"는 그 자체로 완전히 독립적 인 패키지입니다
Ricardo Gamba

21

레이어보다 기능을 선호하지만 프로젝트에 따라 다릅니다. 당신의 힘을 고려하십시오 :

  • 종속성
    특히 기능 간의 패키지 종속성을 최소화하십시오. 필요한 경우 API를 추출하십시오.
  • 팀 구성
    일부 조직에서 팀은 기능에 대해 작업하고 다른 조직 에서는 계층에 대해 작업합니다. 이는 코드 구성 방식에 영향을 미치며이를 사용하여 API를 공식화하거나 협력을 장려합니다.
  • 배포 및 버전 관리
    모듈에 모든 것을 넣으면 배포 및 버전 관리가 간단 해지지 만 버그 수정이 더 어려워집니다. 분할하면 제어, 확장 성 및 가용성이 향상됩니다.
  • 변화에 대응하기
    잘 조직 된 코드는 큰 진흙 공보다 변경하기가 훨씬 간단합니다.
  • 크기 (사람과 코드 줄)
    더 형식화 / 표준화되어야합니다.
  • 중요성 / 품질
    일부 코드는 다른 코드보다 중요합니다. API는 구현보다 안정적이어야합니다. 따라서 명확하게 분리해야합니다.
  • 추상화 수준과 진입 점
    외부인이 코드의 내용과 패키지 트리를보고 읽을 위치를 알 수 있어야합니다.

예:

com/company/module
  + feature1/
    - MainClass          // The entry point for exploring
    + api/               // Public interface, used by other features
    + domain/
      - AggregateRoot
      + api/             // Internal API, complements the public, used by web
      + impl/ 
    + persistence/       
    + web/               // presentation layer 
    + services/          // Rest or other remote API 
    + support/            
  + feature2/
  + support/             // Any support or utils used by more than on feature
    + io
    + config
    + persistence
    + web

이것은 단지 예일뿐입니다. 꽤 형식적입니다. 예를 들어 feature1에 대해 2 개의 인터페이스를 정의합니다 . 일반적으로 필요하지는 않지만 다른 사람들이 다르게 사용하는 경우 좋은 아이디어가 될 수 있습니다. 내부 API를 공개적으로 확장 할 수 있습니다.

나는 'impl'또는 'support'이름을 좋아하지 않지만 덜 중요한 것들을 중요한 것 (도메인 및 API)과 분리하는 데 도움이됩니다. 명명에 관해서는 가능한 한 구체적이고 싶습니다. 20 개의 클래스가있는 'utils'라는 패키지가있는 경우 StringUtilssupport / string, HttpUtilsupport / http 등으로 이동하십시오.


13

Java 패키지 구성과 관련하여 모범 사례가 있습니까?

아니에요 많은 아이디어와 의견이 있지만 실제 "모범 사례"는 상식을 사용하는 것입니다!

( "모범 사례"및이를 홍보하는 사람들에 대한 관점은 모범 사례 없음을 읽으십시오 .)

그러나 널리 받아 들여질 수있는 한 가지 원칙이 있습니다. 패키지 구조는 애플리케이션의 (비공식적 인) 모듈 구조를 반영해야하며, 모듈 간의 주기적 종속성을 최소화 (또는 이상적으로는 피)하는 것이 목표입니다.

(패키지 / 모듈의 클래스 간 순환 종속성은 훌륭하지만 패키지 간 사이클은 응용 프로그램의 아키텍처를 이해하기 어렵게 만들고 코드 재사용에 장애가 될 수 있습니다. 특히 Maven을 사용하면 주기적으로 패키지 간 / 모듈 간 종속성은 상호 연결된 전체 엉망이 하나의 Maven 인공물이어야 함을 의미합니다.)

또한 패키지 이름에 대해 널리 인정되는 모범 사례 하나 더 있다고 덧붙여 야 합니다. 즉, 패키지 이름은 조직의 도메인 이름으로 역순으로 시작해야합니다. 이 규칙을 따르면, 다른 사람들과 충돌하는 (전체) 학급 이름으로 인한 문제의 가능성이 줄어 듭니다.


9

일부 사람들이 '레이어 별 패키지'보다 '기능별 패키지'를 홍보하는 것을 보았지만 몇 년 동안 상당히 많은 접근 방식을 사용했으며 '피처 별 패키지'보다 '레이어 별 패키지'가 훨씬 낫습니다.

또한 '패키지 별 패키지'의 많은 장점이 있기 때문에 하이브리드 : '모듈 별 패키지, 레이어 및 기능'전략이 실제로 매우 효과적이라는 것을 알았습니다.

  • 재사용 가능한 프레임 워크 생성을 촉진합니다 (모델 및 UI 측면을 모두 갖춘 라이브러리)
  • 플러그 앤 플레이 레이어 구현을 허용합니다. '패키지 별 기능'에서는 모델 구현과 동일한 패키지 / 디렉토리에 레이어 구현을 배치하므로 사실상 불가능합니다.
  • 더 많은 ...

여기서 자세히 설명합니다 : Java 패키지 이름 구조 및 구성 하지만 표준 패키지 구조는 다음과 같습니다.

revdomain.moduleType.moduleName.layer. [layerImpl] .feature.subfeatureN.subfeatureN + 1 ...

어디:

revdomain 역 도메인 예 : com.mycompany

moduleType [app * | framework | util]

moduleName 예 : 모듈 유형이 앱인 경우 myAppName 또는 회계 프레임 워크 인 경우 '금융'

[유형 등]

layerImpl . 예를 들어, 개찰구는, JSP로, JPA는 JDO는 (주 : 사용하지 않는 계층이 모델의 경우) 최대 절전 모드

특징, 예 : 금융

하위 기능 예 : 회계

하위 기능 N + 1, 예 : 감가 상각

* moduleType이 응용 프로그램 인 경우 'app'가 누락되었지만 응용 프로그램을 넣으면 모든 모듈 유형에서 패키지 구조가 일관되게됩니다.


5

패키지 구성에 대한 표준 사례를 모릅니다. 나는 일반적으로 상당히 넓은 스펙트럼을 다루는 패키지를 만들지 만 프로젝트 내에서 차별화 할 수 있습니다. 예를 들어, 현재 작업중 인 개인 프로젝트에는 맞춤형 UI 컨트롤 (스위스 클래스를 스윙하는 클래스로 가득 찬)에 전용 패키지가 있습니다. 데이터베이스 관리에 전념하는 패키지가 있고, 내가 만든 리스너 / 이벤트 집합에 대한 패키지가 있습니다.

다른 한편으로 나는 동료가 자신이 한 거의 모든 것을위한 새로운 패키지를 만들도록했습니다. 그가 원하는 각각의 다른 MVC는 자체 패키지를 가지고 있었고 MVC 세트는 동일한 패키지에있을 수있는 유일한 클래스 그룹 인 것처럼 보였습니다. 한 시점에서 그는 각각 하나의 클래스를 가진 5 개의 서로 다른 패키지를 가지고있었습니다. 나는 그의 방법이 극단적이라고 생각합니다 (그리고 팀은 단순히 처리 할 수 ​​없을 때 패키지 수를 줄 이도록 강요했습니다). 그러나 사소한 응용 프로그램의 경우 모든 것을 동일한 패키지에 넣을 것입니다. 그것은 당신과 당신의 팀원이 스스로 찾아야 할 균형점입니다.

한 가지 뒤로 물러서서 생각해보십시오. 프로젝트에 신입 사원을 소개했거나 프로젝트가 오픈 소스 또는 API로 출시 된 경우 원하는 것을 찾기가 얼마나 쉬울까요? 나에게있어서 그것이 바로 패키지에서 원하는 것입니다 : 조직. 컴퓨터의 폴더에 파일을 저장하는 방법과 마찬가지로 전체 드라이브를 검색하지 않고도 파일을 다시 찾을 수있을 것으로 기대합니다. 패키지의 모든 클래스 목록을 검색하지 않고도 원하는 클래스를 찾을 수있을 것으로 예상됩니다.

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