4장. 실용주의 편집증
안녕하세요 😀
유로띠 입니다 😉
실용주의 프로그래머
TIL (Today I Learned)
3줄 요약
✏️ 완벽한 소프트웨어는 만들 수 없어.. 안전한 소프트웨어를 만들자.
✏️ 망치지 말고 멈춰!
✏️ 이상적이지만 언제나 교체 가능한 코드를 작성하여 대비하자.
DAY 4
오늘 읽은 범위: 4장 실용주의 편집증
😉 책에서 기억하고 싶은 내용을 써보세요.
여러분은 완벽한 소프트웨어를 만들 수 없다.
🟢 실용주의 프로그래머는 자기 자신 역시 믿지 않는다. 자신의 실수에 대비한 방어책을 마련한다. (P.146)
🟢 불완전한 시스템, 어림도 없는 기간, 우스꽝스러운 도구, 불가능한 요구사항으로 가득 찬 세상에서 안전하게 살아 보자 (P.147)
계약에 의한 설계
🟢 DBC - 계약에 의한 설계(Design By Contract) (P.148)
선행 조건
루틴이 호출되기 위해 참이어야 하는 것.
후행 조건
루틴이 자기가 할 것이라고 보장하는 것.
클래스 불변식
호출자의 입장에서 볼 때는 이 조건이 언제나 참인 것을 클래스가 보장한다.
🟢 자신이 하는 일이라고 주장하는 것보다 많지도 적지도 않게 딱 그만큼만 하는 프로그램이다. 이 주장을 문서화하고 검증하는 것이 '계약에 의한 설계'의 핵심이다. (P.148)
🟢 만약 호출자가 루틴의 모든 선행 조건을 충족한다면 해당 루틴은 종료 시 모든 후행 조건과 불변식이 참이 되는 것을 보장한다. (P.149)
글보다 예시를 보면 더 이해하기가 쉽다.
✅ 예금을 처리하는 예시
선행 조건(pre) : 금액이 0보다 커야 한다, 계좌가 개설되어 있어야 한다.
후행 조건(post) : 반환하는 값인 새로운 거래를 이 계좌의 거래 목록에서 찾을 수 있다.
(defn accept-deposit [account-id amount]
{ :pre [ (> amount 0.00)
(account-open? account-id) ]
:post [ (contains? (account-transactions account-id) %) ] }
"입금을 처리하고 거래 id를 반환"
;; 이런저런 처리를 수행...
;; 새로 거래를 만들어서 반환.
(create-transaction account-id :deposit amount))
계약으로 설계하라.
🟢 게으름뱅이코드 - 시작하기 전에 자신이 수용할 것은 엄격하게 확인하고, 내어 줄 것에 대해서는 최소한도를 약속하는 것이다. (P.151)
DBC 구현
🟢 코드를 작성하기 전에 유효한 입력 범위가 무엇인지, 경계 조건이 무엇인지, 루틴이 뭘 전달한다고 약속하는지, 혹은 더 중요하게는 무엇을 약속하지 않는지 등을 나열하는 것만으로도 더 나은 소프트웨어를 작성하는 데에 엄청난 도움이 된다. (P.153)
🟢 일찍 작동을 멈춰라 (P.154)
🟢 문제를 찾고 원인을 밝히기 위해서는 사고가 난 지점에서 일찍 멈추는 것이 유리하다. (P.155)
🟢 의미론적 불변식은 무언가가 품은 진짜 의미의 중심이 되어야 하며, 훨씬 역동적으로 변하는 비즈니스 규칙처럼 일시적인 정책에 영향을 받으면 안 된다. 우리가 의미론적 불변식이라는 용어를 사용하는 것은 이 때문이다. (P.156)
🟢 죽은 프로그램은 거짓말을 하지 않는다. (P.158)
try do
add_score_to_board(score);
rescue InvalidScore
Logger.error("올바르지 않은 점수는 더할 수 없음. 종료합니다");
raise
rescue BoardServerDown
Logger.error("점수를 더할 수 없음: 보드가 죽었음. 종료합니다");
raise
rescue StaleTransaction
Logger.error("점수를 더할 수 없음: 오래된 트랜잭션. 종료합니다);
raise
end
실용주의 프로그래머라면 다음과 같이 쓸 것이다.
add_score_board(score);
🟢 애플리케이션 코드가 오류처리 코드 사이에 묻히지 않는다. 두 번째 이유는 코드의 결합도를 높이지 않는다는 점이다. (P.160)
🟢 일찍 작동을 멈춰라. 망치지 말고 멈춰라 (P.160)
🟢 방어적 프로그래밍은 시간 낭비다. 그냥 멈추는 게 낫다. 일반적으로 죽은 프로그램이 끼치는 피해는 이상한 상태의 프로그램이 끼치는 피해보다 훨씬 적은 법이다. (P.161)
단정적 프로그래밍
🟢 그런 일은 절대 일어날 리 없어. 이런 식으로 자신을 기만하지 말자, 특히 코딩할 때는. (P.162)
🟢 진짜 오류 처리를 해야 하는 곳에 단정을 대신 사용하지는 말라. 단정은 결코 일어나면 안 되는 것들을 검사한다. (P.163)
리소스 사용의 균형
🟢 중첩 할당 시 리소스를 할당한 순서의 역순으로 해제하라. 코드의 여러 곳에서 동일한 구성의 리소스들을 할당하는 경우에는 언제나 같은 순서로 할당해야 교착 가능성을 줄일 수 있다. (P.171)
헤드라이트를 앞서가지 말라
🟢 작은 단계들을 밟아라. 언제나. (P.178)
🟢 불확실한 미래에 대비한 설계를 하느라 진을 빼는 대신 언제나 교체 가능한 코드를 작성하여 대비하면 된다. 설사 여러분이 미래에 대한 확신이 있더라도 저 모퉁이 너머에 블랙 스완이 기다리고 있을 수 있다. (P.179)
🧐 오늘 익은 소감은? 떠오르는 생각을 가볍게 적어보세요
✅ DBC의 설계 방식을 응용하여 TDD를 한다면 보다 좋은 테스트 설계가 가능할 것 같다. 계약의 의한 설계(DBC)를 읽어보면 맞는지 모르겠지만 단일 책임 원칙이 떠오른다.
많지도 적지도 않게 딱 자신의 책임만 하면 되기에..
✅ 망치지 말고 멈춰. 실제론 애플리케이션을 종료시킬 수 없지만 계속해서 버그를 만드는 것보다는 중지시키고 원인을 찾아 해결하는 것이 더 낫다는 생각이 든다.
실제로 강의의 시청 기록을 저장하는 부분을 패치하다가 강의는 문제없이 시청하지만 시청 기록을 저장하지 못하는 버그가 발생되었다.
약 20여분 정도 후에 알게 되어 급히 핫픽스를 진행했지만, 그 시간 동안 처리되지 못하는 사용자는 대략 1000여 명 정도이다.
만약, 어떠한 버그로 멈춰서 시청이 아예 안되었다면 버그를 빨리 찾아서 핫픽스를 진행했을 것이고 시청기록의 누락도 발생하지 않았을 것이다.
물론 어느 쪽이 피해가 큰지는 확인해야겠지만..
✅ 정말 일어날 수 없는 일은 없다고 생각한다. 책에서도 몇 번 강조하였지만, 코드에 대해 자신을 가지되, 자만하지는 말자.
✅ 코드를 작성할 때 항상 교체 가능한 코드를 작성하면 정말 이것만큼 이상적인 것은 없다고 생각한다. 매번 코드를 작성할 때마다 그놈의 결합도가 높아지고 걷어 내려고 하면 얽히고설키고 스파게티처럼 꼬여있는 코드를 발견하게 된다. 항상 생각하자. 교체 가능한 코드!
🙋♂️ 궁금한 내용이 있거나, 잘 이해되지 않는 내용이 있다면 적어보세요.