혁신적인(innovative)라는 단어는 엔지니어를 포함하여 많은 사람들에게 꽤 매력적으로 들리는 단어다. 그리고 창발적 설계(Emergent design)라는 말도 마치 무언가 폭발적으로 뿜어나오는 테크닉 같이 있어보이는 느낌을 준다. 많은 사람들이 바라는 형용사와 단어다. "혁신적인 아키텍처와 창발적 설계"이라는 제목으로 IBM dW에 올라오고 있는 글들은 "능률적인 프로그래머 프로그래머 생산성의 비밀 (The Productive Programmer, 지앤선)"의 저자이자 소트웍스사(=마틴 파울러가 과학자 직함으로 있는 곳)의 아키텍트인 닐 포트(Neal Ford)가 쓴 글이다.
현재 번역기준으로 2편까지 나온 이 글들은 몇가지 어려운 용어와 배경지식이 필요한 부분, 그리고 (아쉽게도) 쉽지 않은 번역문장으로 인해 다소 난해했다. 그럼에도 불구하고 이전에 dW의 글을 소개하는 것과 마찬가지로 몇 가지 사전 지식을 갖고 있으면 조금 더 이해하기 쉬울 것 같다.
1. 기술적 채무(Technical Debt)
기술적 채무라는 표현은 켄트벡의 멘토인 워드 커닝엄에 의해 널리 알려지게 된 은유표현으로 기술적 개선사항이 가능한 상황에서 현재의 비용을 써서 해결하지 않으면 이자가 붙게 되어 나중에는 동일한 수준으로 개선하는데에 더 큰 비용이 발생한다는 의미이다.
린 소프트웨어로 이름을 알리 포펜틱 부부의 책(린 소프트웨어 개발의 적용, 위키북스)에도 이를 언급하고 사례가 나온다.
"코드를 변경하기 어렵게 만든다면, 그게 무엇이든 기술적인 빚이다" - 172p
인터넷에서도 이와 관련된 좋은 글을 발견할 수 있다. 소프트웨어 설계에 있어서 관련해서는 언제나 그렇듯 쉽게 풀어써서 많은 사람들에게 IT해설가로 덕망이 높은 마틴 파울러 아저씨의 글(Technical Debt, TechnicalDebt Quadrant)도 시간을 들여서 읽어 볼만한 좋은 글에 해당한다.
위 그림은 기술적 채무의 사분면을 나타내며, 각각의 사분면은 무모함(Reckless), 신중함(Deliberate), 심사숙고(Prudent), 부주의함(Inadvertent)의 조합으로 구성된다
좌측 상단부터 시계방향으로 살펴보면 다음과 같다.
1. 무모함 + 신중함 : "설계에 시간쓸 여유 없습니다"
2. 심사숙고 + 신중함 : "우선 배포하고 결과에 대응해야 합니다"
3. 심사숙고 + 부주의 : "(지나고보니) 이제야 어떻게 했어야 했는지 알게됐다"
4. 무모함 + 부주의: "레이어로 구성한다는게 무슨 뜻이야?"
보통 이런 기술적인 빚을 해결하는데 가장 손쉬운 방법은 리팩터링(Refactoring)을 개발시점 내내 적절하게 적용하는 것이다.
2. SLAP(Single Level of Abstraction Principle, 단일레벨 추상화 원칙)
닐 포드 아저씨의 책에도 언급되는 내용으로 메소드 내에서도 각 라인이 추상화의 레벨이 일치하도록 작성해야 한다는 원칙이다. 아래 예제를 보자. (try 부분 위주로 보길 바란다)
다음은 try 구문 안의 굵은 글씨로 표시한 부분만 발췌한 모습이다.
위 코드는 리팩터링을 통해 아래와 같이 추상화 레벨을 맞춰줄 수 있다.
private메소드는 표시에서 제외하였지만, 이런식으로 addOrder를 리팩터링 해 나감으로써 SLAP위반을 제거할 수 있다. 마찬가지로 기술적 부채를 갚는 방법 중 하나이다.
3. 관련서적 읽기
마지막으로 dW 기사를 읽고 좀 더 잘 이해하려면, 해당 기사에서 언급한 관련 책을 읽는 것이 도움이 된다. 꼭 기사때문이 아니더라도 한 번쯤 읽어보길 추천하는 도서들이기도 하다. (참고로 닐포드의 책은 사실 내용에 조금 논란이 있는 책이긴 하다. :)
- 실용주의 프로그래머
The Pragmatic Programmer(Andy Hunt 및 Dave Thomas 저, The Pragmatic Bookshelf, 2001년)
- 린 소프트웨어 개발의 적용
Implementing Lean Software Development: From Concept To Cash(Mary Poppendieck, Tom Poppendieck, 2006년)
- 능률적인 프로그래머 프로그래머 생산성의 비밀
The Productive Programmer(Neal Ford 저, O'Reilly Media, 2008년)
- 리팩토링: 나쁜 디자인의 코드를 좋은 디자인으로 바꾸는 방법
Refactoring: Improving the Design of Existing Code(Martin Fowler 저, Addison-Wesley, 1999년)
- GoF의 디자인패턴
Design Patterns: Elements of Reusable Object-Oriented Software(Erich Gamma 등, Addison-Wesley, 1994년):
혁신적인 아키텍처와 창발적 설계: 설계를 위한 환경 고려사항
Part1: http://www.ibm.com/developerworks/kr/library/j-eaed17/index.html
Part2: http://www.ibm.com/developerworks/kr/library/j-eaed18/index.html
Part1: http://www.ibm.com/developerworks/kr/library/j-eaed17/index.html
Part2: http://www.ibm.com/developerworks/kr/library/j-eaed18/index.html
현재 번역기준으로 2편까지 나온 이 글들은 몇가지 어려운 용어와 배경지식이 필요한 부분, 그리고 (아쉽게도) 쉽지 않은 번역문장으로 인해 다소 난해했다. 그럼에도 불구하고 이전에 dW의 글을 소개하는 것과 마찬가지로 몇 가지 사전 지식을 갖고 있으면 조금 더 이해하기 쉬울 것 같다.
1. 기술적 채무(Technical Debt)
기술적 채무라는 표현은 켄트벡의 멘토인 워드 커닝엄에 의해 널리 알려지게 된 은유표현으로 기술적 개선사항이 가능한 상황에서 현재의 비용을 써서 해결하지 않으면 이자가 붙게 되어 나중에는 동일한 수준으로 개선하는데에 더 큰 비용이 발생한다는 의미이다.
린 소프트웨어로 이름을 알리 포펜틱 부부의 책(린 소프트웨어 개발의 적용, 위키북스)에도 이를 언급하고 사례가 나온다.
"코드를 변경하기 어렵게 만든다면, 그게 무엇이든 기술적인 빚이다" - 172p
인터넷에서도 이와 관련된 좋은 글을 발견할 수 있다. 소프트웨어 설계에 있어서 관련해서는 언제나 그렇듯 쉽게 풀어써서 많은 사람들에게 IT해설가로 덕망이 높은 마틴 파울러 아저씨의 글(Technical Debt, TechnicalDebt Quadrant)도 시간을 들여서 읽어 볼만한 좋은 글에 해당한다.
[기술적 채무의 사분면]
위 그림은 기술적 채무의 사분면을 나타내며, 각각의 사분면은 무모함(Reckless), 신중함(Deliberate), 심사숙고(Prudent), 부주의함(Inadvertent)의 조합으로 구성된다
좌측 상단부터 시계방향으로 살펴보면 다음과 같다.
1. 무모함 + 신중함 : "설계에 시간쓸 여유 없습니다"
2. 심사숙고 + 신중함 : "우선 배포하고 결과에 대응해야 합니다"
3. 심사숙고 + 부주의 : "(지나고보니) 이제야 어떻게 했어야 했는지 알게됐다"
4. 무모함 + 부주의: "레이어로 구성한다는게 무슨 뜻이야?"
보통 이런 기술적인 빚을 해결하는데 가장 손쉬운 방법은 리팩터링(Refactoring)을 개발시점 내내 적절하게 적용하는 것이다.
2. SLAP(Single Level of Abstraction Principle, 단일레벨 추상화 원칙)
닐 포드 아저씨의 책에도 언급되는 내용으로 메소드 내에서도 각 라인이 추상화의 레벨이 일치하도록 작성해야 한다는 원칙이다. 아래 예제를 보자. (try 부분 위주로 보길 바란다)
public void addOrder(ShoppingCart cart, String userName,
Order order) throws SQLException {
// ...
try {
s = c.createStatement();
transactionState = c.getAutoCommit();
int userKey = getUserKey(userName, c, ps, rs);
c.setAutoCommit(false);
addSingleOrder(order, c, ps, userKey);
int orderKey = getOrderKey(s, rs);
addLineItems(cart, c, orderKey);
c.commit();
order.setOrderKeyFrom(orderKey);
} catch (SQLException sqlx) {
s = c.createStatement();
c.rollback();
throw sqlx;
} finally {
// .....
}
}
Order order) throws SQLException {
// ...
try {
s = c.createStatement();
transactionState = c.getAutoCommit();
int userKey = getUserKey(userName, c, ps, rs);
c.setAutoCommit(false);
addSingleOrder(order, c, ps, userKey);
int orderKey = getOrderKey(s, rs);
addLineItems(cart, c, orderKey);
c.commit();
order.setOrderKeyFrom(orderKey);
} catch (SQLException sqlx) {
s = c.createStatement();
c.rollback();
throw sqlx;
} finally {
// .....
}
}
다음은 try 구문 안의 굵은 글씨로 표시한 부분만 발췌한 모습이다.
try {
// ...
c.setAutoCommit(false);
addSingleOrder(order, c, ps, userKey);
// ...
}
두 줄은 서로 목적레벨이 다르다. 윗줄은 트랜잭션을 처리하는 부분이고, 그 다음은 addOrder 메소드의 논리로직이다. 서로 추상화의 수준(Level of Abstraction)이 다른것이다. 이런식으로 작성된 코드를 SLAP원칙을 위반한 코드라고 부른다.// ...
c.setAutoCommit(false);
addSingleOrder(order, c, ps, userKey);
// ...
}
위 코드는 리팩터링을 통해 아래와 같이 추상화 레벨을 맞춰줄 수 있다.
public void addOrderFrom(ShoppingCart cart, String userName,
Order order) throws SQLException {
setupDataInfrastructure();
try {
add(order, userKeyBasedOn(userName));
addLineItemsFrom(cart, order.getOrderKey());
completeTransaction();
} catch (SQLException sqlx) {
rollbackTransaction();
throw sqlx;
} finally {
cleanUp();
}
}
[리팩터링 Step1]Order order) throws SQLException {
setupDataInfrastructure();
try {
add(order, userKeyBasedOn(userName));
addLineItemsFrom(cart, order.getOrderKey());
completeTransaction();
} catch (SQLException sqlx) {
rollbackTransaction();
throw sqlx;
} finally {
cleanUp();
}
}
public void addOrderFrom(final ShoppingCart cart, final String userName,
final Order order) throws SQLException {
wrapInTransaction(new Command() {
public void execute() throws SQLException{
add(order, userKeyBasedOn(userName));
addLineItemsFrom(cart, order.getOrderKey());
}
});
}
[리팩터링 Step2]final Order order) throws SQLException {
wrapInTransaction(new Command() {
public void execute() throws SQLException{
add(order, userKeyBasedOn(userName));
addLineItemsFrom(cart, order.getOrderKey());
}
});
}
private메소드는 표시에서 제외하였지만, 이런식으로 addOrder를 리팩터링 해 나감으로써 SLAP위반을 제거할 수 있다. 마찬가지로 기술적 부채를 갚는 방법 중 하나이다.
3. 관련서적 읽기
마지막으로 dW 기사를 읽고 좀 더 잘 이해하려면, 해당 기사에서 언급한 관련 책을 읽는 것이 도움이 된다. 꼭 기사때문이 아니더라도 한 번쯤 읽어보길 추천하는 도서들이기도 하다. (참고로 닐포드의 책은 사실 내용에 조금 논란이 있는 책이긴 하다. :)
- 실용주의 프로그래머
The Pragmatic Programmer(Andy Hunt 및 Dave Thomas 저, The Pragmatic Bookshelf, 2001년)
- 린 소프트웨어 개발의 적용
Implementing Lean Software Development: From Concept To Cash(Mary Poppendieck, Tom Poppendieck, 2006년)
- 능률적인 프로그래머 프로그래머 생산성의 비밀
The Productive Programmer(Neal Ford 저, O'Reilly Media, 2008년)
- 리팩토링: 나쁜 디자인의 코드를 좋은 디자인으로 바꾸는 방법
Refactoring: Improving the Design of Existing Code(Martin Fowler 저, Addison-Wesley, 1999년)
- GoF의 디자인패턴
Design Patterns: Elements of Reusable Object-Oriented Software(Erich Gamma 등, Addison-Wesley, 1994년):
'이생각 저생각' 카테고리의 다른 글
당신은 애자일 전문가 입니까? (Are you an agile expert?) (2) | 2011.05.30 |
---|---|
세상을 구하는 용기 (The Courage that save the world) (5) | 2011.03.29 |
P-Camp & 대안언어축제 2011 참가후기 (4) | 2011.03.16 |
Git vs Mercurial (기트 대 머큐리얼.. 으응?) (10) | 2011.03.09 |
감사주도개발 TDD (Thanks Driven Development) (12) | 2011.03.07 |