크리에이티브 커먼즈 라이선스
Creative Commons License
enum 객체는 상속이 되지 않기 때문에 공통된 부분을 상속을 사용해서 사용하지 못한다. 대신에 인터페이스와 static 오퍼레이션을 사용한다면 이와 유사하게 재사용할 수 있다.

예를 들어, 특정 코드값을 갖는 enum을 선언시 다음과 같이 사용할 수 있다.

public class CodeTest {

    private interface Codable {
        String getCode();
    }
   
    private static <E extends Enum<E> & Codable> E from(
            E[] values, String code) {
        for (E e : values)
            if (e.getCode().equals(code))
                return e;

        throw new IllegalArgumentException("Boring: " + code);
    }
   
    enum Gender implements Codable {
        MALE("1"), FEMALE("2");
       
        private final String code;
        Gender(String code) { this.code = code; }
        public String getCode() { return this.code; }
       
        static Gender makeCode(String genderCode) {
            return from(values(), genderCode);
        }
    }
   
    enum FixedCode implements Codable {
        THIS("001"), THAT("002");
       
        private final String code;
        FixedCode(String code) { this.code = code; }
       
        public String getCode() { return this.code; }
        static FixedCode makeCode(String fixedCode) {
            return from(values(), fixedCode);
        }
    }
}



저작자 표시 비영리 동일 조건 변경 허락
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

1. 관리

진실 1. 소프트웨어 작업에서 가장 중요한 요소는 프로그래머들이 사용하는 도구나 기술이 아닌 프로그래머들 자신들의 자질(quality)이다.

진실 2. "개인차" 조사에 따르면, 최고의 프로그래머는 최악의 프로그래머보다 28배나 생산성이 높다. 이들의 연봉이 결코 그만큼 받지 못한다는 사실로 미루어봐서 소프트웨어 분야에서 이들은 大 바겐세일용이다.

진실 3. 지연된 프로젝트에 사람을 투입하는 것은 프로젝트를 더 지연되게 만든다.

진실 4. 작업 환경은 생산성과 제품 품질에 깊은 영향을 준다.

진실 5. 과대 선전은 소프트웨어 업계에서 전염병이다. 대부분의 소프트웨어 도구와 기법들은 생산성과 품질에 있어서 약 5내지 35 퍼센트 가량 향상시켜준다. 하지만, 어느 시점이건 대부분의 그러한 향상성은 "대규모" 이익을 얻은 누군가가 주장해왔다.

진실 6. 새로운 도구나 기법을 배우는 것은 실질적으로 초기에 프로그래머의 생산성과 제품의 품질을 저하시킨다. 궁극적인 이익은 이러한 학습 곡선(learning curve)을 극복한 후에만 달성된다. 따라서, 이러한 도구나 기법의 가치가 현실적으로 보이거나, 인내라는 것이 이익에 같이 측정될 때에 새로운 도구와 기법을 적용할 만하다.

진실 7. 소프트웨어 개발자들은 도구에 대해서 수많은 이야기를 한다. 이들은 상당한 수의 도구들을 평가하고, 적당한 수만큼 도구들을 구매하며, 실제로는 아무 것도 사용하지 않는다.

진실 8. 실패한 프로젝트들의 두 가지 가장 공통된 원인 중에 한가지는 엉성한 예측(poor estimation)이다.

진실 9. 대부분의 소프트웨어 예측들은 초반에 이루어진다. 이는 요구사항이 정의되기 전인 문제를 이해하기 전에 예측을 할 수 있다고 깨달을 때까지 의미가 있다. 결국, 예측은 잘못된 시점에 발생된다.

진실 10. 대부분의 소프트웨어 예측들은 소프트웨어를 만들 사람이나 관리자가 아닌, 최상위 관리자나 영업(마케팅)에 의해서 결정된다. 결국, 예측은 잘못된 사람들이 하게 된다.

진실 11. 소프트웨어 예측들은 프로젝트 진행 중에 거의 바뀌지 않는다. 따라서 잘못된 시점에 잘못된 사람들이 했던 그러한 예측은 보통 바로 잡지는 못한다.

진실 12. 예측은 그렇게 잘못되었기 때문에 소프트웨어 프로젝트가 예측한 목표에 부합되지 않을 때 환기시킬 만한 사유가 거의 없다. 하지만, 모든 사람은 여하튼 환기를 부여 받는다.

진실 13. 관리와 프로그래머들 사이에는 연결고리가 없다. 예측에 실패하고 관리에서도 실패했다고 보는 프로젝트에 대한 한 연구 조사에서 기술적인 참여자들은 이전에 작업했던 가장 성공적인 프로젝트라고 생각했다.

진실 14. 타당성 조사 대한 대답은 늘 "yes"이다.

진실 15. '작은 것에서의 재사용 (서브 루틴의 라이브러리)' 은 거의 50년 전부터 시작되었으며 잘 풀려진 문제이다.

진실 16. '큰 것에서의 재사용 (컴포넌트)' 은 모든 사람이 매우 중요하고 바람직하다고 동의하더라도 대부분이 풀리지 않은 문제로 남겨져 있다.

진실 17. '큰 것에서의 재사용'은 관련된 시스템 군에서 가장 잘 적용되며 따라서 도메인에 의존적이다. 이는 큰 것에서의 재사용에 대한 잠재적인 적용 범위를 좁힌다.

진실 18. 재사용에는 두 가지 "세 개의 규칙"이 있다. 하나는 컴포넌트들을 사용하는 것보다 재사용 가능한 컴포넌트를 만드는 것이 세 배나 어렵다는 것이며, 다른 하나는 재사용 가능한 컴포넌트는 재사용 라이브러리로 인정받는 데 충분히 범용적이 되기 전에 세 번의 서로 다른 어플리케이션에서 시도해보아야 한다.

진실 19. 재사용된 코드를 수정하는 것은 특히 에러가 발생하기 쉽다. 만일 컴포넌트의 20내지 25 퍼센트가 변경된다면, 처음부터 다시 만드는 것이 더 효과적이고 효율적이다.

진실 20. 디자인 패턴 재사용은 코드 재사용에서 반복되는 문제들에 대한 한가지 해결책이다.

진실 21. 문제 복잡도가 25 퍼센트 증가할 때마다 소프트웨어 해결책에서는 100 퍼센트의 복잡도 증가가 발생한다. 이는 바꾸어야 할 조건이 아니다(복잡도의 감소가 항상 바람직한 것임에도 불구하고). 늘 그렇게 발생한다.

진실 22. 소프트웨어 작업의 80 퍼센트는 지적인 능력을 필요로 한다. 상당한 부분이 창의적이며, 사무적인 부분은 거의 없다.

허위1. 측정할 수 없는 것은 관리할 수 없다.

허위 2. 소프트웨어 제품으로 품질을 관리할 수 있다.

허위 3. 프로그래밍은 자신의 존재감을 느낄 수 없거나 느껴서는 안된다.

허위 4. 도구와 기법은 하나로 해결된다.

허위 5. 소프트웨어는 더 많은 방법론들을 필요로 한다.

허위 6. 비용과 일정을 예측하기 위해서 첫번째는 코드 라인 수를 예측하는 것이다.

2. 생명주기

진실 23. 실패한 프로젝트들 중의 두가지 가장 공통적인 원인 중에 하나는 수시로 바뀌는 요구사항이다.

진실 24. 요구사항의 실수나 에러는 제품화 동안에 발견되었을 때 수정 비용이 매우 비싸지만 개발 초기에는 수정 비용이 제일 싸다.

진실 25. 요구사항의 누락은 수정하기 가장 어려운 요구사항 에러이다.

진실 26. 요구사항 분석에서 설계로 넘어가는 도중에 해결 과정의 복잡도로 인해서 유발되는 "기인된 요구사항"(특정 설계 해결책에 대한 요구사항)) 의 폭발이 발생한다. 이러한 설계 요구사항의 목록은 원래 요구사항의 목록보다 50배나 더 길다.

진실 27. 소프트웨어 문제에 대해서 한가지 최상의 설계 해결책은 거의 없다.

진실 28. 설계는 복잡하고 반복적인 과정이다. 초기 설계 산출물은 잘못될 수 있으며 확실히 최적화된 상태는 아니다.

진실 29. 프로그래머들은 해결할 문제가 설계자가 담당했던 "최소 단위" 수준으로 분해될 때 설계에서 코딩으로 옮긴다. 만일 코더가 설계자와 동일한 사람이 아니라면 설계자의 최소 단위는 코더의 최소 단위와 일치하지 않을 수도 있으며, 여기서 문제가 발생된다.

진실 30. COBOL은 매우 나쁜 언어지만, 모든 다른 것들은(비즈니스 데이터 처리용으로) 그 만큼 더 나쁘다.

진실 31. 에러를 없애는 것은 생명주기에서 가장 시간을 많이 잡아먹는 단계이다.

진실 32. 일반적인 프로그래머가 전체적으로 테스트를 했다고 믿는 소프트웨어는 실행된 로직의 경로의 약 55 내지 60 퍼센트만 커버리지를 갖는다. 커버리지 분석기와 같은 자동화 도구를 사용하면 어림잡아 85 내지 90 퍼센트까지 증가될 수 있다. 로직 경로의 100 퍼센트 수준으로 소프트웨어를 테스트하는 것은 거의 불가능하다.

진실 33. 만일 100 퍼센트 테스트 커버리지가 가능하다고 하더라도, 이것인 테스팅의 충분 조건은 아니다. 소프트웨어 결점들의 약 35 퍼센트는 로직 경로의 누락에서 발견되며, 40 퍼센트는 로직 경로의 유일한 조합 실행으로 발견된다. 이것들은 100 퍼센트 커버리지에서 밝혀지는 것들이 아니다.

진실 34. 도구 없이 에러를 없애는 훌륭한 작업을 하는 것이 불가능한 것인 아니다. 디버거를 보편적으로 사용하지만, 커버리지 분석기와 같은 다른 것들은 사용하지 않는다.

진실 35. 테스트는 거의 자동화되지 않는다. 즉, 어떤 테스팅 과정은 자동화될 수 있거나 자동화되어야 한다. 하지만 자동화될 수 없는 수많은 테스팅 활동이 존재한다.

진실 36. 컴파일러 파라미터를 기반으로 객체 코드에 가능하면 선택적으로 포함된 프로그래머가 만든 내부 디버그 코드는 테스팅 도구에게 중요한 부연 설명서와 같다.

진실 37. 엄격한 검사(inspection) 활동은 첫 테스트 케이스를 실행하기 전에 소프트웨어 제품으로부터 90 퍼센트까지 에러를 없애줄 수 있다.

진실 38. 엄격한 검사(inspection) 활동의 이점에도 불구하고, 테스팅을 대체할 수 있다거나 대체해서는 안된다.

진실 39. 인도후 검토(postdelivery review, 보통 "retrospective"라고 함) 과정은 고객 만족도를 결정한다는 측면과 프로세스 향상이라는 측면 모두 중요하다고 일반적으로 인정된다. 하지만 대부분의 조직들은 인도후 검토 과정을 하지 않는다.

진실 40. 쌍으로 검토하는 것은 기술적인 동시에 사회적이다. 다른 사람 없이 한 사람을 주목하는 것은 재앙에 대한 처방이다.

진실 41. 유지보수는 전형적으로 소프트웨어 비용의 40 내지 80 퍼센트(평균 60 퍼센트)가 든다. 따라서, 이 단계가 아마도 소프트웨어의 가장 중요한 생명주기 단계이다.

진실 42. 기능 강화가 소프트웨어 유지보수 비용의 대략 60 퍼센트를 차지한다. 에러 수정은 약 17 퍼센트이다. 따라서, 소프트웨어 유지보수는 대부분이 기존 소프트웨어에 새로운 기능을 추가하는 것이며, 수정이 아니다.

진실 43. 유지보수는 해결책이지, 문제가 아니다.

진실 44. 소프트웨어 개발과 소프트웨어 유지보수 작업에 대한 조사에서 대부분의 작업은 "기존 제품에 대한 이해" 라는 추가적인 유지보수 작업을 제외하고 동일하다. 이 작업은 전체 유지보수 시간의 개략적으로 30 퍼센트를 차지하며 주요한 유지보수 활동이다. 따라서 유지보수가 개발보다 더 어려운 작업이라고 말하는 것이 가능하다.

진실 45. 더 나은 소프트웨어 공학 개발이 결코 더 적지 않은 더 많은 유지보수를 낳게 한다.

허위 7. 랜덤 테스트 입력은 테스팅을 최적화하는 좋은 방법이다.

허위 8. "보는 눈이 많으면, 모든 버그들은 사라질 것이다."

허위 9. 미래 유지보수 비용을 산정하고 제품을 교체하기 위한 결정을 하는 방법은 과거 비용 데이터를 살펴보는 것이다.

3. 품질

진실 46. 품질은 속성들의 집합이다.

진실 47. 품질은 사용자 만족이나, 요구사항을 부합하는 것, 비용과 일정 목표를 준수하는 것, 혹은 신뢰성이 아니다.

진실 48. 대부분의 프로그래머들이 저지르기 쉬운 에러들이 존재한다.

진실 49. 에러들은 한데 모아져 있는 경향이 있다.

진실 50. 소프트웨어 에러를 없애는 유일한 최상의 방법은 없다.

진실 51. 남아 있는 에러들은 늘 지속되기 마련이다. 목표는 심각한 에러들을 최소화하거나 없애는 것이다.

진실 52. 효율성은 좋은 코딩 보다는 좋은 설계로부터 기인한다.

진실 53. 적절한 컴파일러 최적화를 가지는 고수준 언어 (High-Order Language, HOL) 코드는 어셈블리 코드보다 약 90 퍼센트 가량 효율적일 수 있다. 혹은 어떤 복잡한 아키텍처에 대해서는 더 높다.

진실 54. 크기와 시간 최적화 사이에는 균형이 필요하다. 종종 어느 한쪽의 향상은 다른 한쪽의 저하를 가지고 온다.

4. 연구

진실 55. 많은 소프트웨어 연구자들은 조사나 탐구보다는 주장이나 이론을 세운다. 그 결과로 몇몇 주장된 개념들은 옹호자들이 믿었던 것보다도 훨씬 덜 가치가 있으며, 그러한 개념들의 가치가 진정으로 무엇인지를 결정하는데 도움을 주는 평가하는 연구가 부족하다.

5. 교육

허위 10. 사람들에게 어떻게 프로그램을 작성하는지를 보여줌으로써 프로그래밍하는 방법을 가르친다.

신고
크리에이티브 커먼즈 라이선스
Creative Commons License
다음의 패턴은 Hibernate에서 예전이나 지금이나 여전히 보편적이지만, Hibernate3 에서 이 문제를 해결하는 다른 방법이 있다.

다음과 같은 저장 클래스를 가지고 있다고 가정하자.
public class Document implements Node {
   private Long _key;
   private String _name;
   private Calendar _created;
   private Calendar _updated;
   private Folder _folder;
   private Clob _text;
   public String getKey() { return _key; }
   public void setKey(Long key) { _key = key; }
   public String getName() { return _name; }
   public void setName(String name) { _name = name; }
   public Calendar getCreated() { return _created; }
   public void setCreated(Calendar created) { _created = created; }
   public Calendar getUpdated() { return _updated; }
   public void setUpdated(Calendar updated) { _updated = updated; }
   public Folder getFolder() { return _folder; }
   public void setFolder(Folder folder) { _folder = folder; }
   public Clob getText() { return _text; }
   public void setText(Clob text) { _text = text; }
}
이 클래스의 모든 속성들은 DOCUMENTS 테이블의 컬럼에 매핑된다. 성능상의 이유로 문서 리스트를 가지고오거나, 문서의 이름을 변경하거나, 문서를 옮기는 등의 매순간마다 포함되어 있는 CLOB 데이터에 대한 스트림을 열기 원치 않는다. 어떤 상용 OR 매핑 도구는 기본적인 초시화 속성을 세팅하여 처음에 조회를 하도록 한다. 나머지 속성들은 처음 접근될 때 가지고 온다. Hibernate3는 이와 같은 특성을 가지고 있지만, Hibernate2는 그렇지 않다. 하지만, 그러한 방법보다도 더 성능을 잘 내도록 하는 잘쓰는 방법이 있다.

Document 클래스를 "가벼운" 상위 클래스와 "무거운" 하위클래스로 나눈다.
public class DocumentInfo implements Node {
   private Long _key;
   private String _name;
   private Calendar _created;
   private Calendar _updated;
   private Folder _folder;
   public String getKey() { return _key; }
   public void setKey(Long key) { _key = key; }
   public String getName() { return _name; }
   public void setName(String name) { _name = name; }
   public Calendar getCreated() { return _created; }
   public void setCreated(Calendar created) { _created = created; }
   public Calendar getUpdated() { return _updated; }
   public void setUpdated(Calendar updated) { _updated = updated; }
   public Folder getFolder() { return _folder; }
   public void setFolder(Folder folder) { _folder = folder; }
}

public class Document extends DocumentInfo {
   private Clob _text;
   public Clob getText() { return _text; }
   public void setText(Clob text) { _text = text; }
}
다음과 같이 매핑을 한다.
<class name="DocumentInfo" table="DOCUMENTS">
   <id name="key" type="long" column="ID">
       <generator class="native"/>
   </id>
   <property name="name"/>
   <property name="created"/>
   <property name="updated"/>
   <many-to-one name="folder"/>
</class>

<class name="Document" table="DOCUMENTS" polymorphism="explicit">
   <id name="key" type="long" column="ID">
       <generator class="native"/>
   </id>
   <property name="name"/>
   <property name="created"/>
   <property name="updated"/>
   <many-to-one name="folder"/>
   <property name="text"/>
</class>
이제 어플리케이션은 정보만을 원한다면 DocumentInfo의 인스턴스를 조회할 수 있으며, text 속성을 접근할 필요가 있는 경우 Document 인스턴스를 조회할 수 있다. polymorphism="explicit" 를 사용해서 Document를 매핑하고 있기 때문에 다음과 같은 쿼리들은 DocumentInfo를 반환한다.
from DocumentInfo
from Node
from java.lang.Object
다음의 쿼리는 Document 인스턴스만을 반환한다.
from d in class Document

주의 : Hibernate2에서 두개의 서로 다른 객체로 동일한 데이터베이스의 행을 로딩할 수 없다. 그렇기 때문에 Hibernate가 객체를 캐스팅하지 못해서 동일한 Document ID의 Document 다음의 DocumentInfo를 먼저 로딩할 수 없다. 예를 들어, 다음의 코드는 ClassCastException이 발생할 것이다.
DocumentInfo info = (DocumentInfo) session.load(DocumentInfo.class, new Long(1));
Document doc = (Document) session.load(Document.class, new Long(1));

DocumentInfo와 Document로 동일한 Document를 얻어오려면 session.evict() 나 먼저 DocumentInfo를 사용할 필요가 있다. 혹은 클래스 매핑에 polymorphism="explicit"를 추가하면 로더가 동일한 테이블에 매핑되는 서로 다른 클래스에 매핑되는 것을 방해하는 것을 멈추고 동일한 PK를 공유하는 것을 멈추게 한다.

논란의 여지가 있지만 Hibernate는 지연 로딩(lazy loading) 기능이 진정으로 필요하지 않을 수도 있음을 유의하라. 왜냐하면 쿼리가 project을 지원하고 자바 코드를 통해 정확하게 필요한 속성을 끄집어오게끔 하는 것이 가능하기 때문이다.
신고

+ Recent posts

티스토리 툴바