Whiteship's Note

'2008/10'에 해당되는 글 65건

  1. 2008.10.31 7분 완성. CRUD 개발 쑈!!!(with OSAF) (4)
  2. 2008.10.31 취직이 힘든가 보군요. (4)
  3. 2008.10.31 프로토타입 패턴(Prototype Pattern) (2)
  4. 2008.10.31 EJ2E Item 11. 적절하게 clone을 재정의하라
  5. 2008.10.31 EJ2E Item 10. toString은 항상 재정의하라.
  6. 2008.10.31 OSAF에 참여하고 싶은 개발자 (2)
  7. 2008.10.30 Eclipse 3.4(Ganymede)에서 Subversive 설치가 순조롭지 않을 때 (2)
  8. 2008.10.30 꺄오~~ 살꺼야. 키보드. 카시오 PX-320 (8)
  9. 2008.10.29 Spring Webinar 우와.. (2)
  10. 2008.10.29 맥OSX IRC 클라이언트 Colloquy
  11. 2008.10.29 EJ2E Item 9. equals를 재정의할 땐 hashCode도 재정의하라.
  12. 2008.10.29 EJ2E Item 8. equals를 재정의 할 떄는 일반적인 계약을 따르라. (2)
  13. 2008.10.29 연변 말투 == 보이스피싱 (4)
  14. 2008.10.29 EJ2E Item 7. finalizer 사용 자제하기
  15. 2008.10.28 OSAF 샘플 코드 실행하기(스크린캐스팅) (4)
  16. 2008.10.28 EJ2E Item 6. 사용하지 않는 객체 레퍼런스를 제거하라
  17. 2008.10.28 EJ2E Item 5. 불필요한 객체 생성 방지하기
  18. 2008.10.28 EJ2E Item 4. private 생성자로 객체생성 방지하기
  19. 2008.10.28 OpenSprout IRC 서버로 오세요.
  20. 2008.10.28 EJ2E Item 3. 싱글톤 속성은 private 성성자 또는 enum 타입으로 (2)
  21. 2008.10.27 EJ2E Item 2. 생성자에 매개변수가 너무 많을 때는 빌더를 고려하자.
  22. 2008.10.27 EJ2E Item 1. 생성자 대신 static 팩토리 메소드 사용을 고려하라.
  23. 2008.10.26 Effective Java Reloaded
  24. 2008.10.25 OSAF 공개에 대한 이 생각 저 생각 (10)
  25. 2008.10.24 개그경제
  26. 2008.10.24 파트 3: Refactoring Toward Deeper Insight
  27. 2008.10.24 OSAF의 특징 (2)
  28. 2008.10.24 OSAF 빌드하기 (2)
  29. 2008.10.24 OSAF 다운받기 (2)
  30. 2008.10.23 OSAF(OpenSprout Application Framework) 1.0 M1 공개 (6)

7분 완성. CRUD 개발 쑈!!!(with OSAF)

OSAF : 2008.10.31 23:20




검색하다가 NG가 났는데, 영문 검색은 잘 됩니다. 한글 검색시 인코딩 때문에 문제가 좀 있네요. 전에도 발생했던 문제인데, 톰캣 설정(사부님왈. bodyfor어쩌구..)을 조금 수정하면 간단하게 고칠 수 있을 것 같습니다.

실제 동영상 런타임이 7분 49초인데, 설명 없이 코딩만 샥샥 하면 분명 3분 미만으로 CRUD 개발을 완성할 수 있습니다. 그렇게 만들어 놓고 세부적인 검색 조건과 파라메터 들을 추가하면서 개발 해 나간다면... 캬오... 멋지지 않아요??!!!

2008/10/24 - [Screen Casting] - OSAF 빌드하기
2008/10/28 - [OSAF] - OSAF 샘플 코드 실행하기(스크린캐스팅)

이것으로 OSAF 스크린캐스팅 시리즈 세 개가 완성됐습니다. 캬~
다음 스크린캐스팅은 OSAF 아키타입으로 웹 개발 시작하기. 입니다. 많이 기대해주세요.

ps: 요즘 다운로드 수가 바닦을 치던데.. 받으실 분들은 다 받으신 건가요. :)

신고
top


취직이 힘든가 보군요.

모하니?/Thinking : 2008.10.31 20:07




흠.. 정말 우울한 영상이네요. 힘내시길... 힘내서 열심히 자바, 스프링, 하이버 공부하세요.
신고
top

TAG 파이팅

프로토타입 패턴(Prototype Pattern)

Design Pattern : 2008.10.31 16:57


참조: Java 언어로 배우는 디자인 패턴 입문

"복사해서 인스턴스 만들기"
"클래스에서 인스턴스를 만들지 않고 인스턴스에서 인스턴스 만들기"

객체를 클래스를 사용하여 new로 생성하지 않고 복사해서 만들고 싶은 경우
- 취급하는 객체가 다양해서 각각을 별도의 클래스로 두기엔 무리가 있을 때..
- 클래스에서 객체 생성이 어려운 경우(ex. 런타임에 마우스 조작으로 만들어 내는 객체)
- 프레임워크와 생성할 인스턴스를 분리하고 싶을 때. 모형이 되는 객체를 등록해 놓고 그 객체를 복사해서 인스턴스 생성.

예제 코드 from Wikipedia
/** Prototype Class **/
public class Cookie implements Cloneable {

public Object clone() {
try {
Cookie copy = (Cookie)super.clone();

//In an actual implementation of this pattern you might now change references to
//the expensive to produce parts from the copies that are held inside the prototype.

return copy;

}
catch(CloneNotSupportedException e) {
e.printStackTrace();
return null;
}
}
}

/** Concrete Prototypes to clone **/
public class CoconutCookie extends Cookie { }

/** Client Class**/
public class CookieMachine {

private Cookie cookie;//could have been a private Cloneable cookie;

public CookieMachine(Cookie cookie) {
this.cookie = cookie;
}
public Cookie makeCookie() {
return (Cookie)cookie.clone();
}
public static void main(String args[]) {
Cookie tempCookie = null;
Cookie prot = new CoconutCookie();
CookieMachine cm = new CookieMachine(prot);
for (int i=0; i<100; i++)
tempCookie = cm.makeCookie();
}
}

Prototype
- 원형 인터페이스로 객체 복사에 사용할 메소드를 정의한다.
- Cloneable 인터페이스 상속.

ConcretePrototype
- Prototype 인터페이스 구현하여 실제 복사 로직 구현.

Client
- Prototype 인터페이스를 사용하여 새로운 객체를 만든다.

주의할 것.
- Cloenable은 마커 인터페이스.
- 실제 clone 메소드는 Object 클래스에 들어있다.
- 필드 대 필드 복사라서 배열의 경우 레퍼런스를 복사해서 위험할 수 있다. 그럴 땐 직접 clone 메소드를 재정의 해야 한다.
- clone을 재정의 할 떄는 super.clone()을 호출해야 한다.
- clone은 복사만 하지 생성자를 호출하지 않는다. 그래서 생성시에 로직이 필요한 땐 그 로직도 clone에 같이 넣어 준다.
- 자세한건 API를 보시라...
신고

'Design Pattern' 카테고리의 다른 글

[OOAD] 객체지향 원칙 1. SRP  (2) 2010.05.07
[Tell, Don't Ask] 물어보지 말고 시켜라  (8) 2010.04.07
Visitor 패턴  (2) 2010.03.12
Holub on Pattern 좋은데요~  (4) 2008.12.07
프로토타입 패턴(Prototype Pattern)  (2) 2008.10.31
데코레이터(Decorator) 패턴  (0) 2008.10.01
프록시(Proxy) 패턴  (0) 2008.09.26
JUnit 공부하자.  (0) 2008.09.01
H.F.OOAD 5장 문제  (0) 2007.11.20
상위 클래스 보다는 인터페이스를...  (4) 2007.08.31
Singletons and lazy loading  (2) 2007.01.27
top


EJ2E Item 11. 적절하게 clone을 재정의하라

Java : 2008.10.31 15:29


참조: Effective Java 2nd Edition Item 11. Override clone judiciously

Cloneable 인터페이스는 mixin 인터페이스(Item 18)로 복제가 가능한 객체임을 나타낼 의도로 만들었다. 하지만, 그런 목적을 제공하는데 실패했다.

이번 항목에서는 어떻게 하면 잘 동작하는 clone 메소드를 구현할지에 대한 것이다.

메소드도 없는 Cloneable 인터페이스는 무엇을 해주는 건가? Object의 clone 구현체 행위를 결정한다. 만약 해당 클래스가 Cloneable을 구현했다면, Obejct의 clone 메소드는 객체의 모든 필드를 복사한 것을 반환한다. Cloneable 인터페이스를 구현하지 않았으면, CloneNotSupportedException을 던진다.

JavaSE6 java.lang.Object 표준에서 정의한 clone 메소드 general contract

x.clone() != x // true
x.clone().getClass() == x.getClass() // true
x.clone().equals(x) // true
생성자는 호출하지 않는다.

문제
- 생성자를 호출하지 않는다는 조항은 너무 강하다.
- x.clone().getClass() == x.getClass() 조항은 너무 약하다.

...중간 어렵다..-_-;;

음.. 결론은.. final이 아닌 클래스의 clone 메소드를 재정의할 땐, super.clone 호출해서 얻어온 객체를 반환해야 한다.

@Override public PhoneNumber clone() {
  try {
    return (PhoneNumber) super.clone();
  } catch(CloneNotSupportedException e) {
    throw new AssertionError();  // Can't happen
  }
}

Object가 아니라 PhoneNumber를 반환하고 있는데, 1.5 부터는 이런 코드도 괜찮다. 1.5에 covariant return type을 도입했기 떄문에 재정의하는 메소드의 반환 타입으로 원래 타입의 하위 타입을 반환할 수도 있다.

mutable 객체를 참조하는 필드(ex. private Object[] elements)를 가지고 있는 객체에서 위와 같은 clone 메소드를 사용하면 문제가 생길 수 있다. super.clone()으로 복사하면, 같은 객체를 참조하게 되고, 그럼 원복과 복사체가 동이한 객체에 대한 레퍼런스를 쥐고 있는거라 위험하다. 따라서 원본 객체와는 별개로 복사해줘야 한다.

@Override public Stack clone() {
  try {
    Stack result = (Stack) super.clone();
    result.elements = elements.clone();
    return result;
  } catch (CloneNotSupportedException e) {
    throw new AssertionError();
  }
}

clone을 재쉬적으로 호출하는 걸로도 안 될 때(ex. private Entry[] buckets)가 있다. 그럴 땐 deep copy.

코드 생략.

아.. 복잡해. 이런게 정말 필요한거야? 만약에 Cloneable 인터페이스를 구현한 클래스를 상속할 땐, 위에 있는걸 전부 신경써서 잘 동작하는 clone 메소드를 구현해야 한다.

그런 경우가 아니라면, 객체 복사 대안책을 사용하던가 아예 이런 기능을 제공하지 않아도 된다. immutable 클래스에서 객체 복사를 제공하는건 말이 안 된다. 복사체를 원본과 구분할 수가 없기 때문에.

첫번째 대안 copy constructor 또는 copy factory를 제공하는 방법이 있다.

복사 생성자(ex, public Yum(Yum yum);)
복사 팩터리(ex. public static Yum newInstance(Yum yum);)

이 방법이 clone보다 더 좋은 이유
- they don’t rely on a risk-prone extralinguistic object creation mechanism
- they don’t demand unenforceable adherence to thinly documented conventions
- they don’t conflict with the proper use of final fields
- they don’t throw unnecessary checked exceptions
- they don’t require casts

기선: clone 안 쓰는데 이거 왜케 어렵나요?
사부님 왈: 프로토타입 패턴에서 쓰는 거다.
신고
top

Java : 2008.10.31 15:29 Trackback. : Comment.

EJ2E Item 10. toString은 항상 재정의하라.

Java : 2008.10.31 13:36


참조:  Effective Java 2nd Edition Item 10. Always override toString

JavaSE6 스펙에서 정의한 toString 제약 사항.
“a concise but informative representation that is easy for a person to read”
toString은 println이나 printf를 호출할 때 자동으로 호출된다.

toString을 구현할 때 결정 해야 하는 중요한 것 하나는 문서에서 반환 값 형식에 대해 서술할지 여부다. value class에서는 이렇게 형식을 기술해 주는게 좋은데, 모호하지 않으며, 가독성이 좋기 때문이다. 자바의 BigInteger, BigDecimal 같은 API가 이런 방법을 취하고 있다.

형식을 기술하던 말던, 어쨋거나 문서에 여러분의 의도를 분명하게 해야한다.

신고
top

Java : 2008.10.31 13:36 Trackback. : Comment.

OSAF에 참여하고 싶은 개발자

OSAF : 2008.10.31 11:39


메일 한 통이 날아왔습니다. 흠.. 한 단어의 영문 이름과 제목도 한 단어. hi.

'스팸인가...스팸이라고 하기엔 너무 단순한데..'

그래서 열어봤습니다.

캬오.. 소스포지에서 소스 코드만 보고 찾아온 것 같네요. 그래서 프로젝트 사이트 알려주고, 어떻게 참여하고 싶은지 물어보는 답멜을 보내줬습니다.

한국에 계신 분들도 참여하실 분 계시면 말씀하세요~
신고
top


Eclipse 3.4(Ganymede)에서 Subversive 설치가 순조롭지 않을 때

Good Tools : 2008.10.30 18:05


http://thecoffeemachine.wordpress.com/2008/08/20/subversive-in-eclipse-ganymede/

어떤 상황이냐면, 플러그인 설치할 때 Ganymede -> Collaborate를 사용해서 subversive를 설치할 때 플러그인 다운로드가 잘 안 되서 죽어버리는 현상입니다.

위 링크 마지막에 나와있는 순서대로 하면 잘 됩니다.

  1. Go to Help->Software Updates.
  2. Click on the “Available Software” tab.
  3. Unfold the Ganymede->Collaboration Tools node, and if your experience is like mine, you will see the “SVN Team Provider (Incubation)” item with this version identifier, “0.7.1.I20080612-1500″. What you really need (since the Subversive/Polarion team posted updates) is the version from 2008-08-01.
  4. Click on “Manage Sites…”.
  5. Uncheck the “Ganymede” checkbox (http://download.eclipse.org/releases/ganymede)
  6. Scroll down to find “http://download.eclipse.org/technology/subversive/0.7/update-site/”, select it and click “OK”.
  7. You should be back on the “Available Software” tab, with only the subversive items present. Unfold the “Subversive SVN Team Provider Plugin (Incubation)” item, and you will see the “SVN Team Provider (Incubation)” item. Note that the version identifier is “0.7.3.I20080814-1500″.
  8. Check the box, and click”install”. The install will be change to an update. Restart Eclipse at the end of the install.
  9. Go to “Help->Software Updates”.
  10. Choose the “Available Software” tab.
  11. Click the “Add Site” button, and add “http://www.polarion.org/projects/subversive/download/eclipse/2.0/update-site/”.
  12. Check the SVNKit Connectors and click “Install”. Restart Eclipse at the end of the install.
  13. Subversive should be working !

신고
top


꺄오~~ 살꺼야. 키보드. 카시오 PX-320



요즘 피아노에 점점 빠져들고 있습니다. 어렸을 때 조금 치고(초2~초6), 그 뒤로 안 치다가 근.. 15년 만에 다시 학원에가서 배우고 있습니다. 어렸을 때야 뭐 피아노에 관심이 있어서 친게 아니라, 부모님이 일하셔야 하는데 애를 어디 맡겨둘 곳도 마땅찮으니까 동네 피아노 학원에 넣어둔건데.. 나름 재밌게 쳤었습니다. 기분 전환도 할 겸 새로운 스킬도 만들 겸 다시 시작했습니다.

처음엔 악보 보기도 힘들었는데, 이젠 대충 높은음자리표(보통 오른손)는 음표를 보면 대충 알겠고, 낮은 음자리표(보통 왼손)는 아직 좀 익숙치 않습니다. 그래서 인지 마디 마디를 넘어 갈 때마다 자꾸 텀이 생겨서 끊기더군요. 악보 보면서 스무스 하게 이어나가면서 칠 수 있어야 할 텐데 말이죠. 흠..어렸을 땐 아마도 외워서 쳤던것 같습니다. 선생님이 몇 마디 쳐주면 그것만 하루 종일 연습하니까 자연스럽게 외워서 쳤었던 거 같네요. 뭐 계속 악보 보면서 치는걸 연습하다보면 늘겠죠. ㅋ

그래서 연습이 중요한데, 피아노는 문제가 좀 많습니다. 일단 공간을 고정적으로 차지 한다는게... 집도 좁고 방도 좀은 저에게는 무리죠. 그리고 가장 큰 문제는 소리. 저녁이나 밤에 연습할 수 밖에 없는데 달동네 비슷한 골목길이라 아마.. 난리가 날겁니다. 그래서 사부님이 추천해준 키보드로 결정.

카시오 PX-320

헤드셋끼고 맘대로 쳐도 되도되고, 휴대용이라 공간도 피아노에 비해 덜 차지하니깐. Good입니다. 평가를 보니 소리나 건반 느낌도 좋다는 군요. 음하하하 열심히 해서 잼난거 많이 익혀야지~


신고

'모하니? > 그냥 놀아' 카테고리의 다른 글

LA에서 보낸 하루(?)  (6) 2008.12.01
지금은 공항이에요  (8) 2008.11.30
LA, 마이애미, 아틀란타 날씨  (0) 2008.11.28
회사 이사 중  (2) 2008.11.21
개발자들의 수다 후기  (0) 2008.11.09
꺄오~~ 살꺼야. 키보드. 카시오 PX-320  (8) 2008.10.30
보고 싶은 피아노 공연  (0) 2008.10.22
방송탔네~  (0) 2008.10.01
KSUG 도배 성공  (2) 2008.10.01
HP CP1215 맥에서 사용하기  (0) 2008.09.25
KSUG 9번째 스프링 세미나  (2) 2008.09.24
top


Spring Webinar 우와..

Good Tools : 2008.10.29 23:14


실시간 세미나.... ㄷㄷㄷ..
그것도 무료로..
그것도 맥북에도 잘 돌아가는...

사용자 삽입 이미지
사용자 삽입 이미지
와.. 장난 아닙니다. 단순하게 PPT 보여주는게 아니라, 스크린캐스팅을 실시간으로 보여주고 있는거네요.

사용자 삽입 이미지
이제 강의에 집중하렵니다. +.+
신고
top


맥OSX IRC 클라이언트 Colloquy

Good Tools : 2008.10.29 22:08


공짜에요. 좋네요. 캬캬
http://colloquy.info/

사용자 삽입 이미지
사용자 삽입 이미지

캬오... 갠춘하네요.
신고
top


EJ2E Item 9. equals를 재정의할 땐 hashCode도 재정의하라.

Java : 2008.10.29 16:51


참조: Effective Java 2nd Edition Item 9. Always override hashCode when you override equals

equals를 재정의한 클래스는 반드시 hashCode를 재정의 해야 한다. 그렇지 않으면 Object.hashCode 일반적인 계약을 위반하게 된다. 이를 위반하면 hash 기반의 컬렉션(HashMap, HashSet, Hashtable)에서 제대로 동작하지 않을 것이다.

JavaSE6 Object 표준
  • hashCode를 여러번 호출 할 때마다 같은 integer를 반환해야 한다.
  • 두 객체가 equals(Object) 메소드로 동일할 때, hashCode도 같은 integer를 반환해야 한다.
  • 필수는 아니지만, equals(Object)로 가지 않은 두 객체는 hashCode를 호출했을 때 반드시 반드시 다른 integer를 반환해야 한다.
이 중에서 핵심은 두 번째 것.

HashMap에서 key로 사용하는 객체의 hashCode 값이 다르면 equals로 같은 객체여도 같은 key로 인식하지 않는다.

좋은 hashCode 만드는 방법
  • result 라는 int 변수에 0이 아닌 수를 넣는다.
  • 각각의 필드에 다음과 같은 계산식을 적용한다.
    • 필드가 boolean이면, (f ? 1 : 0)
    • 필드가 byte, char, short, int면, (int) f
    • 필드가 long이면, (int)(f ^ (f >>> 32))
    • 필드가 float면, Float.floatToIntBits(f)
    • double이면, Double.doubleToLongBits(f)를 한 다음에 long 타입 다루듯이 한 번 더 계산
    • 레퍼런스 타입이면 hashCode 호출하여 그 결과값 반환. null이면 0 반환
  • result = 31 * result + 위에서 계산한 값
  • result를 반환한다.
  • 작성후 equals로 같은 객체가 같은 hashCode를 반환하는지 단위 테스트로 검증.
equals에서 사용하지 않는 필드는 hashCode에서도 사용하면 안 된다.

example

@Override public int hashCode() {
  int result = 17;
  result = 31 * result + areaCode;
  result = 31 * result + prefix;
  result = 31 * result + lineNumber;
  return result;
}



신고
top

Java : 2008.10.29 16:51 Trackback. : Comment.

EJ2E Item 8. equals를 재정의 할 떄는 일반적인 계약을 따르라.

Java : 2008.10.29 12:18


참조: Effective Java 2nd Edition Item 8. Obey the general contract when overriding equals

equals 메소드 재정의은 간단해 보이지만 잘못 될 여지가 많다.

equals 메소드 재정의가 필요 없는 경우
  • 클래스 특성상 각각의 객체가 유일할 때. ex) Thread
  • "논리적인 일치" 확인 기능을 제공하는지 관심 없을 때. ex) Random
  • 이미 상위 클래스에서 재정의한 equals를 재공하며, 그 로직이 현재 클래스서도 적당할 때. ex) AbstractSet, AbstractList, AbstractMap
  • 클래스가 private 또는 package-private인 경우 equals가 절대로 호출되지 않을거라는 확신이 있을 때.
equals 메소드 재정의가 필요한 경우
  • logical equality 개념이 있는 클래스
  • 보통 value class(예외, 싱글톤, Enum 타입 - Object의 equals가 곧 logical equality)
  • ex) Integer, Date
equals를 재정의할 때 따라야 하는 일반적인 계약(JavaSE6 Object 스펙)
  • Reflexive: null이 아닌 레퍼런스 값 x에 대해, x.equals(x)는 반드시 true를 반환해야 한다.
  • Symmetric: null이 아닌 레퍼런스 값 x와 y에 대해, y.equals(x)가 true를 반환 경우에 한 해서만 x.equals(y)도 true를 반환해야 한다.
  • Transitive: null이 아닌 레퍼런스 값 x, y, z에 대해, x.equals(y)가 true고 y.equals(z)가 true면 x.equals(z)도 반드시 true여야 한다.
  • Consistent: null이 나닌 레퍼런스 값 x와 y에 대해, x.equals(y)를 몇 번 호출하든지 계속해서 일관적으로 true를 반환하거나 false를 반환해야 한다.
  • null이 아닌 레퍼런스 값 x에 대해, x.equals(null)은 반드시 false를 반환한다
규칙을 어기면 다른 객체가 어떻게 동작할지 예측하기 힘들다.

고품질 equals 메소드 레서피
  • 같은 객체를 참조하는 레퍼런스가 아닌지 확인. == 사용.
  • 정당한 타입인지 확인할 떄는 instanceof 연산자를 사용,
  • 적당한 타입으로 캐스팅
  • 각각의 필드가 같은지 확인. primitive 타입은 == 사용, 레퍼런스 타입은 equals 사용
  • 메소드 작성을 마친 뒤에, symmetric, transitive, comsistent 한지 단위 테스트를 작성한다.
example

@Override public boolean equals(Object o) {
  if (o == this)
    return true;
  if (!(o instanceof PhoneNumber))
    return false;
  PhoneNumber pn = (PhoneNumber)o;
    return pn.lineNumber == lineNumber
      && pn.prefix  == prefix
      && pn.areaCode  == areaCode;
}

신고
top


연변 말투 == 보이스피싱

모하니?/Thinking : 2008.10.29 11:56


방금 전 사무실로 보이스피싱 전화 한 통이 걸려왔습니다. 보이스피싱 인지 아닌지는 대충 몇 마디만 대화를 나누면 확신이 서고 전화를 끊게 만듭니다.

"여보세요 에스엘티입니다."

"..."

"어디세요?"

"식약청인데요."  // 일단 말투가 연변 말투인데다가, 주춤 거리는걸 보고 50% 확신

"네? 식약청이요? 왜요?"

"누가 연락을 주셨는데요." // 그럴 사람이 회사 내에 없음으로. 80% 확신.

"누가 무슨 연락을 주셨는데요?"

"아.. 그럼 핸드폰 번호를.." // 전혀 어이없는 플로우로 개인 정보 요구. 99% 확신

'찰칵' // 이쯤되면 끊어도 이상하지 않습니다.

끊어 버린뒤 현재 5분 정도 경과 됐는데 연락이 안 오는거 보면 100% 보이스피싱.

말투에서 일단 50% 먹고 들어가는 연변 알바야. 제발 다른 일 좀 하면 안 되겠니?
신고
top


EJ2E Item 7. finalizer 사용 자제하기

Java : 2008.10.29 11:06


참조: Effective Java 2nd Edition Item 7. Avoid finalizers

Finalizer는 예측 불가능하고, 위험하며, 별로 필요없다. 자바에서 자원 반납은 try-finally 블럭에서 처리하는게 보통.

finalizer의 단점은 바로 실행한다는 보장이 없다는 것이다. 객체를 참조하는 모든 레퍼런스가 없어지는 시점과 실제 finalizer를 실행하는 사이의 텀이 불규칙적이다. 따라서 호출 시기를 고려한 어떤 작업도 finalizer에서 하면 안 된다. ex) 파일 닫기.

더딘 finalization으로 인해 심각한 문제가 발생할 수도 있다. 객체 자원 반환을 지연 시키는 경우도 인해 OutOfMemoryError가 발생할 수도 있다. (finalizer thread 우선 순위가 낮아서 계속 처리가 밀리는 듯...)

finalizer 실행 자체를 안하고 프로그램이 종료 될 수도 있다. 중요 영속 상태를 갱신하는 일을 절대로 finalizer에서 하지 말아라. 만약 DB에서 공유 자원에 대한 락 해제를 finalizer에서 했다간 전체 시스템이 정지하는 사태가 벌어질 수도 있다.

System.gc는 finalizer 실행할 가능성을 높여주긴 해도 보장하진 못한다. 그리고 finalier 실행을 보장하는 System.runFinalizersOnExit와 Runtime.runFinalizerOnExitr는 치명적인 결함이 있는데다가 deprecated돼다.

finalizer를 사용하면 심각한 성능 문제도 있다. 저자의 로컬 컴터에서 430배 정도의 성능 차이가 발생했다.

finalizer를 대신해서 명시적인 종료 메소드(explicit termination method)를 제공하라. ex) InputStream의 close 같은 메소드. 이 메소드 내부에서는 해당 객체를 더이상 사용할 수 없다는 flag를 설정하고, 다른 메소드들은 해당 flag를 참조하여 경우에 따라 IllegalStateException을 던진다.

보통 명시적인 종료 메소드는 try-fianlly 블럭으로 감싸서 예외가 발생해도 실행하도록 한다.

finalizer는 언제 사용하면 좋은가?

하나는 "safety net"으로 사용자가 명시적인 종료 메소드 실행을 깜빡한 경우에 대한 대비책이다. 비록 호출될지 안될지도 모르지만 그래도 아예 안하는 것 보단 낫다. 이런 경우 로그 메시지를 뿌려서 해당 자원이 정상적으로 종료되지 않았다는 걸 알려주면 버그를 수정할 여지를 주게된다. ex) FileInputStream, FileOutputStream, Timer, Connection 얘네가 safety net으로 finalizer를 사용하고 있다.

두 번째는 native peers다. native peers는 native 객체들은 일반 객체가 아니라서 GC 대상이 아니다. 만약 이런 native 객체들이 반드시 종료해야 하는 리소스를 가지고 있다면, 위에서 살펴본 명시적인 종료 메소드를 제공하는게 좋겠다.

"finalizer zhaining"은 자동으로 이뤄지지 않는다. 어떤 클래스가 finalizer를 가지고 있고 그 하위 클래스가 그걸 재정의 했다면 그 상위의 finalizer를 반드시 명시적으로 호출해야 한다.

// Manual finalizer chaining
@Override protected void finalize() throws Throwable {
  try {
    ... // Finalize subclass state
  } finally {
    super.finalize();
  }
}

이렇게 try-finally로 감싸야 현재 finalizer에서 예외가 발생해도 상위 클래스의 finalizer를 실행할 수 있다. 상위 클래스의 finalizer 호출을 깜빡할 수도 있는 것에 대비해서 finalizer guardian이라는 걸 사용할 수도 있는데;;;;

finalizer guardian 이건 생략; -_-;;
신고
top

Java : 2008.10.29 11:06 Trackback. : Comment.

OSAF 샘플 코드 실행하기(스크린캐스팅)

OSAF : 2008.10.28 23:44



신고
top


EJ2E Item 6. 사용하지 않는 객체 레퍼런스를 제거하라

Java : 2008.10.28 16:18


참조: Effective Java 2nd Edition Item 6. Eliminate obsolute object references

C나 C++처럼 메모리 관리를 직접 하다가 GC를 사용하는 자바로 넘어오면 편해진거 같지만, 조심하지 않으면 메모리 부족 현상이 나타날 수 있다.

public Object pop() {
  if (size == 0)
    throw new EmptyStackException();
  return elements[--size];
}

배열에서 필요없는 객체 레퍼런스를 가지고 있기 떄문에, 여러 객체를 담고 빼고 하다보면 계속 쌓여서 결국엔 메모리 부족 현상이 발생한다.

public Object pop() {
  if (size == 0)
    throw new EmptyStackException();
  Object result = elements[--size];
  elements[size] = null; // Eliminate obsolete reference
  return result;
}

명시적으로 null 로 설정하는 방법은 예외적인 경우에 한해서 사용하는게 좋다. 객체 레퍼런스를 제거하는 가장 좋은 방법은 scope를 이용하는 것이다. 자연스럽게 제거 되도록..

또 다른 메모리 부족 주요 원인은 캐시.

객체 레퍼런스를 캐시에 넣어두고 삭제하는 걸 깜빡하는 경우가 있다. 대안책으로 WeakHashMap을 사용하는 것이다.
Remember that WeakHashMap is useful only if the desired lifetime of cache
entries is determined by external references to the key, not the value.
흠.. Weak Reference를 사용하는 HashMap인것 같은데, 잘 몰겠다. API를 봐야겠네.

메모리 부족 세 번째 주요 원인은 리스너나 콜백.

콜백을 등록하고 나서 나중에 해지할 때 제대로 하지 않아서 문제 발생. 콜백을 GC 하는 최선의 방법은 WeakHashMap을 사용해서 콜렉션에 오직 weak reference만 담는 것이다.

메모리 부족 문제는 힙 프로파일러(heap profiler)를 사용해서 디버깅 하지 않는 이상 찾아내기 힘들다.

신고
top

Java : 2008.10.28 16:18 Trackback. : Comment.

EJ2E Item 5. 불필요한 객체 생성 방지하기

Java : 2008.10.28 12:09


참조: Effective Java 2nd Edition Item 5. Avoid creating unnecessary objects

객체를 매번 새로 생성하는 것보다 재사용하는게 당연히 더 빠르고 적절한 방법이다.

String s = new String("stringette"); 이렇게 쓰지 말것.

위 방법은 매번 새로운 String 객체 생성한다.

String s= "stringette"; 이렇게 쓸 것.

이 방법은 매번 하나의 String 객체를 사용한다. 또한 이 경우 VM에 같은 문자열을 참조하는 코드가 있을 때 같은 객체를 재사용한다.[JLS, 3.10.5]

static factory method[item 1]를 사용해서 조정할 수 있다. 생성자를 사용하면 무조건 새로운 객체를 생성하지만, 이 녀석은 꼭 그래야 하진 않으니까.

mutable 객체 재활용하는 방법
- static initialization.

private static final Date BOOM_START;
private static final Date BOOM_END;

static {
  Calendar gmtCal =
    Calendar.getInstance(TimeZone.getTimeZone("GMT"));
  gmtCal.set(1946, Calendar.JANUARY, 1, 0, 0, 0);
  BOOM_START = gmtCal.getTime();
  gmtCal.set(1965, Calendar.JANUARY, 1, 0, 0, 0);
  BOOM_END = gmtCal.getTime();
}

1.5에서 불필요한 객체를 생성하게 된 경우.
- autoboxing/unboxing.
- primive 타입을 사용 선호하고, 의도하지 않은 autoboxing을 하지는 않는지 조심해야 한다.

// Hideously slow program! Can you spot the object creation?
public static void main(String[] args) {
  Long sum = 0L;
  for (long i = 0; i < Integer.MAX_VALUE; i++) {
    sum += i;
  }
  System.out.println(sum);
}

(캬오.. 위 코드에 그렇게 심각한 문제가 있었다니.. ㄷㄷㄷ...)

이번 Item을 읽으면서 주의할 것은 객체 생성이 굉장히 비싼 일이고 기피해야 할 것은 아니라는 것이다. 코드를 보다 분명하게 하고, 간단하게 하기 위해 객체 생성을 명시적으로 하는 것은 괜찮다.

반대로 비싼 객체를 자신만의 객체 풀(object pool)을 만들어서 관리하려는 건 비추한다. 객체 풀 관리하다가, 메모리 잡아먹고, 성능 문제가 생길 수도 있다.

신고
top

Java : 2008.10.28 12:09 Trackback. : Comment.

EJ2E Item 4. private 생성자로 객체생성 방지하기

Java : 2008.10.28 11:00


참조: Effective Java 2nd Edition Item 4. Enforce noninstantiability with private constructor

때로는 static 메소드나 static 필드만 가지고 있는 클래스를 작성하고 싶을 떄가 있을 것이다. (ㅇㅇ. XXUtils 같은 클래스들이 그런 경우겠다.)

이때 abstract 클래스로 만드는 건 효과가 없다.
- 상속 받아서 객체 생성할 수 도 있으니깐..
- 또 abstract를 보면 왠지 상속받아서 사용하도록 만들어둔 클래스로 생각하게 한다.

public class UtilityClass {
  // 객체 생성 방지
  private UtilityClass(){
    throw new AssertionError();
  }
}

명시적으로 기본 생성자라를 private으로 설정한다.
- 생성자 안에서 던지는 AssertionError는 보험.
- 반직관적이기 때문에 생성자에는 주석을 달아주는게 좋다.
- 상속 받아도 소용없다. 명시적이든 암묵적이든 상위 클래스 생성자를 호출할테니까..

신고
top

Java : 2008.10.28 11:00 Trackback. : Comment.

OpenSprout IRC 서버로 오세요.

OSAF : 2008.10.28 09:50


원문: http://www.opensprout.org/wiki/pages/viewpage.action?pageId=2162739

Introduction

OpenSprout에서 발표한 OSAF 프레임워크나 Spring에 대해서 질문이나 의견 나누실 분들 또는 다른 개발자들과 이런 저런 채팅을 원하시는 분들은 언제든 환영합니다. IRC서버 운영이 생전 처음이라 미흡한 점이 있을 것 같아 일단 KSUG분들을 중심으로 시범 운영해보려고 합니다.

How-to

IRC 클라이언트 설치

mirc같은 상용 제품도 있지만, 파이어폭스 플러긴 Chatzilla를 이용할 수도 있습니다. 파이어폭스 기준으로 설명하겠습니다.

  • 도구 -> 부가기능 클릭
  • 전체검색 탭 클릭
  • irc로 검색
  • chatzilla 설치 및 파폭 재시작.

Chatzilla 설정하기

위에서 Chatzilla를 설치했다면, 이제 도구 -> Chatzilla 메뉴가 생겼을 겁니다. Chatzilla를 이용해서 클라이언트 프로그램을 실행하면 조그만 창이 뜹니다.

일단 설정 화면(ChatZilla -> Preference)에 들어가서 인코딩 설정을 해줍니다.

부가적으로 Gloval 탭의 중간쯤에 알람 설정을 할 수도 있습니다. 다른 사용자가 메시지를 입력했는지 알고 싶다면 해당 탭에서 beep 또는 wav 파일 위치를 설정하면 됩니다.

이제 채팅하기

/server www.opensprout.org

이렇게 OpenSprout IRC 서버로 접속합니다. 접속이 되면,

/list

list 명령어로 현재 개설된 채널을 확인할 수 있습니다. OSAF 채널은 항상 열려있습니다. 따라서,

/join OSAF

이렇게 OSAF 채널로 들어오시면 됩니다.


신고
top

OSAF : 2008.10.28 09:50 Trackback. : Comment.

EJ2E Item 3. 싱글톤 속성은 private 성성자 또는 enum 타입으로

Java : 2008.10.28 09:41


싱글톤은 객체를 딱 한번만 생성하는 클래스.

1.5 전에 싱글톤을 구현하는 방법은 두 개였다. 둘 다 private 생성자와 public static 멤버를 노출한다.

첫 번째 방법: public static filed

public class Elvis {
  public static final Elvis INSTANCE = new Elvis();
  private Elvis(){...}
  ...
}

private 생성자는 딱 한 번 static final 필드인 Elvis.INSTANCE를 초기화할 때만 호출한다. 한 가지 주의 할 것이 있는데...
a privileged client can invoke the private constructor reflectively
(Item 53) with the aid of the AccessibleObject.setAccessible method
이 부분 잘 모르겠슴.

두 번째 방법: public static factory method

public class Elvis {
  private static final Elvis INSTANCE = new Elvis();
  private Elvis(){...}
  public static Elvis getInstance() { return INSTANCE; }
  ...
}

위에서 잘 모르는 부분의 문제가 이렇게 하면 발생하지 않아. (OSAF도 이런식으로 싱글톤을 만들었쥐.) 좀 더 유연하게 변경할 수 있다. Generic 타입을 고려할 수 있다.(Item 27) 이것도 모르겠군.

위의 두 가지 방법은 Serializable 하지 못한다. (static 필드는 직렬화 안 되니깐) 따라서 모든 객체 필드를 transient로 선언하거나 readResolve 메소드(Item 77)를 제공해야 한다.

세 번째 방법: Enum singleton

1.5 부터 사용할 수 있는 싱글톤 구현 방법. 캬.. 드디어 새로운 방법 등장이구나.

public enum Elvis {
  INSTANCE;
  ...
}

이 방법은 기능적으로는 public filed 접근 방법과 동일하지만, 간결하고, 여러 객체를 생성할 여지도 없으며, 직렬화도 제공한다는 점에서 차이가 있다.
a single-element enum type is the best way to implement a singleton
저자가 이 정도로 권장할 정도니까.. 사용해 봐야겠다.
신고
top


EJ2E Item 2. 생성자에 매개변수가 너무 많을 때는 빌더를 고려하자.

Java : 2008.10.27 18:20


참조: Effective Java 2nd Edition. Item 2: Consider a builder when faced with many constructor parameters

생성자나 static factory method에 매개 변수가 너무 많고 다양할 때 기존에는 Telescoping constructor 패턴 또는 JavaBeans 패턴을 사용왔다.

telescoping constructor 패턴
- 생성자에서 다른 생성자 호출하면서 비는 매개변수에는 기본값 설정해주는 방식.
- 잘 동작은 하는데, 매개 변수를 많이 사용할 떄는 클라이언트 코드를 작성하기도 힘들고, 읽기도 힘들다.
- 위치가 바껴도 컴파일 에러가 안 남.
 
JavaBeans 패턴
- 기본 생성자만 사용하고, 필요한 속성은 세터 사용.
- 쉽게 객체 생성 가능. 코드 읽기 쉬움.
- 생성 과정이 여러 호출로 구성되어 있어서 불완전한 상태로 사용될 여지가 있다.
- 불변 객체로 만드는 걸 불가능하게 하고, 쓰레드 세이프티를 보장하려면 개발자가 추가로 신경을 써야 한다. -> freezing 이용할 수 있지만 이 방법은 거의 사용 안 해.

Builder 패턴
- 필요한 객체를 직접 만들지 않고, 필수 매개 변수를 생성자나 static factory 메소드에 넘겨서 객체를 만들고, 부가적인 속성들은 그 뒤에 설정한다. 그리고 최종적으로 build()를 호출해서 불변 객체를 생성한다.
- 클라이언트 코드
NutritionFacts cocaCola = new NutritionFacts.Builder(240, 8).
calories(100).sodium(35).carbohydrate(27).build();
- 작성하기도 쉽고, 읽기도 쉽다. Ada와 Python의 named optional parameters를 사용했다.
- Abstract Factory 패턴을 구현할 때, 자바 1.5 이상의 버전에서 빌더를 사용하면, 예전처럼 런타임이 아닌 컴파일 타임에 에러를 발견할 수 있다.
- 단점: 빌더 객체 생성 비용. 다른 패턴에 비해서 좀 복잡하다. 따라서 매개 변수가 넷 이상일 때만 사용을 권장.
신고
top

Java : 2008.10.27 18:20 Trackback. : Comment.

EJ2E Item 1. 생성자 대신 static 팩토리 메소드 사용을 고려하라.

Java : 2008.10.27 17:52


참조: Effective Java 2nd Edition. Item 1: Consider static factory methods instead of constructor

static factory method는 Factory Method 디자인 패턴이랑 같은 것이 아니다. 직접적인 관계는 없다.

장점
- 이름을 가질 수 있다.
- 매번 새로운 객체를 만들 필요가 없어진다.
- 하위 타입을 반환할 수 있다. -> service provider framework
- 타입 매개변수를 가진 클래스 객체를 생성할 때 간결하게 쓸 수 있다. -> type inference

Service Provider Framework
- Servide interface: 공급자가 구현할 인터페이스. ex) Connection
- Provider registration API: 시스템이 구현체를 등록할 때 사용. ex) DriverManager.registerDriver
- Service access API: 사용자가 서비스 객체를 얻어올 때 사용. == fexible static factory. ex) DriverManager.getConnection
- (option) Service provider interface: 공급자가 서비스 구현체의 객체를 생성할 때 구현한다. ex) Driver

단점
- public 또는 protected 생성자 없이 static factory method만 제공하는 클래스는 상속할 수 없다.
- 다른 static factory method랑 확연하게 구분이 안 된다. -> 이름을 잘 짓자.(valueOf, of, getInstance, newInstance, getType, newType)

신고
top

Java : 2008.10.27 17:52 Trackback. : Comment.

Effective Java Reloaded

Java : 2008.10.26 09:49


참조: Parleys.com에서 Effective Java Reloaded

Generic

- PECS, Producer extends, Consumer super.
- 타입제한으로 인해 다형성같은 유연함이 떨어질 땐, PECS를 적용하면 유연하게 만들 수 있다.

Enum

- int 값을 얻고 싶을 때 ordinal()+1 을 반환하는건 유지보수 힘들다.(순서 바뀔 수도 있고, 중간 요소가 빠져있을 수도 있고, 같은 수를 반환할 수가 없다.)
- int 속성을 enum 생성자에 전달하고 그 값을 반환하도록 코딩한다.(오.. 멋지다.)
public enum Ensemble {
  SOLO(1), DUET(2), TRIO(3), ...
 
  private final int numberOfMusicians;

  Ensemble(int size){
    numberOfMusicians = size;
  }
 
  public int numberOfMusicians() {
    return numberOfMusicians;
  }

}

- int 상수 사용 문제. not typesafe, no namespace, brittle, 출력시 값이 명시적이지가 않아, 순회하기도 힘들어, 64비트 넘으면 ㄷㄷㄷ
- EnumSet을 enum이 가지고 있는 메소드에 넘긴다.
public void applyStyles(Set<Style> styles) {...}

text.applyStyles(EnumSEt.of(Style.BOLD, Style.ITALIC));

- ordinal()은 EnumSet, EnumMap 같은 곳에서 내부적으로 사용할 목적이니까, 프로그래밍 할 땐 쓰지 말도록.

- 싱글톤 퀴즈, enum으로 싱글톤 만들기
 Serializable Singleton

public enum Elvis {
  INSTANCE;
  ...
}

- enum 제약 사항
확장 못 한다. 메소드는 인터페이스를 사용해서 확장 가능
Emulated Extensible Enum

Lazy initialization

- 언제 사용하는가
성능, initialization circularity 해결하려고

- static 필드는 Holder Class 사용하기
private static class FiledHolder {
  static final FieldType field = computeFirldValue();
}

static FieldType getField(){
  return FieldHolder.field;
}

- 인스턴스 필드는 더블 체킹

private volatile FieldType field;

FieldType getField(){
  FieldType result = field;
  if(result == null){  // 1st check (no lock)
    synchronized(this){
      result = field;
      if(result == null)  // 2nd check (w/ lock)
        field = result = computeFieldValue();
    }
  }
  return result;
}





신고
top

Java : 2008.10.26 09:49 Trackback. : Comment.

OSAF 공개에 대한 이 생각 저 생각

모하니?/Thinking : 2008.10.25 21:19


프로젝트 시작

사부님의 글 스프링과 하이버네이트를 이용한 RAD프레임워크 - OSAF(OpenSprout App. Framework) 공개에도 나와있지만, 이 프로젝트를 시작하게 된 시점과 여자친구에게 차인 시점이 교묘하게 일치합니다. 그리고 그 즈음에 경제가 막 악화 되면서 프로젝트가 연이어 연기 되거나 파토나는 상황이 이어졌습니다. 현재까지도 좀 그런 상태라 회사에 나와서 할 일이.. 딱히 없었습니다. 일이 없어도 워낙 하고 싶은 공부도 많고 번역할 꺼리도 많았기 때문에 심심하지는 않았는데.. 문제는 도태되는 느낌. 그리고 헤어짐에 대한 아픔. 그 두 가지는 무슨 일을 해도 해결할 수가 없었습니다. 집중할 것이 필요했습니다.

그래서 처음엔 일을 늘려나갔습니다. 번역과 스크린캐스팅을 늘려나갔습니다. 주말에도 일을 해야지 일정에 맞출 수 있을 정도로 말이죠. 그리고 취미를 만들었습니다. 사부님이 추천해준 큐브도 돌리고, 어렸을 때 배웠던 피아노가 생각나서 피아노 학원도 다니기 시작했습니다. 그런데도 기술적으로 도태되는 느낌과 시련의 아픔은 여전히 어떻게 할 수가 없었습니다. 그래서 OSAF를 시작했습니다.

내가 사용하는 이 프레임워크가 얼마나 좋은지 보여주고 싶었습니다. 그리고 그 당시는 그다지 잘 알고 있지도 않아서 더 알고 싶은 마음도 있었습니다. 대체 이 많은 태그는 어떻게 만들었으며 그리드가 어떻게 동작하는건지 말이죠. 저에겐 딱 좋다 싶었습니다. 공부도 되고, 집중도 할 수 있으니깐 말이죠.

프로젝트 진행

토비님이 거의 모든 핵심 코드를 작성했다고 봐도 무방합니다. 저는 그 코드에 살을 조금 붙이거나 공개를 위해서 수정을 했습니다. 주석을 달고, 사이트를 준비하고, 예제를 만들고, OSGi 서비스 기반으로 제공할까 하다가 실패를 해서 그냥 패키지 기반으로 전환, 그리드 태그 만들다가 DisplayTag가 적절치 않음을 발견, 그리드 태그 변환으로 인해 CRUD 형태가 기존과 달라짐, 덩덩덩. 여러 문제가 있었습니다.

하다보니, 예전에는 무심코 지나갔던 코드도 다시 들여다보게 되고, 공부할 것도 간간히 등장하더군요. 하지만, 공부할 것들이 너무 많아서 자칫 공부에 빠지면 공개를 못하겠다는 느낌이 들었습니다. 선택의 기로였죠. 공부냐 공개냐. 공부를 하자니 공개를 못하겠고, 공개를 하자니 공부를 못하겠고. 선택은 아시다시피 공개를 선택했습니다. 공부야 언제든 계속 하면 되는데, 지금 이렇게 시간 있을 때 공개 못하면 나중엔 더 힘들것 같았거든요. 그래서 공부를 좀 미루더라도 공개하기로 결정했습니다.

프로젝트 공개

공개하는 과정도 쉽지가 않았습니다. 일단 웹 사이트라도 있어야 하는데 그러려면 도메인이 있어야 하고, 서버도 있어야 되고, 그 서버에 위키, 이슈 트래커, CI 환경, 덩덩덩이 있어야 됐거든요. 근데 그런 귀찮을 일을 사부님 한테 맡길 순 없자나요. 그래서 제가 다 했습니다. 리눅스에 톰캣 깔고, 아파치랑 연동하고, 연동할 때 모르는거 물어보고, 개발 환경 제품들은 전부 Atlassian 제품들도 설치했습니다. 라이선스는 처음엔 그냥 임시 라이선스를 가지고 설치하고, 나중에 설치도 하고, 도메인 설정도 하고, 준비 중인 코드를 일단 올려서, 오픈 소스 라이선스를 신청했습니다. 근 2주 정도 뒤에 오더군요. 그걸로 라이선스를 바꿔서 이제 1년 간은 라이선스 걱정없이 사용 할 수 있게 됐습니다. 막바지에는 개발 해오던 프로젝트 구조와는 달리 멀티 프로젝트 구조의 메이븐 프로젝트로 변경해서 공개 했습니다.

프로젝트 3일 후

이제 공개 한 지 3일이 지났습니다. 일단은 후련합니다. 그리고 근 세달에 걸쳐 OSAF를 다듬고 수정하고 공개하는 시간을 지나면서 시련의 아픔도 차차 나아졌습니다. 지금도 사실 완치됐다고 느껴지지는 않지만 예전 보단 정말 많이 나아졌습니다. 그리고 두려움이 다가옵니다. 이렇게 세 달 동안 노력해서 공개한 프레임워크가 잘 살아갈 수 있을지 말이죠. 책임감이 느껴집니다. OSAF가 잘 살지 못하고 아무런 관심도 못 받고 아무도 사용하지 않고 묻혀버릴 거라면 내가 지금 괜한 일을 한 것 아닐까. OSAF라는 이름에 누를 끼치는 건 아닐까. 말이죠. 그래서 의무감이 생깁니다. 절대로 먼지가 쌓이지 않게 해야겠다. 계속 다듬어야겠다. 지금은 비록 많이 부족해도 언젠간 반짝 반짝 빛이 나도록 말이죠.

앞으로

OSAF는 최첨단 프레임워크가 될 예정입니다. 포기 했었던 OSGi 서비스 기반을 다시 시도하고, 이클립스 플러그인 개발을 해서 IDE로 코드 생성을 지원하고, 그리드 태그를 개선할 겁니다. 그리고 스프링 3.0이 출시되면 RESTful을 지원할 것이며, 스프링 Security 예제도 제공하고, 메이븐 아키타입으로 OSAF 기반 웹 애플리케이션 개발을 아주 쉽게 사용할 수 있도록 할 것입니다.

OSAF 관련 활동 말고, OpenSprout 활동으로는 스프링, 하이버 RI 프로젝트 및 OSGi 관련 프로젝트도 사부님과 구상 중입니다. 새로운 OpenSprout 멤버도 모집할 것 같습니다. 아직 구체적인 계획은 없지만, 아무래도 사람이 좀 더 있어야 하지 않을까 싶습니다.

끝으로

새싹아.. 무럭 무럭 자라거라. OpenFlower, OpenTree, OpenForest가 되는 날까지. ㄱㄱㅆ!!

신고
top

TAG OSAF, 잡담

개그경제

모하니?/Thinking : 2008.10.24 23:42




헐헐헐.
신고
top


파트 3: Refactoring Toward Deeper Insight

JEDI/DDD : 2008.10.24 13:05


리팩터링 수준

다른 책들은 너무 로우 레벨로 얘기하는데 그 보다는 도메인에 대한 통찰을 통한 또는 모델이 말하고자 하는 바를 분명하게 하는 것이 시스템의 실용성에 더 지대한 영향을 주는 리팩터링 이라는 이야기..
The refactorings that have the greatest impact on the viability of the system are those motivated by new insights into the domain or those that clarify the model's expression through the code.
Deep Model

모델을 좀 더 심도있게 바라보도록.. 피상적인 모습으로만 축출한 모델이 다가 아니라는거...
A deep model provides a lucid expression of the primary concerns of the domain experts and their most relevant knowledge while it sloughs off the superficial aspects of the domain.
Supple Design

변경을 반영할 수 있는 설계가 되어야 한다.

In a process of constant refactoring, the design itself needs to support change.
Deep Model과 Supple Design은 Model-Driven Design을 뒷받침하는 두 개의 축이다.
A MODEL-DRIVEN DESIGN stands on two legs. A deep model makes possible an expressive design. At the same time, a design can actually feed insight into the model discovery process when it has the flexibility to let a developer experiment and the clarity to show a developer what is happening.
The Discovery Process

좋은 모델을 찾아가는 과정은 개인의 창의성에 달려있기도 하지만, 여러 패턴을 따를 수도 있겠다.
You will usually depend on creativity and trial and error to find good ways to model the concepts you discover, but sometimes someone has laid down a pattern you can follow.

가끔은 이론적인 얘기로 머리를 환기시키는 것도 좋네요.
신고

'JEDI > DDD' 카테고리의 다른 글

[DDD] User-Familly 구현  (0) 2009.06.22
[DDD] Whiteship's DDD 아키텍처 수정  (6) 2009.06.16
[DDD] Whiteship's DDD 아키텍처  (10) 2009.06.12
[DDD] DDD 입문에 좋은 글  (4) 2009.06.11
파트 3: Refactoring Toward Deeper Insight  (0) 2008.10.24
Factories  (0) 2007.12.25
Aggregates  (0) 2007.12.18
Modules  (2) 2007.12.14
Services  (2) 2007.12.13
DAO vs Repository  (4) 2007.12.04
DTO(Data Transfer Object)  (2) 2007.11.21
top


OSAF의 특징

OSAF : 2008.10.24 12:32


OSAF는 스프링, 하이버네이트 기반 애플리케이션 프레임워크입니다. 라는 다소 두리 뭉실한 소개로는 대체 어떤 특징이 있는지 애매 모호 하실 것 같아서 OSAF가 가지고 있는 특징을 설명하겠습니다.

1. 제네릭 활용

GenericDao는 많이 듣고, 알고, 사용하고 있으리라 생각합니다. 하지만, OSAF에는 하이버네이트 기반의 GenericDao 뿐만 아니라, GenericService, GenericController 기능을 제공합니다. 따라서 GenericDao를 사용했을 때의 장점을 그대로 살려서 Service와 Controller 계층에서도 빠르고 간편하게 CRUD 개발이 가능하다는 것입니다. 또한, GenericPropertyEditor를 제공하여 스프링의 커스텀 프로퍼티 에디터 작성을 지원하고 있습니다. 훨씬 쉽고 빠르게 커스텀 프로퍼티 에디터를 작성하실 수 있을 것으로 생각합니다.

2. 태그 파일 활용

JSP 기반 뷰 코드를 컴포넌트화 하여 태그 파일로 만들었습니다. 이로 인해 JSP를 모르는 사람도 몇 개의 태그만 익히면 빠르게 뷰를 만들 수 있습니다. 이는 곧 생산성으로 직결될 것입니다. OSAF는 add, update, grid, search 등의 기본 뷰와 레이아웃을 제공합니다. 일반적인 JSP 파일이기 때문에, 얼마든지 워하는 대로 커스터마이징이 가능합니다.

3. 스프링 2.5 기반 프레임워크

스프링 2.5의 가장 큰 변화이자 핵심은 애노테이션 활용 극대화입니다. 애노테이션으로 XML 설정을 최소화 했기 때문에, 더 이상 여러 명의 개발자가 빈 설정 파일 하나를 수정해서 커밋하다가 충돌나고 어쩌구 저쩌구 하는 복잡한 일이 벌어질 여지를 최소화 했습니다. 또한, 스프링 MVC의 경우처럼 클래스 상속 구조를 애노테이션으로 대체하여 POJO 개발이 가능하도록 개선된 부분도 있습니다. 컴포넌트 스캔과 오토 와이어링을 비롯한 많이 기능이 애노테이션을 기반으로 하고 있습니다. OSAF는 스프링 2.5가 제공하는 애노테이션 기능들을 매우 잘 활용하고 있습니다.

4. 하이버네이트 기반 프레임워크


하이버네이트를 사용하여 도메인 중심의 개발이 가능합니다. 하이버네이트 기반 DAO를 제공하며, 하이버네이트에 특화된 기능 flush(), clean() 등의 인터페이스를 사용할 수 있습니다. 또한 하이버네이트를 사용하여 DB 교체가 용이하기 때문에 테스트 DB와 실제 배포 환경 DB가 다르더라도 편하게 개발할 수 있습니다.

5. CRUD 초고속 개발

위의 모든 특징들은 바로 이 것으로 귀결 됩니다. 별다른 코드 생성기나 IDE가 없이도, 직접 C&P를 해가면서 5분 이내에 한 도메인에 대한 CRUD 개발이 가능합니다. 여기서 CRUD 개발에 필요한 파일은 전부 12개 정도로, 자바 클래스 8개. 뷰 4개 정도 입니다. 이 코드는 예제 코드를 복사하여 붙여 넣고 find/replace 기능을 사용하여 이름만 바꾸면 작업이 종료됩니다. 컴포넌트 스캔과 애노테이션 활용을 극대화 했기때문에, 빈 설정을 건드릴 필요도 없으며, 하이버네이트 기반이라 테이블을 만들 필요도 없습니다. 태그 파일을 활용했기에 뷰도 정말 간단하게 편집하여 재사용할 수 있며, 제네릭 서비스와 컨트롤러의 역할은 두 말할 필요가 없습니다.

이상이 OSAF의 가장 큰 특징 다섯 가지입니다. 세부적인 기능에 대해서는 차차 또 공개하겠습니다. 급하신 분들은 소스 코드를 다운로드 하여 직접 확인해 보시기 바랍니다. :)

ps: OSAF 말고 OpenSprout에 대해 궁금하시다면, 여기를 참조하세요.
신고
top


OSAF 빌드하기

OSAF : 2008.10.24 10:49




프로젝트를 받으시면, dist 폴더에 jar 파일이 들어있으니까, 직접 빌드를 하시진 않아도 되지만, 그래도.. 재미삼아 한 번 해보세요.ㅋㅋ

빌드 할 때 주의함 점이 하나 있는데요. 위에서처럼, JDK 버전이 1.6이 아닌 경우에 에러가 날 수 있습니다. 그럴 떄는 pom.xml을 열어서 jdk.version 프로퍼티를 1.5로 수정해주시면 됩니다. 위 동영상에서도 똑같은 현상이 벌어졌으니 참고하시면 되겠습니다.

참고로 OSAF는 JDK 1.5 이상에서만 사용할 수 있습니다. 1.4 이하는... ( --) 몰라요..ㅋㅋㅋ
신고
top


OSAF 다운받기

OSAF : 2008.10.24 08:41


OSAF 소스포지 링크를 클릭하면 다음과 같이 두 개의 파일이 보입니다.


위에 있는 녀석은 OSAF 의존성 라이브러리들을 osaf홈/lib 폴더에 모두 담고 있습니다. 메이븐을 사용하지 않을 때는 거기에 있는 모든 라이브러리를 클래스패스에 추가해서 사용하시면 됩니다.

메이븐을 사용하실 때에는 아래에있는 1메가 남짓의 파일을 받으시면 됩니다.

소스포지를 이용해주시면 다운로드 집계가 되기 때문에 차후에 통계 자료를 참고할 수 있습니다.

한 가지 방법이 더 있는데, 메이븐 리파지토리에 OSAF 메이븐 저장소를 등록하신 다음, 다음의 dependency 설정을 pom.xml에 추가하는 방법이 있습니다.

<dependency>
        <groupId>org.opensprout</groupId>
        <artifactId>osaf-core</artifactId>
        <version>1.0.0-m1</version>
</dependency>

이렇게만 추가하면, 필요한 모든 라이브러리까지 알아서 끌어오기 때문에 매우 편리합니다.

OSAF 저장소를 추가하는 방법도 간단합니다.

<project>
...
    <repositories>
...
        <repository>
            <id>osaf.repository</id>
            <name>OSAF Repository</name>
            <url>
                http://www.opensprout.org:8082/nexus/content/groups/public/
            </url>
        </repository>
...
    </repositories>
..
</project>

신고
top


OSAF(OpenSprout Application Framework) 1.0 M1 공개

OSAF : 2008.10.23 17:17



(쇼팽, 연습곡 25번, 겨울바람)

사용자 삽입 이미지

토비님과 제가 주관하는 OpenSprout에서 OSAF 1.0을 드디어 공개합니다.

OSAF는 스프링, 하이버네이트 기반의 자바 애플리케이션 프레임워크입니다. 그리고 OSGi 플랫폼에 설치하여 사용할 수 있는 번들이기 때문에, 필요한 패키지만 import 할 수 있다면, 얼마든치 번들로 설치가 가능합니다.

주요 기능으로는 자바 5의 Generic 사용을 극대화 했으며, 진정한 스프링 2.5 애노테이션 활용을 볼 수 있습니다. 제공하는 기능에 비해 프레임워크의 크기는 전혀 크지 않습니다. 인터페이스 포함 클래스 갯수는 46개 정도입니다. 태그 파일, 자바스크립트, 이미지 파일까지 포함해서 1메가가 조금 넘는 크기입니다.

스프링, 하이버 학습 시 또는 자바 5이상 프로젝트에 자유롭게 사용하시기 바랍니다. 아! 주의할 것이 있는데, OSAF는 EPL 라이선스라는 것입니다. 단순한 사용에는 아무런 제약이 없지만, 저희 코드를 수정하거나 복사하여 재 배포 할 시 해당 코드도 반드시 공개해야 합니다. 이 점 주의해 주시기 바랍니다. :)

현재 버전은 OSAF 1.0.0 M1 입니다. 아직은 부족한게 많아서 마일스톤 버전으로 공개합니다. 이번 배포 버전에는 OSAF-Core 모듈과 OSAF 기반의 웹 애플리케이션 샘플을 같이 제공하고 있습니다.

http://www.opensprout.org/wiki/display/os/OpenSprout+Application+Framework

위 페이지가 OSAF 위키 페이지입니다. 저곳을 중심으로 OpenSprout 관련 위키 글을 정리할 예정입니다.

https://sourceforge.net/project/showfiles.php?group_id=158280&package_id=177263


소스 코드는 위 링크에서 다운로드 할 수 있으며, depedency 라이브러리들을 몽땅 포함하고 있는 17M 정도의 osaf-1.0.0-m1-with-dependency.zip과 라이브러리는 제외한 osaf-1.0.0-m1.jar 파일을 받을 수 있습니다.

현재는 문서도 많이 부족하고, 주석도 충분치가 않습니다. 물론 코드 완성도도 조금 떨어집니다. 그런 부분들은 앞으로 버전을 올리면서 차차 보완할 예정입니다. 그리고 스크린캐스팅을 통해서 OSAF 사용법을 자주 올릴 예정이오니, 기대해주시기 바랍니다. 그리고 개선할 부분이나 문제가 있다면 번거롭더라도 이슈를 올려주시면 감사하겠습니다.

관련 사이트는 다음과 같습니다.

OpenSprout 홉 페이지: http://www.opensprout.org/wiki/display/os/Home
OSAF 배포 소식: http://www.opensprout.org/wiki/display/os/Release
OSAF JavaDoc: http://www.opensprout.org/api/
OSAF 이슈 트래커: http://www.opensprout.org/jira/browse/OSAF
OSAF 소스 코드 뷰: http://www.opensprout.org:9060/browse/OSAF/osaf/trunk
OSAF 커버리지: http://www.opensprout.org/coverage/
신고
top

TAG 1.0.0 M1, OSAF






티스토리 툴바