Whiteship's Note


Principle of least astonishment

모하니?/Coding : 2008.09.24 22:06


참조: http://en.wikipedia.org/wiki/Principle_of_least_astonishment

astonishment라는 생소한 단어 때문에 뜻을 가늠하기가 어렵습니다. astonishment는 경악, 놀람이라는 뜻으로, "최대한 놀래키지 말라는 원칙"입니다. 

위키피디아의 정의를 인용하면 다음과 같습니다.

In user interface design, programming language design, and ergonomics, the principle (or rule or lawof least astonishment (or surprise) states that, when two elements of an interface conflict, or are ambiguous, the behaviour should be that which will least surprise the human user or programmer at the time the conflict arises.

즉, 두 개의 애매모호 하거나 상이한 인터페이스 요소는 사용자가 프로그래머에게 혼란을 줄 수 있으니 주의하라는 것입니다.

예를 들어, 보통 Ctrl+S는 저장 단축키로 인식되고 있는데, 이 단축키를 창닫기 용으로 사용하면 어떻게 될까요? 좀 더 코딩에 가까운 예를 들면, 오버로딩한 메소드 두 개가 있을 때 그 둘의 행동은 같아야 합니다. 즉, add(Cat)과 add(Dog)은 둘 다 더해주는 객체만 달라질 뿐 내부에서 하는 일은 동일해야 하는거죠. 둘의 행위가 넘겨져온 객체에 따라 상이해질 경우 개발자나 사용자에게 혼란을 줄 수 있을 겁니다.

API 설계시에 주의해야할 원칙인 듯 합니다. OSAF를 다시 한번 검토해봐야겠습니다. Hibernate에는 사실 UPDATE sql을 직접 날릴 필요가 없습니다. 자동으로 dirty checking을 해서 필요한 순간에 flushing(DB와 SessionContext 동기화)를 할 때 필요한 UPDATE 문을 날려주기 때문입니다. 그래도 가끔은 Session의 reattch() 메소드를 사용해서, 원하는 순간에 명시적으로 UPDATE 문을 날리는 것과 비슷한 결과를 만들 수 있습니다. 

이때, reattach()를 DAO에서는 update()로 감싸야 하는게 좋을지. 그냥 reattch()라고 해야 할지 고민입니다.
top

Write a comment.


How to Design a Good API & Why it Matters

모하니?/Coding : 2008.09.24 14:53


참조 :
http://www.infoq.com/articles/API-Design-Joshua-Bloch
http://www.infoq.com/presentations/effective-api-design;jsessionid=E80287C669787CA7AD3F810A3850932B


Public API(아마 인터페이스를 말하는듯)는 영원한거다. 그만큼 신중하게 만들어야 함.

좋은 API 특징. 문서 없이도 잘 이해가 되는 API

API 설계 프로세스

요구사항을 분명히 할 것

모두를 만족 시킬 순 없다. 모두를 똑같이 실망시켜라.
- 실수 할 수도 있다. API를 진화시켜라.

미심쩍은 것은 무조건 빼내라. 나중에 추가하긴 쉽지만, 빼는 건 불가능에 가깝다.

구현에 대한 세부 사항이 API에 영향을 주지 않게 한다.

최소한의 접근성
- default 접근 지시자가 protected보다 엄격하다. 엄하게 구분해놔야 테스트하기 좋다.

작명은 중요하다.
- 마치 영어 문장처럼 읽히는 코드를 작성하라.

문서화 중요하다.
- 모든 클래스, 메소드, 필드, 파라메터, 예외에 대해 문서화하라.

API 성능에 신경써라.
- Dimension Component.getSize() 같은 API는 매번 새로운 mutable한 Dimention 객체를 생성해내서 성능이 안 좋다.

클래스 설계

mutable은 최대한 최소화하라. 되도록이면 immutable.
- Date랑 Calandar 안 좋아. 변할 수 있는데 왜 안 변해. TimerTask 처럼 좀 변하란 말야.

상속은 리스코프 원칙에 맞게 사용할 것
- is-a 관계 일 때만 사용하기.

메소드 설계

모듈이 할 수 있는 걸 고객이 직접 하게 하지 말아라.
- boilerplate 코드 작성할 필요를 없애라.

Principle of least astonishment를 위배하지 말라.
- Thread의 interrpt의 경우 안 좋은 예에 해당한다. 인터럽트 할 때 현재 상태 정보를 클리어 해버린다. 따라서 clearAndInterrupt라고 하는게 낫겠다.

Fail-Fast
- 컴파일 타임에 에러나면 좋고, 실행 중엔 첫 번째 메소드 호출에서 바로 fail하도록..
- Generic 쓰면 컴파일 타입에 타입 체크 할 수 있으니 좋다.

문자열로 데이터 보여주는 API를 제공하라.
- 안그럼 고객이 직접 작성해야 한다.
- StrackTraceElement 객체의 같은 거 좋다.

오버로딩 사용에 신중하라.
- 오버로딩 할 때는 같은 기능을 제공해야 한다.
- TreeSet의 생성자는 안 좋은 예에 해당한다. 넘겨주는 인자에 따라 행위가 다르다.

파라미터와 리턴타입
- float으로 화폐단위 표시하지 말것. 부정확하다.
- 인터페이스 타입을 사용하면 유연하고 성능에좋다.
- 구체적인 타입일 수록 컴파일 타임에 에러를 잡을 수 있다.
- 문자열 보단 특정 타입을 사용할 수 있도록하자. 문자열은 에러 발생할 여지가 많다.(흠.. 문자열을 써야 할 경우엔 해당 문자열을 상수화해서 쓰면 괜찮지 않을까.)

너무 긴 매개변수 리스트는 피하라.
- 메소드를 나누던가, 헬퍼 클래스를 만들어서 줄여라.

에러 발생 시킬 반환값을 피하라.
- null말고, 비어있는 리스트나 배열을 반환하라.

예외로 흐름 제어 하지 말아라.
- 제어문으로 해라~. 예외는 예외적인 상황일때 그것을 알려주기 위해 사용하라.

언체크드 익셉션을 선호하라.
- checked exception - 사용자가 반드시 복구해야 할 때 사용
- unchecked exception - 프로그래밍 에러

API 설계 리팩토링하기

Vector의 indexOf 메소드
- Vector, List
- ThreadLocal의 string -> Key


top

Write a comment.