실용주의 프로그래머
들어가며
지난 클린코드에 이어서 개발철학에 대한 실용적 관점을 담은 실용주의 프로그래머를 읽게 되었다.
사실 개발자로서 마인드셋을 어떻게 가져야 하는지를 기대했는데, 생각보다 뻔한 내용들, 클린코드와 겹치는 내용들이 많아서 재밌게 읽지는 못했다.
1999년에 출판한 초판, 2019년에 출판한 개정판이 있었는데 초판을 읽어서 그런가 낡은 내용들이 너무 많아서 아쉬웠다.(읽는다면 개정판을 읽자..)
그럼에도 20년이 지나도 필독서로 꼽히기에 한번 읽어볼만한 가치는 충분히 있는 것 같다.
깨진 창문을 놔두지 마라
‘깨진 창문 이론’은 뉴욕과 다른 주요 도시 경찰들에게, 큰일을 막기 위해 조그만 것들을 엄중 단속해야겠다는 영감을 불어넣어 줬다. 정말 그렇게 된다.
정말 그렇게 된다. 깨진 창문, 낙서, 기타 작은 위반 행위를 잘 단속했더니 중범죄가 줄었다
…중략
깨끗하고 잘 기능하는 시스템들이 일단 창문이 깨지기 시작하면 급속도로 악화되는 것을 많이 보아 왔다.
소프트웨어의 부패에는 다른 요인들도 있는데, 그것에 대해서는 다른 곳에서 다루겠지만 방치는 다른 어떤 요인보다도 부패를 더 가속시킨다.
p.35
실제로 레거시 프로젝트를 유지보수할 때 어짜피 망한거라고 다독이며 대충 때운 코드들이 아주 많다.
반면에 새로 시작하면서 컨벤션을 잡고 갔던 프로젝트는 시간이 더 걸리더라도 클린코드를 짜려 노력하게 된다.
언제 멈춰야 할지 알라
사용자들에게 뭔가 직접 만져볼 수 있는 것을 일찍 준다면, 피드백을 통해 종국에는 더 나은 솔루션에 도달할 수 있을 것이다.
…중략
완벽하게 훌륭한 프로그램을 과도하게 장식하거나 지나칠 정도로 다듬느라 망치지 말라. 그냥 넘어가고 코드가 현재 상태에서 한동안은 그대로 있도록 놓아두라.
완벽하지 않을 수도 있다. 걱정하지 마라. 완벽해지기란 불가능하다.
p.44
그림 실력이 좋지 않은 나는 스케치를 그릴 때엔 ‘오 괜찮은데?’라고 생각하고, 물감을 칠하고 나서는 ‘망했다..!’라는 순간이 자주(매번) 발생한다.
프로그래밍도 욕심부려서 완벽에 가까워지려 하는 것보다는 일정 수준에 도달한 후 멈춰서서 사용자 피드백을 받아보는 것이 더 빠르게 완벽에 가까워질 방법인 것 같다.
이카루스가 되지 말자.
지식 포트폴리오
지식에 대한 투자가 언제나 최고의 이윤을 낸다. - 벤자민 프랭클린
새로운 기술, 언어, 환경이 개발됨에 따라 지식은 옛것이 된다.
변화하는 시장 역시 여러분의 경험을 퇴물이나 별 소용없는 것으로 만들 수 있다.
여러분의 지식 가치가 점점 떨어짐에 따라, 회사나 클라이언트에 대한 여러분 자신의 가치 역시 떨어진다.
p.46
이상한 나라의 엘리스 후속작 거울 나라의 엘리스에는 붉은 여왕의 경주에 대한 내용이 나온다.
제자리에 멈춰 있으면 자신도 모르게 뒤쪽으로 이동해 버리고, 그 자리에 멈춰 있으려면 끊임없이 달려야 하는 법칙이 적용된 곳이다.
개발자도 그러하다. 나날이 발전되는 기술에 적응하지 못하면 어느샌가 뒤처져 시장에서 살아남기 힘들어지게 된다.
개발자의 길을 걷는 한, 평생을 공부해야 한다. 개발자가 되고 싶다면, 평생을 공부할 수 있는지를 먼저 생각해보자.
비판적 사고
마지막으로 중요한 점은 여러분이 읽거나 듣는 것에 대해 ‘비판적으로’ 생각하는 것이다.
자신의 포트폴리오에 있는 지식이 정확하고, 벤더나 매체의 과대광고에 흔들림이 없도록 확실히 해야 할 필요가 있다.
자신의 도그마가 유일한 답이라고 주장하는 열광자들을 주의하라.
그것은 여러분과 여러분의 프로젝트에 적용될 수도 있고, 안 될 수도 있다.
p.52
아마 개정판에서는 GPT 같은 도구에 대해 언급이 나왔을 것 같다.
개발자가 정보를 얻기 위해 구글링을 하던 모습에서 이제는 GPT로 쉽게 원하는 정보를 얻을 수 있는 패러다임으로 변화되었다.
나도 매우 유용하게 사용하지만, 언제나 100%로 정보를 신뢰하진 않았다.
항상 1% 확률로 잘못된 정보를 제공할 것이라는 의심을 가지고, 주는 정보를 그대로 가져다 쓰지 않고 적용해보고 검증하고 이해할 때까지 깊이 파고들었다.
덕분에 그로 인해 발생하는 부작용은 별로 없는 것 같다.
100% 옳은 정보는 없다는 점에 유의하며 의심하는 자세를 가져보자.
EJB(Enterprise Java Beans)
책이 쓰이던 시기가 한창 EJB가 뜰 때여서 그런지 EJB에 대한 칭찬이 가득하다.
지금은 스프링이 나오고 아무도 안쓰는 기술이 되었지만, 저자가 왜 칭찬했는지는 궁금하다.
직교성에 대해 칭찬하는 내용이었는데, 먼저 직교성의 정의는 다음과 같다.
직교성이란, 한 요소의 변경이 다른 요소에 영향을 주지 않고 독립적으로 동작하는 성질을 의미한다.
물론 지금에야 분리되는 것이 당연하지만, 그때 당시에는 EJB의 직교성을 갖춘 트랜잭션이 혁신적이었다고 한다.
[옛날 방식]
과거에는 개발자가 직접 코드에서 트랜잭션 시작과 종료를 명시적으로 처리해야 했다.
때문에 트랜잭션 로직이 비즈니스 로직과 섞여 있어서 유지보수가 어려웠다.
1
2
3
4
5
6
7
8
9
10
11
12
13
Connection conn = dataSource.getConnection();
try {
conn.setAutoCommit(false); // 트랜잭션 시작
updateAccountA(conn);
updateAccountB(conn);
conn.commit(); // 트랜잭션 종료
} catch (Exception e) {
conn.rollback(); // 오류 발생 시 롤백
} finally {
conn.close();
}
[EJB]
애노테이션을 통해 비즈니스 로직과 분리되었다.
1
2
3
4
5
6
7
8
@Stateless
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public class BankService {
public void transferMoney() {
updateAccountA();
updateAccountB();
}
}
추정
추정에서 한 가지 재미있는 사실은 사용하는 단위가 결과의 해석에 차이를 가져온다는 것이다.
만약 무언가를 끝내는 데 130일 정도의 근무일 동안 일해야 한다고 말한다면, 듣는 사람은 상당히 가까운 시일 내에 끝날 것이라 생각하며 정확한 일정을 기대하게 된다.
하지만 “아, 대략 6달 정도 걸리겠군요.” 라 말한다면 지금부터 5~7달 사이 언젠가 끝날 것이라 여길 것이다.
두 숫자는 같은 기간을 이야기하지만, ‘130일’은 여러분이 느끼는 것보다 더 높은 정확성을 내포한다.
p.121
항상 프로젝트 일정은 빠듯하다. 프로젝트의 기간을 산정하면 보통 2배는 더 걸리게 된다.
때문에 웬만하면 기간을 넉넉하게 잡으려 애를 쓰는데, 책의 내용처럼 구체적인 단위가 아니라 좀 더 추상적인 단위를 쓰게 되면 상대방으로 하여금 약간의 유예기간을 받을 수 있을 것이다.
Assert문
책에서 단정적 프로그래밍으로 assert
를 사용하라는 내용이 있다.
단정문이라는 것은 프로그램이 특정 시점에서 반드시 참일 것이라고 가정하고 개발하는 것이다.
여러 조건을 검사하지 않기 때문에 가독성, 유지보수성이 증가할 수 있다.
디버깅이나 테스트 용도가 아니라 실제 비즈니스 로직에서 assert
를 사용하는 사람을 봤었다.
주로 null체크 대신에 assert로 절대 null이 아니라고 가정을 해버리고 코드를 짰었는데, 뭔가 아니다라는 느낌이 들었지만 시간이 부족했고, 일단은 돌아가기에 넘어갔었다.
문득 이게 생각나서 assert의 위험성을 찾아보았다.
[assert 위험성]
- JVM 실행 옵션에 따라 assert가 실행되지 않을 수 있다
- assert는 검증 역할을 수행하여 조건이 맞지 않으면 에러를 발생시킨다.
- 운영 환경에서는 JVM 옵션(
-ea
)을 활성화하지 않으면 assert가 무시되어 검증이 수행되지 않는다. - 이는 위험한 버그를 발생시킬 수 있다.
- Exception이 아닌 Error가 발생한다
- assert를 활성화했다고 가정한다.
- assert가 실패하면
AssertionError
가 발생하는데 이는RuntimException
이 아닌Error
계열이다. - Error는 보통 시스템적인 문제로, 애플리케이션에서 직접 처리하기가 어렵다.
때문에 assert문은 자제하고, Exception을 발생시키는 구문을 넣어야 한다.
assert 사용으로 어떤 버그들이 발생했을지 궁금하긴 하다..
추상화
일반적인 분산 애플리케이션을 작성할 때는 시스템 내부의 모든 분산 트랜잭션과 상호작용마다 서로 구별되는 API 호출을 만드느라 상당한 시간을 소모하기 마련이다.
인터페이스와 상호작용들의 조합이 폭발하게 되면, 프로젝트는 금세 악몽으로 바뀌어버린다.
칠판을 이용하는 방식의 프로그래밍을 하면 이렇게 많은 인터페이스가 필요 없어지기 때문에, 더 우아하고 일관성 있는 시스템을 만들 수 있다.
p.266
추상화에 대한 내용이었다.
인터페이스를 두고 여러 구현체를 두어 추상화하는 방식을 통해 더 유연하고 깔끔한 시스템을 만들 수 있다.
스프링은 추상화를 적극 사용하여 복잡한 시스템이 유기적으로 돌아간다.
이 점이 스프링의 장점이자 매력 포인트인 것 같다.
요구사항 채굴하기
- 직원 기록은 지명된 사람들만 볼 수 있다.
첫째 진술에 대해 사용자는 다음과 같이 말했을 수도 있다.
“해당 직원의 관리자와 인사부에서만 그의 기록을 열람할 수 있다.”
이 진술이 정정 요구사항일까? 오늘은 그럴 수도 있지만, 이 진술 속엔 비즈니스 정책이 내포되어 있다.
정책은 수시로 바뀐다. 따라서 요구사항 속에 그걸 고정하는 건 그리 좋은 생각이 아니다.
우리는 이런 정책들을 요구사항에서 분리해 문서화하고, 양자를 하이퍼링크할 것을 조언한다.
요구사항은 최대한 일반적 진술로 만들고, 나머지 정책에 관한 정보는 개발자에게 구현에서 지원해야 할 것들의 한 예로 넘겨주어야 한다.
p.320
고객들은 생각보다 더 개발에 대해 무지하다.
자신들이 본 서비스의 세부사항이 당연히 요구사항에 포함되었다고 생각한다.
당연히 해당 내용을 전해듣지 못한 개발자들은 ‘적혀있는 요구사항’에 대해서만 충실할 것이고, 고객들은 뿔이 난다.
고객과 만날 일 없이, 개발만 했던 나도 고객의 피드백을 문서로 접한 적이 있었는데 당연한 것이 빠져 화가 난 말투, 당연히 한번에 모든 것이 다 되어야한다는 말투 등 굉장히 공격적인 피드백이었다.
고객들을 상대하는 일은 매우 무서운 일이다.
마무리
옛날 책이어서 그런지 더 당연한 것 같은 내용들이 가득했다.
어찌보면 당연한 일이다.
이와 같은 주장들을 토대로 지금 우리가 쓰고 있는 기술들이 발전한 것 아니겠는가.
당시에는 혁명적이었던 기법들이 지금은 평범한 것처럼, 나중에는 평범한 것이 될 혁명적인 기법들이 곧 등장할지도 모른다.
붉은 여왕의 말처럼 같은 위치에라도 있으려면 쉬지 않고 힘껏 달려야 할 것이다.
여기서는 같은 곳에 있으려면 쉬지 않고 힘껏 달려야 해. 어딘가 다른 데로 가고 싶으면 적어도 그보다 두 배는 빨리 달려야 하고.