리더가 직접 일을 하면
그 누구보다도 더 잘할 수 있을 것입니다.
그러나 리더는 아랫사람이 잘 못하는 줄 알면서도,
가끔은 실패할 것을 알면서도 일을 맡길 줄 알아야 합니다.
그래야 본인은 더 큰 전략적 업무에 집중할 수 있고,
직원들을 키워 줄 수 있기 때문입니다.
-조영탁, 행복한 경영
2013년 4월 12일
by gdkim
0 comments
리더가 직접 일을 하면
그 누구보다도 더 잘할 수 있을 것입니다.
그러나 리더는 아랫사람이 잘 못하는 줄 알면서도,
가끔은 실패할 것을 알면서도 일을 맡길 줄 알아야 합니다.
그래야 본인은 더 큰 전략적 업무에 집중할 수 있고,
직원들을 키워 줄 수 있기 때문입니다.
-조영탁, 행복한 경영
2013년 4월 10일
by aduris
0 comments
모임정보
모임기간 : 5월 4일 (토) 13시 00분 ~ 18시 00분
등록기간 : 3월 30일 (토) 21시 00분 ~ 5월 3일 (금) 18시 30분
모임장소 : 서울시여성가족재단 아트홀봄
* 총 모집인원 : 180명 | 현재참여자 93명 | 대기 97명
[세미나 제목]
[세미나 구성]
[일자]
[장소]
[세미나 - Agendar]
2013년 4월 10일
by aduris
0 comments
2013년 4월 10일
by aduris
0 comments
죠수아 블로치는 구글의 소프트웨어 아키텍쳐로 유명한 사람입니다.
아래 내용은 2007년 1월 24일 Google Tech Talks 에서 발표한 내용입니다.
API 를 개발하면서 한 번쯤 고민했던 내용들이 모두 들어있습니다.
API 를 개발하는 개발자라면 거의 하나도 놓칠 게 없는 경험이라고 생각합니다.
그만큼 많이 번역되고 블로그에 퍼졌던 글들입니다.
좀 길지만, 많은 개발자들이 두고두고 참조했으면 하는 바람이 있습니다.

원제 : How to Design a Good API and Why it Matters(Google Tech Talks, 2007.1.24)
저자 : Joshua Bloch, Principal Software Engineer, Google
API는 회사가 가진 중요한 자산일 수 있다.
- 고객들은 무섭게 투자한다 : 구매하고, 사용하고, 배운다.
- 운영중인 API를 중단시키는 비용은 엄두도 낼 수 없다.
- 성공적인 public API 는 고객을 잡는다.Public API 는 영원하다. – 그것을 제대로 만들 기회는 오직 딱 한 번 뿐이다.
당신이 만일 프로그래머라면, 당신은 이미 API 디자이너이기 때문이다.
- 좋은 코드는 모듈화되어 있고, 모든 모듈들은 API 를 가지고 있다.유용한 모듈들은 재사용되어지기 때문이다.
- 일단 모듈이 사용자를 가지기 시작하면, 임의로 API를 바꿀 수 없다.
- 좋은 방향으로 재사용되어지는 모듈들은 회사의 자산이다.
API라는 관점에서 생각하는 것은 Code 의 Quality를 높이기 때문이다.
배우기 쉬울 것
문서가 없어도 사용하기 쉬울 것.
잘못 사용하기 어려울 것.
읽기 쉽고, API를 사용하는 코드를 유지보수하기 쉬울 것
요구사항을 만족시키기에 충분히 강할 것.
확장하기 쉬울 것
사용하는 사람들의 수준에 맞을 것
첫째. The Process of API Design
- 만일 더 나은 솔루션들이 있을 수 있다면,당신의 일은 진짜 요구사항을 수집하는 것이어야 한다.
- 유즈케이스 형태로 수집을 해야 한다.
더 일반적일수록 더 쉬워지거나 더 보상이 될 수 있다.
가능한 많은 사람들로부터 반응을 살펴라.
- 그들의 input 에 대해 귀기울여 듣고, 심각하게 받아들여라.
스펙을 작게 할수록, 고치기 쉽다.
자신감을 얻을 때까지 살을 붙여라.
- 이것은 필연적으로 코딩을 포함한다.
- 구현하는 시간을 절약해준다.가능한 스펙을 잡기 이전부터 시작하라.
- 스펙을 잡는 시간을 절약해준다.
살이 붙을 때까지 API 에 글을 적어라.
- 끔찍한 실패를 예방해준다.
- 코드는 예제와 unit test 를 먹고 산다.
- 플러그인 방식의 인터페이스는 여러 개의 구현을 가능하게 한다.
- 예 : Java Ctyptography Extension (JCE)배포하기 전에 multiple plug-in 들을 만들어라. (윌 트랙은 “세개의 법칙”이라고 부른다.)
- 만일 플러그인 하나를 만들면, 아마도 API가 다른 것은 지원하지 못하게 될 것이다.
- 두 개를 만든다면, 어렵게라도 여러개를 지원하기는 할 것이다.
- 세 개를 만든다면, 그것은 아주 잘 작동할 것이다.
- 당신은 모든 사람을 만족시켜줄 수 없다.
- 모든 사람들을 똑같이 불만족하게 만드는 것에 초점을 맞추어라.실수하기를 기대하라
- 몇 년 간 실사용이 되면, 실수따위는 잊어버리게 된다.
- 실수를 통해 API를 진화시켜라.
둘째. General Principles (일반 원칙)
- 이름짓기 힘들다면, 통상적으로 잘못 만들어진 것이다.
- 좋은 이름이 자연스럽게 개발로 이어지게 만든다.
- 모듈을 쪼개거나 합칠 수 있어야 한다.
의심이 들면 그대로 두어라.
- 기능, 클래스, 메쏘드, 파라미터까지.
- 뭔가를 더할 수는 있지만, 결코 제거할 수는 없다. (배포되면 회수불가)개념적인 무게가 규모보다 더 중요하다.
(API의) 힘과 무게(power-to-weight ratio) 간의 균형비를 찾아라.
- 사용자를 혼란스럽게 한다.
- implemenation 을 바꿀 자유를 방해한다.세세한 구현이 무엇인지를 정확히 알아라.
- method behavior 스펙을 너무 과하게 잡지 마라.
- 예를 들면 : hash function 들은 스펙화하지 마라.
- 모든 튜닝 파라미터들은 의심해야 한다. (이게 많다고 좋은 API가 아니라는 뜻)
세세한 구현이 API 로 흘러들어가게 해서는 안된다.
- 디스크 상이나, 네트워크 상이나, 예외로라도 !!!
public class 가 (상수에 대한 예외와 함께) public field를 가져서는 안된다.이렇게 해서 정보은폐를 최대화하라. (밖으로 드러나지 않게 Capsulation 하라는 뜻.)
모듈이 독립적으로 debug 되고, 이해되어지고, 구축되어지고, 테스트 되어지도록 하라.
- 기호나 축약을 사용하지 마라.Consistent 하게 하라 – 똑같은 단어는 같은 것이어야 한다.
- API 전반에 걸쳐서 (API 플랫폼 전반에 걸쳐서!!!)
규칙적이어야 한다. – 대칭과 균형을 갈구하라.
코드는 산문처럼 읽힐 수 있어야 한다. (얼마나 읽기 쉬운가?)
if (car.speed() > 2 * SPEED_LIMIT)
generateAlert(“Watch out for cops!”);
재사용성은 “재사용한다”는 Action 보다 “재사용하겠다.”고 쉽게 말할 수 있는 어떤 것이어야 한다. Action 은 좋은 디자인과 좋은 문서를 필요로 한다. 비록 아주 가끔 우리가 좋은 디자인(설계, 아키텍쳐)을 보게 되었다고 하더라도, 우리가 문서 없이 재사용되어질 정도로 좋은 컴포넌트를 볼 수는 없다. – D.L.Parnas, Software Aging, 1994
- class : instance 화 되는 것들
- method : method 와 그 client 들간의 계약들이다.
- parameter : units, form, ownership 등을 지칭한다.state-space(상태공간, 전체적인 것에 대해)을 주의깊게 문서화하라.
나쁜 의사결정은 성능 한계를 만들기도 한다.
- type 을 상호 교환가능하게 만들어라.
- static factory 대신 constructor 를 제공하라.
- interface 대신에 implementation type 을 사용하라.성능을 얻기 위해 API를 뒤틀지 마라. (변형하지 마라)
- 기본적인 성능 이슈는 고쳐질 것이다. 하지만 두통이 그대와 함께 영원할 것이다.
- 좋은 디자인은 일반적으로 좋은 성능과 일치한다.
- Component.getSize()는 Dimension을 return 한다.
- Dimension 은 mutual 하다.
- 모든 getSize call 은 Dimension을 할당해야만 한다.
- 수많은 불필요한 object allocation 이 발생한다.
- 대체안이 1.2 버전에 추가된다 : old client code 는 여전히 느리다.
- 표준 naming rule 을 따라라.
- 독자적인 파라미터나 Return Type을 쓰지마라.
- 코어 API나 언어에 있는 패턴을 흉내내어 써라.API 친화적인 특징을 이용하라.
- Generics, varargs, enums, default arguments
API 의 위험과 단점들을 잘 알고 회피하라.
- Finalizers, public static final arrays
셋째. Class Design
- 장점 : simple, thread-safe, reusable
- 단점 : 각 value 별로 분리된 object
만일 변경해야 한다면, 상태공간(state-space)를 작게 유지하고, 정의를 잘 유지하라.
- 언제, 어떤 method를 부르는게 합리적인지를 명확히 하라.
Bad: Date, Calendar
Good: TimerTask
- (..은..이다)라는 관계가 존재할 때만 subclass 를 써라.
- 그렇지 않으면, composition 을 사용하라.Bad: Properties extends Hashtable, Stack extends Vector
Good: Set extends Collection
설계가 그렇게 되어 있지 않고 문서가 없다면, 상속을 못하게 만들어라.상속이란 캡슐화와 상충한다.
- subclass 는 superclass 의 세세한 구현에 민감하다.
만일 subclass 를 허락한다면, self-use를 문서화하라.
- method가 어떻게 다른 method 를 사용하는지?
보수적인 정책 : 모든 구체적인 class 는 final 이다.
Bad: Many concrete classes in J2SE libraries
Good: AbstractSet, AbstractMap
넷째. Method Design
- boilerplate code 란 일반적으로 cut-and-paste 로 행해지는 코드를 말한다.
- (모듈을 cut&paste해서 client 내에 넣어버리면) 아주 추하고 번거롭고, 오류 발생이 잦다.
import org.w3c.dom.*;
import java.io.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.*;
import javax.xml.transform.stream.*;
// DOM code to write an XML document to a specified output stream.
private static final void writeDoc(Document doc, OutputStream out)throws IOException{
try {
Transformer t = TransformerFactory.newInstance().newTransformer();
t.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, doc.getDoctype().getSystemId());
t.transform(new DOMSource(doc), new StreamResult(out));
} catch(TransformerException e) {
throw new AssertionError(e); // Can’t happen!
}
}
API 사용자는 behavior 에 의해 놀라서는 안된다.
- 그렇게 하기 위해 구현에 추가적인 노력을 기울일만한 가치가 있다.
- 그리고, 조금 성능을 깎여도 될만한 가치가 있다.
public class Thread implements Runnable {
// Tests whether current thread has been interrupted.
// Clears the interrupted status of current thread.
public static boolean interrupted();
}
런타임에, 첫 잘못된 method invocation 이 제일 좋다.
- method 는 반드시 failure-atomic 해야 한다.
// A Properties instance maps strings to strings
public class Properties extends Hashtable {
public Object put(Object key, Object value);
// Throws ClassCastException if this properties
// contains any keys or values that are not strings
public void save(OutputStream out, String comments);
}
- client 는 괴롭다.
- 더 나쁜 건, string 이 사실상의 API 로 변질되어 버린다.
public class Throwable {
public void printStackTrace(PrintStream s);
public StackTraceElement[] getStackTrace(); // Since 1.4
}
public final class StackTraceElement {
public String getFileName();
public int getLineNumber();
public String getClassName();
public String getMethodName();
public boolean isNativeMethod();
}
- 여러 개의 오버로딩이 동시에 적용될 수 있다.
- 보수적이 되어라 : 동일한 argument 숫자가 없도록 하라.당신이 모호한 오버로딩을 제공해야 한다면, 동일한 arguments에 대해서는 동일한 behavior 가 일어나게 하라.
public TreeSet(Collection c); // Ignores order
public TreeSet(SortedSet s); // Respects order
- 유연성과 성능을 제공하라.가장 구체적이면서 가능한 input parameter type 들을 사용하라.
- 런타임 시간으로부터 컴파일 시간까지 에러를 옮겨라.
더 좋은 type 이 있으면, string 을 사용하지 마라.
- string 은 무겁고, 에러가 나기 쉽고, 느리기까지 하다.
통화를 표현하는데 floating point 를 사용하지 마라
- binary floating point 는 부정확한 결과를 야기시킨다.
float(32 bits) 보다 double(64 bits)를 사용하라.
- 정확성 손실은 현실이고, 성능 손실은 무시할만 하다.
#include
char *strcpy (char *dest, char *src);
void bcopy (void *src, void *dst, int n);
java.util.Collections first parameter always collection to be modified or queried
java.util.concurrent – time always specified as long delay, TimeUnit unit
- 더 많다면, 사용자들은 문서를 참조하려 할 것이다.똑같이 타이핑된 파라미터들의 긴 리스트는 위험하다.
- 프로그래머들이 parameter 순서를 실수로 바꾸어버릴 수도 있다.
- 프로그래머들이 여전히 컴파일하고, 실행한다. 그러나 그것이 잘못일 수 있다.
파라미터 리스트를 짧게할 수 있는 두가지 기법이 있다.
- method 를 두개로 나누어라.
- 파라미터를 유지할 수 있도록 helper class 를 만들어라.
// Eleven parameters including four consecutive ints
HWND CreateWindow(LPCTSTR lpClassName, LPCTSTR lpWindowName,
DWORD dwStyle, int x, int y, int nWidth, int nHeight,
HWND hWndParent, HMENU hMenu, HINSTANCE hInstance,
LPVOID lpParam);
package java.awt.image;
public interface BufferedImageOp {
// Returns the rendering hints for this operation,
// or null if no hints have been set.
public RenderingHints getRenderingHints();
}
다섯째. Exception Design
private byte[] a = new byte[BUF_SIZE];
void processBuffer (ByteBuffer buf) {
try {
while (true) {
buf.get(a);
processBytes(tmp, BUF_SIZE);
}
} catch (BufferUnderflowException e) {
int remaining = buf.remaining();
buf.get(a, 0, remaining);
processBytes(bufArray, remaining);
}
}
정반대로, 조용하게 fail 이 나서는 안된다.
ThreadGroup.enumerate(Thread[] list)
. Unchecked – programming error
. Checked exceptions 의 과한 사용은 boilerplate 를 야기시킨다.
try {
Foo f = (Foo) super.clone();
….
} catch (CloneNotSupportedException e) {
// This can’t happen, since we’re Cloneable
throw new AssertionError();
}
unchecked exception에 대해서는 메시지로 충분하다.
checked exception에 대해서는 accessor 를 제공하라.
여섯째. Refactoring API Designs
public class Vector {
public int indexOf(Object elem, int index);
public int lastIndexOf(Object elem, int index);
…
}
매우 파워풀하지 않다. – 단지 검색만을 지원한다.
문서없이 사용하기 힘들다.
* Sublist Operations Refactored
public interface List {
List subList(int fromIndex, int toIndex);
…
}
매우 파워풀하다. 모든 동작을 지원한다.
인터페이스 사용이 개념적 무게를 작게한다.
- power-to-weight ratio 가 올라간다.
문서 없이도 사용할 수 있다.
// Broken – inappropriate use of String as capability.
// Keys constitute a shared global namespace.
public class ThreadLocal {
private ThreadLocal() { } // Non-instantiable
// Sets current thread’s value for named variable.
public static void set(String key, Object value);
// Returns current thread’s value for named variable.
public static Object get(String key);
}
* Thread-Local Variables Refactored (1)
public class ThreadLocal {
private ThreadLocal() { } // Noninstantiable
public static class Key { Key() { } }
// Generates a unique, unforgeable key
public static Key getKey() { return new Key(); }
public static void set(Key key, Object value);
public static Object get(Key key);
}
동작하기는 한다. 그러나 사용하려면 boilerplate code 가 필요하다.
static ThreadLocal.Key serialNumberKey = ThreadLocal.getKey();
ThreadLocal.set(serialNumberKey, nextSerialNumber());
System.out.println(ThreadLocal.get(serialNumberKey));
* Thread-Local Variables Refactored (2)
public class ThreadLocal {
public ThreadLocal() { }
public void set(Object value);
public Object get();
}
API나 client code 로부터 잡동사니를 없애라.
static ThreadLocal serialNumber = new ThreadLocal();
serialNumber.set(nextSerialNumber());
System.out.println(serialNumber.get());
일곱째. 결론
- 많은 프로그래머와 사용자들과 회사들을 이롭게 한다.
- 노예같이 휴리스틱한 기술들에 달라붙지 마라.
- 충분한 이유없이 그들을 침범하지도 마라.
- 혼자하는 작업이 아니다.
- 완벽할 수 없다. 그러나 완벽해지려고 시도하라.
2013년 4월 9일
by shpark
0 comments
생각을 조심해라. 말이 된다.
말을 조심해라. 행동이 된다.
행동을 조심해라. 습관이 된다.
습관을 조심해라. 성격이 된다.
성격을 조심해라. 운명이 된다.
우리는 생각하는 대로 된다.
- 마가랫 대처
2013년 4월 9일
by admin
0 comments
2013년 4월 9일
by 강명수
0 comments
http://www.adobeconference.co.kr/dps2013/rgst.asp
일시 : 2013년 4월 23일(화요일) 13:00~ 16:50시
장소 : 중구 페럼타워 페럼홀 3층
관심있으신 분들은 신청하세요!
2013년 4월 1일 by alexis | 0 comments
LO STATO DELL’ITALIA
Come siamo, come potremmo essere e soprattutto come vorremmo essere. Inchiesta ottimista sul futuro del nostro Paese.
+
L’INGORGO Sonetto rap per la crescita scritto da JOVANOTTI in esclusiva per IL
illustrations by Giacomo Gambineri
photo by Massimo Siragusa
















2013년 3월 29일
by gdkim
0 comments
“안돼. 나는 할 수 없어”
많은 사람들이 이같이 부정적인 말을 너무도 쉽게, 습관처럼 내뱉는다.
사람의 마음은 강력한 도구이다.
어떤 일이 자신의 능력 밖의 것이라고 일단 확신하게 되면,
그 후에는 스스로 만든 장애물을 넘어서기가 거의 불가능해진다.
-리처드 칼슨, ‘우리는 사소한 것에 목숨을 건다’에서
* 불가능은 사실이 아니라 하나의 의견에 불과하다
Proudly powered by WordPress | Theme: Yoko by Elmastudio
Top
최근 답글