달력

05

« 2012/05 »

  •  
  •  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  •  
  •  
2010/08/04 10:24

javadoc의 주석 태그 패턴/구현패턴2010/08/04 10:24


@exception : 메소드에서 발생할 수 있는 예외를 기술(method 뒤에 throws가 있을 때 사용)
@throws : @exception과 동일하나 method 뒤에 throws가 없고 코드상에서 RuntimeException이 발생할 때 사용


대충 작성중...
저작자 표시 비영리 변경 금지
크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by 스쿨쥐
2010/08/03 16:50

개발시 참조할 용어정리 패턴/구현패턴2010/08/03 16:50

프로젝트에서 개발시에 참조할 용어정리 중....
  1. 퍼시스턴트
    • create
    • read
    • update
    • delete

  2. 도메인(비지니스)
    • add, register ...
    • inquiry, find, search...
    • modify, change, to, convert, revise ...
    • remove, cancel, destroy ...
저작자 표시 비영리 변경 금지
크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by 스쿨쥐

보통 비지니스 로직을 구현하는 부분에 있어서는 비지니스 로직을 글이나 말로 설명하듯이 코드를 작성하는 것이 좋습니다. 물론 어플리케이션 로직과 100% 분리는 할 수 없겠지만 노력은 해야합니다. 이런 노력을 기울인다면 컴퓨터가 이해하는 로직이 아닌 사람이 이해하는 로직을 짤 수 있지 않을까 합니다.

자판기에서 커피를 뽑는 것을 생각해봅시다.
1. 자판기에 동전을 넣습니다.
2. 자판기에서 금액에 맞는 커피 종류 버튼에 불이 들어옵니다.
3. 불이 들어온 버튼을 누릅니다.
4. 커피 나오는 곳에서 불이 켜지면서 자판기에서 일정시간동안 커피를 만듭니다.
5. 커피를 만들고 나면 커피나오는 곳의 불이 꺼지게 됩니다.

아래의 경우와 비교해봅시다.
1. 자판기는 기존 금액에 동전만큼의 금액을 더합니다. 
2. 커피의 종류 중 금액보다 작은 커피의 종류에 불켜짐 속성을 true로 바꿉니다.
3. 버튼을 누릅니다. 자판기는 해당 버튼의 불켜짐 속성이 true인지 false인지 비교를 합니다. 
4. 불켜짐 속성이 true이면 커피 나오는 곳의 불켜짐 속성을 true로 하고, 해당 커피를 설탕 ~g과 커피 ~g, 물 ~cc를 넣어서 섞습니다.
5. 커피를 만들고 나면 커피 나오는 곳의 불켜짐 속성을 false로 바꿉니다.

위쪽이 훨씬 이해하기가 쉽지 않을까요? 물론 코드 자체는 굉장히 유사할 수 있지만 로직을 구현하는 부분에서 비지니스 설명단위로 메서드를 표현하고 메서드명을 의도에 맞게 이름을 짓는 것이 좋습니다. 예를 들어, 자판기에 동전을 넣는 것을 setMoney 또는 addMoney라고 하는 것보다 insertCoin이 훨씬 낫겠지요.

서비스 명이나 도메인에 있어서의 메서드 명은 의도가 분명히 들어나는 이름을 사용해야 할 것이고, DAO를 통해 데이터베이스에 값을 저장하는 것과 같이 어플리케이션 로직에서는 그에 맞는 이름을 사용해야 할 것입니다.

저작자 표시 비영리 변경 금지
크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by 스쿨쥐
비지니스 로직을 구현하다 보면 다음과 같은 코드를 작성할 경우가 있다.

public int getWorkingDay() {
     return DateUtil.diff(getStartDate(), new Date()) + 1;    
}

위의 예제는 근무일을 계산하는 예제이다. 근무일 = 근무시작일과 오늘(현재날짜)의 차이 + 1의 계산공식을 통해서 구할 수 있다.

이럴때 테스트하기란 참 어렵다. 오늘은 항상 바뀌기 때문이다. 오늘 성공한 테스트케이스가 내일이면 분명히 실패할 것이다. 물론 사용하는데 있어서 전혀 문제가 없지만 어떠한 특정 계산을 하는 클래스가 시간에 종속이 되면 테스트도 힘들뿐더러 재사용하기도 난감한 경우가 있다.

이를 위해서 다음과 같은 절차를 따른다.

1. new Date()와 같이 시간이 들어가는 부분이 있다면 DI를 이용해서 기준일을 넣는다.
public class Employee {
    private Date baseDate;  // 기준일
    private Date startDate;  // 근무시작일

    public Date setDate(Date baseDate){
        this.baseDate = baseDate;
    }
}

2. new Date()가 들어가는 부분을 baseDate로 바꾼다.
public int getWorkingDay() {
     return DateUtil.diff(getStartDate(), getBaseDate()) + 1;    
}

위의 절차대로 바꾸면 테스트하기 쉬운구조가 된다. baseDate만 넣으면 항상 테스트결과는 동일하다. 그럼 baseDate는 언제 값을 설정하는가? 서비스 컴포넌트에서 Entity도메인을 생성하는 시점에 넣어주면 된다.

다음 예제를 보라.
public class EmployeeServiceImpl implements EmployeeService{
    ...

    public int readWorkingDayByEmployeeId(Long employeeId){
        Employee e = readEmployee(employeeId);
       e.setBaseDate(new Date());
       return e.getWorkingDay();

    }

    ...
}

즉, 서비스 컴포넌트에서 실제 시간을 주입하고, 엔티티 컴포넌트에서는 시간에 독립적이어야한다. 엔티티 컴포넌트를 조립하여 서비스 컴포넌트를 만들때 영업일 개념이 들어가게 되면 처음에 만든 예제와 같이 되어있다면 재활용성이 매우 떨어지기 때문이다. 

마지막 예제에서도 좀 더 손을 보면 좋을듯하다. 지금은 new Date()를 통해서 현재날짜를 넣고있지만 상황에 따라서는 영업일 개념이 들어가야할 것이다. 즉, new Date()로 구현하지 말고 영업일을 담당하는 클래스 또는 컴포넌트를 만들고 그곳에서부터 기준일을 가져와야 할 것이다. 그렇게되면 일관성있는 날짜 정책을 수립할 수 있다.

더 좋은 방법은 차라리 날짜를 파라미터로 받는 것이다 ^^;;

ps. 사실 기준일을 setBaseDate로 넣어주는 것을 잊어버릴 수 있다. 생성자에서 받아도 좋으나 가장 좋은 방법은 getWorkingDay에 파라미터로 baseDate를 받고, private 변수 자체를 없애는 것이다. 즉, getWorkingDay(Date baseDate) 이런식으로...
저작자 표시 비영리 변경 금지
크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by 스쿨쥐
2009/10/27 00:08

Integer와 int 패턴/구현패턴2009/10/27 00:08

Integer와 int 관계와 같은 wrapper 클래스 - primitive 타입의 관계는 어떤 기준을 가지고 구분하는 것이 좋을까?

이에 대한 소장님의 답변과 내가 경험한 것을 바탕으로 내린 결과는 다음과 같다.

1. indentity를 가진다면 Integer로 만들어야 하고, 순수 값의 의미라면 int를 쓰는 것이 맞다.
ex.)
PK, FK의 시퀀스값(ID) : Integer
나이, 점수 : int

2. DB에서 null이 반드시 필요한 경우 Integer를 사용한다. int로는 null이 불가능하다.

만약 값의 의미지만 null이 필요한 경우는 어떻게 할 것인가? 내 생각은 다음과 같다. 

먼저 1번의 원칙을 충실히 따른다. null이 허용된다는 것은 반드시 필요한 값이 아니라는 것이다. 즉, 도메인의 입장에서 반드시 필요한 정보는 아니라는 것이다. 오라클에서는 테이블 생성시 not null 컬럼과 null 컬럼끼리 인접하게 만든다고 한다. 

그와 마찬가지로 도메인에서 반드시 필요한 정보와 부가 정보를 구분해서 필수정보에는 int로 사용하고 부가정보는 따로 관리하면 문제가 없으리라 생각된다. 또한 철저히 VO객체를 만들어 사용한다면 해결될 것이다.

예를들어 개인신체정보를 나타내는 클래스를 만들어보자.

public class Person {
    Integer id;
    String name;
    int height;
    int weight;
    Integer shoesSize;   << null 컬럼이라고 가정
}

원래는 이와 같은 모양일 것이다. 다음과 같이 바꾸어보자.

public class Person {
    Integer id;
    String name;
    int height;
    int weight;
    PersonAdditionalInfo personAdditionalInfo;
}

public class PersonAdditionalInfo {
    Integer shoesSize;
}

위에서 언급한 것처럼 오라클에서 not null, null 컬럼을 나누듯 필수 정보와 부가정보를 별도의 클래스로 나누었으며, Integer와 int가 둘 다 값의 의미로써 혼용되는 것을 어느정도 막을 수 있었다.

물론 이 방법을 통해서 모든것이 해결되지는 않겠지만 적절한 가이드 역할은 할 수 있다고 생각한다.


저작자 표시 비영리 변경 금지
크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by 스쿨쥐
2009/10/26 16:52

Exception Naming 패턴/구현패턴2009/10/26 16:52

다음 명명규칙은 순전히 스쿨쥐만의 규칙이므로 참조만 하시기 바랍니다.

1. 공통
- ParameterException : 메서드의 parameter로 받은 값이 null일 때 발생한다. null을 허용하는 메서드라면 예외가 발생하지 않는다.
(java.lang.IllegalArgumentException을 쓸 것)
- ValidationException : 유효성 검증에 실패하면 예외가 발생한다.

2 서버
 - BusinessException : 비지니스 로직 수행 중 비지니스에 정의되어 있지 않거나, 제외하기로 한 비지니스가 생길 때 예외가 발생한다.
 - DataAccessException : DB에 접근하여 작업도중 문제가 생기면 예외가 발생한다.
저작자 표시 비영리 변경 금지
크리에이티브 커먼즈 라이선스
Creative Commons License

'패턴 > 구현패턴' 카테고리의 다른 글

날짜에 종속적인 도메인을 개발할 때 주의점  (2) 2009/11/12
Integer와 int  (0) 2009/10/27
Exception Naming  (0) 2009/10/26
알고리즘이냐? 자료구조냐?  (0) 2009/09/25
String(or int) vs Enum  (0) 2009/03/06
null 및 예외처리 방법  (0) 2008/10/15
Posted by 스쿨쥐
 어떠한 문제를 해결할 때는 2가지 방법을 사용할 수 있다.

1. 알고리즘
2. 자료구조

 보통의 경우 알고리즘으로 해결하는 방법이 가장 일반적이다. 하지만 간혹 자료구조를 잘 사용하면 알고리즘은 굉장히 단순해지고 쉽게 해결되는 경우가 있다.

 예를들어 버그질라 상태값을 살펴보자.


 이런 상태변경을 알고리즘, 쉽게 말해 if, else로 해결한다고 가정해보자. 얼마나 많은 조건문이 발생할 것이며,  상태가 하나 추가된다던가 정책이 바뀌면 굉장히 난감할 것이다.

 이런 것을 자료구조로 해결하면 굉장히 단순해진다.

 TO \ FROM UNCONFIRMED  NEW ASSIGNED  RESOLVED REOPEN VERIFIED CLOSED 
UNCONFIRMED  X  X   X  O  X  O  O
NEW  O  X  O  X  X  X  X
ASSIGNED  O  O  X  X  O  X  X
RESOLVED  O  O  O  X  O  X  X
REOPEN  X  X  X  O  X  O  O
VERIFIED  X  X  X  O  X  X  X
CLOSED   X  X  X  O  X  X  X

 자료구조로 문제를 접근하면 훨씬 가독성도 높고 간단해지며, 상태 추가나 정책이 바뀜으로인해서 수정해야 할 것이 명확하게 보인다. 고치기도 쉽다.

 이렇듯이 문제를 해결할 때 알고리즘으로 해결하는 방법과 자료구조로 해결하는 방법을 같이 생각한 후 쉬운 쪽을 택하면 된다.


참고링크 :

http://en.wikipedia.org/wiki/Finite-state_machine

http://en.wikipedia.org/wiki/State_transition_table
저작자 표시 비영리 변경 금지
크리에이티브 커먼즈 라이선스
Creative Commons License

'패턴 > 구현패턴' 카테고리의 다른 글

날짜에 종속적인 도메인을 개발할 때 주의점  (2) 2009/11/12
Integer와 int  (0) 2009/10/27
Exception Naming  (0) 2009/10/26
알고리즘이냐? 자료구조냐?  (0) 2009/09/25
String(or int) vs Enum  (0) 2009/03/06
null 및 예외처리 방법  (0) 2008/10/15
Posted by 스쿨쥐
2009/03/06 14:42

String(or int) vs Enum 패턴/구현패턴2009/03/06 14:42


  • String 타입 (또는 int)

    public class Color {
    public final static String RED   = "red";
    public final static String GREEN = "green";
    public final static String BLUE  = "blue";
    } 
  • Enum 타입

    public Enum Color {
    RED,
    GREEN,
    BLUE
    }



Enum 타입은 유일성을 보장하기 때문에 되도록이면 Enum 타입을 권장한다. 만약 JDK버전이 1.5이전 버전이라면 Enum 타입을 사용할 수 없다. 이럴경우 유일성을 보장하기 위해서는 다음과 같이 구현하면 된다.

  • Enum 타입처럼 구현된 클래스
    public class Color {
          public final static Color RED   = new Color("red");
          public final static Color GREEN = new Color("green");
          public final static Color BLUE  = new Color("blue");


          private final String name;

          private Color(String name) {

              this.name = name;
          }

          public String toString() {
              return name;
          }
    }
저작자 표시 비영리 변경 금지
크리에이티브 커먼즈 라이선스
Creative Commons License

'패턴 > 구현패턴' 카테고리의 다른 글

날짜에 종속적인 도메인을 개발할 때 주의점  (2) 2009/11/12
Integer와 int  (0) 2009/10/27
Exception Naming  (0) 2009/10/26
알고리즘이냐? 자료구조냐?  (0) 2009/09/25
String(or int) vs Enum  (0) 2009/03/06
null 및 예외처리 방법  (0) 2008/10/15
Posted by 스쿨쥐
2008/10/15 17:18

null 및 예외처리 방법 패턴/구현패턴2008/10/15 17:18

  •  null 및 예외처리 규칙
    1. 메서드를 정의하는 부분에서 null일때 예외를 던질 것인가?
    2. 메서드를 사용하는 부분에서 null을 확인하고 처리할 것인가?
    3. 1번과 2번을 동시에 사용하지는 마라. (둘 중 하나 선택)
    4. RuntimeException의 경우 컴파일시 체크하지 않으므로 잘 사용하면 코드를 줄일 수 있다.
    5. 약정에 의한 프로그래밍을 할 것인지, 방어적 프로그래밍을 할 것인지에 대한 것은 고객의 요구나 업무 지침에 따르도록 한다.

  • 약정에 의한 프로그래밍
    - 트랜잭션의 양쪽 대상이 무슨 행동이 무슨 행위를 발생시키는지 알고 있다는 가정하에 프로그래밍을 하는 것
    - 예외 상황에 대한 특별한 처리를 하지 않는다.(컴파일때 처리를 하지 않아도 컴파일 에러가 발생하지 않는다.)
    - 오류 발생시 대부분 null이나 0, -1, RuntimeException 종류의 예외 상황 등을 반환한다.

    ... 

    public Object getProperty(String property){ 
        ...  

        // properties는 Map형태로 속성을 저장하는 컬랙션이다.  
        // 컴파일시는 필요 없지만 실행이 발생하는 RuntimeException을 던진다. 호출한 쪽에서 처리해야한다.
        if(properties == null){ 
            throw new RuntimeException("이 유닛은 속성이 없습니다."); 
        }  

        ...  

        // value가 null이라도 그대로 반환한다.
        Object value = properties.get(property);    
        return value; 
    }

    ...


  • 방어적 프로그래밍
    - 잘못될 것을을 찾아서, 문제 상황을 회피할 수 있도록 폭넓게 테스트한다.
    - 예외 상황에 대한 처리를 내부적으로 구현하거나 예외 처리를 필수적으로 하기 위해서 컴파일때 에러가 발생하도록 한다.
    - 오류 발생시 대부분 비어있는 객체나 컴파일시 예외처리가 필요한 Exception 종류의 예외 상황 등을 반환한다.
    ... 

    public Object getProperty(String property) throws IllegalAccessException{  
        ...  

        // properties는 Map형태로 속성을 저장하는 컬랙션이다. 
        // 예외처리 필요한 Exception을 던진다.
        if(properties == null){   
            throw new IllegalAccessException("이 유닛은 속성이 없습니다."); 
        } 

        ...  

        // 빈 객체를 반환한다. 실제로 Object를 비어있는 객체로 만드는 경우는 없다. 
        Object value = properties.get(property); 
        if(value == null){ 
            value = new Object();
        } 
        return value;


    ...

 

저작자 표시 비영리 변경 금지
크리에이티브 커먼즈 라이선스
Creative Commons License

'패턴 > 구현패턴' 카테고리의 다른 글

날짜에 종속적인 도메인을 개발할 때 주의점  (2) 2009/11/12
Integer와 int  (0) 2009/10/27
Exception Naming  (0) 2009/10/26
알고리즘이냐? 자료구조냐?  (0) 2009/09/25
String(or int) vs Enum  (0) 2009/03/06
null 및 예외처리 방법  (0) 2008/10/15
Posted by 스쿨쥐