Site Search :
Standard Enterprise XML Methodology Pattern Setting Tunning Other
Article Contributors
GuestBook
Javapattern Maven
XSourceGen Dev
JetSpeed Test
JLook Image
jLook Family Site


[개발] JavaPattern.info 코딩지침
 
놀새가 사용하는 개발의 지침을 설명한다. Sun의 recommendation이기도 하며, 쉽게 지나칠 수 있는 내용을 사이트를 다니며 범용적으로 사용할 수 있도록 취합한 내용이다. ( 2003/04/19 ) 812
Written by ienvyou - 최지웅
1 of 1
 


1.1 주석문 코딩 지침
* 주석문 입력 요령은 JavaDoc표준에 따르고 영문으로 기입한다.

1.1.1 문서화 주석문의 시작과 끝
시작 : /**
중간 :  *
끝   :  */

1.1.2 비문서화 주석문
이 부분의 주석은 한라인을 넘지 않으면 해당 라인 끝에 입력한다.
시작 : //

1.1.3 문서화 주석문에서 사용하는 Tag
    1. @see
    문서의 다른부분과 Link 생성
    ex) @see #getName

    1. @param
    method에서 사용하는 parameter 설명
    ex) @param max 입력받을 문자의 최대 길이

    3. @return
    method의 return value 설명
    ex) @return 실제 입력받은 문자의 길이

    4. @exception
    method에서 발생하는 exception 설명
    ex) @exception IOException	입력 스트림 오류

    5. @author
    code의 작성자 설명
    ex) @author Javapattern.info 홍길동

    6.	@version
    작성한 code의 version 부여
    ex) @version 1.0.0 2003.06.25

    7.	@since
    method가 추가된 시점의 version을 표시
    ex) @since	1.1.5	2003.08.30

1. 2 주석문 사용예제

/*
 * @(#)Attr.java	1.1 03/03/26  
 * 
 * Copyright (c) 2003 Javapattern.info. All Rights Reserved.
 * 
 * 수정내역 : 
 *			list 메쏘드 추가 	  	- 2003.04.03, 홍길동
 *			toString 메쏘드 수정	- 2003.05.10, 임꺽정
 */

package com.javapattern.ejb.masterGroup;

/**
 * Attr 오브젝트는 애트리뷰트의 값을 name/value 쌍으로서
 * 설정한다. 이 때 name은 String 이고, the value는 임의의
 * 오브젝트이다.
 * @author		홍길동
 * @version		1.1
 */
public class Attr {
    Object o;

    /**
     * 애트리뷰트의 값을 set한다.
     * @param newValue 애트리뷰트의 새로운 값
     * @return 애트리뷰트의 원래 값
     * @see #getValue()
     */
    public Object setValue(Object newValue) {
        Object o = this.o;
        this.o = newValue;
        return o;
    }

    /**
     * 애트리뷰트의 값을 get한다.
     * @return	 애트리뷰트의 값
     * @see #setValue()
     */
    public Object getValue() {
        return o;
    }

    /**
     * 애트리뷰트의 값을 String으로 변환하여 반환한다.
     * @return String으로 변환된 값.
     */
    public String toString() {
        return "Attr value = " + o.toString();
    }
}


 

1.3  Coding 지침

1.3.1 환경 지침
  • JDK는 1.4.1_02를 기준한다.
  • HTML은 Indent없이 입력하고 자세한 지침은 개발자 사이트를 참조한다.
  • 소스 입력 시 Indent사이즈는 4로 맞춘다.
  • 서버에서 쉘은 콘쉘을 사용한다.
1.3.2 EJB 코딩 지침
  • 세션빈은 stateless 빈으로 만든다. - Exception 처리는 자체적으로 처리하지 않고 호출한 곳으로 Throw한다.
  • Stateless빈은 다수의 사용자가 공유하므로 기능하면 멤버변수는 사용하지 않는다.
  • 엔티티빈은 container managed빈으로 만든다.
  • 엔티티빈안의 멤버변수는 DB table field와 같은 이름으로 한다.
  • 기본적으로 read query는 세션빈에서 처리하고, create, update, delete는 엔티티빈에서 처리하는데 처리를 해야할 레코드가 10개 이상일때는 performance향상을 위해 세션빈에서 처리한다.
  • Transaction Attribute는 TX_REQUIRED 로 한다.
  • 한 세션빈에서 여러 개의 엔티티빈을 사용하여 업데이트를 할 경우 트랜잭션을 유지시켜 주려면 반드시 각각의 엔티티빈에서 발생하는 Exception은 Throw를 해야한다. EJB에서 처리할 경우에는 Library의 BaseException을 사용하면 된다. (내부적으로 jts Driver를 사용함)
  • 한 세션빈에서 jdbc 를 이용하여 여러 개의 테이블에 업데이트를 할 경우나 한 세션빈에서 여러 개의 다른 세션빈을 호출하여 여러 개의 테이블에 업데이트를 할 경우 - weblogic pool Driver를 사용할 경우에는 최초의 세션빈에서 반드시 setAutoCommit을 false로 하고 마지막 부분에서 commit을 해야 함 - jts Driver를 사용할 경우에는 발생하는 Exception을 Throw하면 된다.
1.3.3 일반 코딩 지침
  • 스트링 객체를 병합하는 행위가 많은경우 + 연산자 보다는 StringBuffer를 사용하는것이 쓸데없는 객체를 만드는 것을 방지할 수 있다. 자바에서 객체를 새로 생성하는 것은 객체 생성 자체가 비싼 작업이라는 점, 그리고 추후 가비지 컬렉터가 더 많은 일을 해야 한다는 점에서 성능에 별로 좋지 않은 영향을 미친다. 단순한 문자의 추가가 비효율적인 이유는 String 객체는 불변(immutable)이기 때문이다. 그러므로 "a"라는 문자열을 수정해서 "ab"라는 문자열로 바꿀 수는 없고 "ab"라는 새로운 객체를 생성해서 "a"를 치환해야만 한다. 이와는 달리 StringBuffer 객체는 문자열을 변경할 수 있다. 문자열을 계속적으로 추가해야만 한다면 StringBuffer를 사용하는 것이 훨씬 효율적이다.
  • StringBuffer를 사용할 경우 초기 용량을 지정한다. 기본 크기가 16바이트인데 이보다 커질 경우 불 필요한 객체가 생성되기 때문에 가능하면 초기용량을 여유있게 잡아준다.
  • 스트링을 비교할 때 대소분자 구분하여 비교하는 행위는 가급적 피한다.
  • String 클래스에서 getBytes() 메소드는 계산량이 가장 많은 메소드이다. 코드에서 단 한번만이라도 getBytes()를 호출해보면 그것이 성능에 많은 영향을 미친다는 것을 알 수 있다. 이 메소드는 char 배열을 byte 배열로 바꿔주는 메소드인데 각각의 유니코드 캐릭터는 하나나 둘 또는 심지어 3개의 바이트로 변환이 되며 이를 위한 판단 작업도 뒤따라야 하므로 비싼 작업일 수 밖에 없다. 그러나 ASCII 문자의 경우는 문제가 간단해진다. 각각의 ASCII 문자는 2byte 유니코드에서 한 byte를 잘라버리고 남은 1byte만을 변환하면 된다. 그래서 ASCII같은 경우에는 charAt()을 사용하는것이 더 나은 방법이다.
  • StringTokenizer 클래스는 자바에서 있어서 프로그래머가 문자열을 파싱할때 간편하게 사용할 수 있는 강력하면서도 유연한 클래스이다. 그러나 강력하고 유연하다는 말은 고성능을 뜻하지는 않는다. 고성능의 코드는 주로 특수화된 코드이므로 단순화된 가정에 초점을 맞춰 작성된다. 일반적인 목적의 코드를 작성하기 위해서는 많은 제반 사항들을 고려해야 하므로 가정을 너무 많이 단순화시킬 수가 없다. JDK는 많은 자바 응용프로그램을 만족시켜야 하므로 일반적인 형태로 작성이 된다. 그래서 일반화된 StringTokenizer를 사용하기 보다는 가능하다면 indexOf()와 substring()을 사용하는 것이 성능을 향상 시킬 수 있는 방법이다.
  • 한 문자를 체크하기 위해서 startsWith()를 사용하지 않는다. 이 경우에는 charAt()이 유용하다.
  • 디버깅용으로 System.out.println()을 사용한 경우는 운영 중에는 remark하는것이 최상이다. 특정 공통클래스에 trace()를 만들고 모든 클래스가 이 공통클래스의 trace()를 사용하는 경우, 대부분 운영자가 이 공통클래스의 trace모드를 off하기만 하는데 실제 Disk I/O를 안 한다 하더라도 이 메소드를 부르는 행위 자체만으로도 쓸데 없는 객체가 만들어지기 때문에 시스템 전체에 영향을 미친다.
  • 벡터를 자료 구조로 사용할 경우 벡터의 중간부분에 추가나 삭제가 빈번히 일어난다면 다른 자료구조를 고려한다. (Linked List, ArrayList etc)
  • 벡터를 사용할 경우 사용할 크기를 어느 정도 예측할 수 있다면 초기 용량을 지정하는것이 쓸데 없는 객체를 만들지 않는 방법이다. 벡터의 엘리먼트는 내부적으로 배열에 저장되어 있다. 기본적으로 객체가 생성되면 배열의 크기는 10이 된다. 만약에 엘리먼트가 늘어나서 엘리먼트의 갯수가 10을 넘어가면 디폴트로 2배의 크기가 되는 배열을 새로 생성하고 이전의 값들을 새로운 배열에 복사한 후 새로운 배열을 사용한다. 이전의 배열은 가비지 컬렉터의 대상이 되면서 버려진다. 이렇듯, 벡터 크기를 확장 시키는 것은 매우 비싼 작업이다.
  • 벡터의 엘리먼트를 얻기위해 반복하는 경우 Enumeration을 사용 하는것 보다는 elementAt( index )을 사용하는 것이 더 빠르다
  • Java2 에서는 Vector에서 동기화가 빠진 ArrayList라는 클래스를 제공한다. 그래서 만약에 단일 쓰레드 환경이라면 Vector 대신 ArrayList를 사용하는 것이 더 좋은 방안이다.
  • 벡터 클래스가 가지고 있는 또다른 문제점은 다음의 몇가지 메소드를 수행하기 위해서 엘리먼트를 처음부터 끝까지 다 훑어야 한다는 점이다. - contains() - indexOf() - lastIndexOf() - removeElement() - remove() - removeAllElements() - clear() 이러한 것들은 다 비싼 작업이며, 그 비용은 Vector의 size에 비례할 것이다.
  • 해쉬테이블 및 Hash용 객체에서 버킷의 링크드 리스트의 길이는 가능한 짧을수록 좋다. 그러기 위해서는 객체가 삽입될때 동일한 버킷으로 삽입되는 일은 가능하면 없어야 한다. 이는 곧 키의 hashCode() 값이 가능하면 넓게 분포되는 것이 좋다는 말이다 해쉬테이블에서 링크드 리스트의 길이를 결정하는 또하나의 요인은 초기 용량(capacity)과 부하율(load factor)이다. Hashtable의 초기 용량은 곧 버킷의 수이다. 또한 부하율은 현재의 버킷이 얼마만큼 찼을때 버킷의 수를 두배로 늘릴것인가(rehashing)하는 것이다. 이 작업은 비싼 작업이다. 그래서 가능하면 초기 용량을 1.33배로 잡아 주는 것이 rehashing하는 것을 막고 성능을 향상 시킬 수 있는 방법이다.
  • 지속적으로 변하긴 하되 상대적으로 긴 수명을 가지는 값들에 대해서는 캐싱 전략을 세우는 것이 적절하다.
  • System.currentTimeMillis()는 매우 비싸다. 자바는 system clock에 의존하기 때문에 이를 위해서는 반드시 native call이 필요하다. java에서 Java Native Interface(JNI)를 거쳐가는 것은 비용이 들기에 System.currentTimeMillis()에 드는 비용을 가볍게 보아서는 안된다.
  • Date 클래스는 랭귀지에 상관없이 처리하기에 매우 비싼 자원이다. 현재 시간을 물어본다면 1970년 1월 1일 이후 현재 시간까지를 초로 바꾼 다음 매우 복잡한 처리 과정을 거쳐서 'Fri Jul 02 16:38:41 PDT 1998'과 같이 변환해주어야 한다. 게다가 자바에서는 locale 까지도 반영을 하니 현재 시간 하나를 얻기 위해 얼마나 많은 비용을 지불해야 하는지 짐작할 수 있다.
  • 루프내에서 변치 않는 값을 미리 계산해 놓는 것도 고전적인 최적화 방법의 하나이다. 이는 루프가 실행되는 동안 값이 변하지 않으므로 static value 범주에 들어간다
  • 버퍼링은 바이트당 오버헤드를 최소화 할 수 있는 기법이다. 데이터를 보내기 위해서 자바에서는 OS 자체의 함수를 콜해야 하는데, OS 함수 자체는 한번 콜하는데 드는 비용이 한 바이트를 보내나 여러 바이트를 보내나 비슷하다(그 비용 또한 만만치도 않다). 그러므로 한번에 한 바이트씩만 보낸다면 여러 바이트를 묶어서 한번에 보내는 것보다 엄청나게 비싼 댓가를 치러야 되는 것은 자명한 사실이다. 자바에서 I/O stream을 이용해서 버퍼링을 하는 것은 아주 쉽다. 단지 원래의 output stream을 buffered stream으로 감싸기만 하면 된다.
  • 버퍼에 담겨 있는 데이터를 내보내는 flushing은 버퍼가 다 차면 자동으로 내보내는 식으로만은 사용할 수 없다. 예를 들어 일단 클라이언트 쪽에서 요청 명령을 보낸다음 서버쪽으로부터 어떤 데이터를 받는다고 했을 때 요청이 버퍼링이 되어있다면 서버쪽에 전달이 되질 않을테니 그러한 경우는 버퍼가 다 차지 않아도 즉각 데이터를 내보내야 한다. 반면에 그 후로 이어지는 일련의 데이터가 있다면 버퍼가 찰 때까지 기다렸다 한꺼번에 보내주는게 효율적이다. 이렇듯 플러슁은 그 시점이 나름대로 중요하므로 수동으로 적절히 조절할 필요가 있다. 그러나 비적절한 시점에 자주 플러슁을 하면 성능은 떨어진다.
  • Output stream은 대략 유니코드 문자열을 다루는 writer와 바이트 배열을 다루는 것으로 나눌 수 있다. 유니코드 문자열을 writer를 이용하여 내보낼 때 그 끝단은 아마 socket이나 file쯤이 될 것이다. 그런데 여기서의 문제점은 soket이나 file은 유니코드가 아니라 단지 바이트로만 처리 할 수 있다는데 있다. 그러므로 어딘가에서는 유니코드를 바이트로 변환을 해주어야 하는데 이는 매우 비싼 작업이다.
 
1
References
 
Copyright ⓒ 2003 www.javapattern.info & www.jlook.com, an jLOOK co.,LTD