라벨이 code quality인 게시물 표시

2018년 17번째 주

이 포스팅은 그냥 지난 한 주간 읽었던 것들을 정리하는 포스트입니다. 그냥 예전에 봤던 글 중 나중에 필요한데 뭐였는지 기억 안 나는 글들이 있어서 쓰기 시작했습니다. 보통 하는 일과 관련된 글들이 올라오겠지만 딱히 정해둔 주제는 없고, 그때그때 관심 있었던 것을 읽었기 때문에 지난주에 쓰인 글일 수도 있고 몇 년 전에 쓰인 글일 수도 있습니다. The Configuration Complexity Clock Configuration을 만들다 보면 Rules engine 이나 심할 때는 DSL (Domain Specific Language)까지 만들기도 하는데, 어떨 때는 그냥 하드코딩 하는 것이 가장 적절한 방법일 수 있다는 글이다. Linus's Law given enough eyeballs, all bugs are shallow 리누스의 법칙은 위의 한 줄로 정리된다. 오픈 소스의 근간이 되는 문장이고, peer-review가 필요한 이유로도 많이 언급된다. 문제는 최근의 거대한 소프트웨어서는 버그를 발견하는 데 필요한 enough의 수가 너무 크다는 것이다. 게다가 시스템이 복잡하다면, 그 시스템을 이해하지 못한 개발자는 버그를 발견하기 위한 eyeballs 중 하나가 되지도 못한다. 그렇기 때문에 시스템을 단순하게 유지하는 것이 중요하다. Language Health 각 언어가 오픈 소스에서 얼마나 많이 사용되는지 비교해보는 사이트다. 다만, 어디까지나 오픈소스에서 얼마나 많이 커밋이 있었는지에 대한 비교이지, 얼마나 많은 사람이 사용하는지나, 클로즈드 프로젝트에서 얼마나 많이 사용하는지는 알 수 없다. An introduction to the GNU Core Utilities 리눅스에서 작업하다 보면 필요한 유틸리티 모음. 터미널에서 작업할 때 알면 좋은 것들이다. REST APIs are REST-in-Peace APIs. Long Live GraphQL. GraphQL의 장점에 관해서 쓴 글이다. 근데

좋은 코드를 많이 봐야 한다

얼마 전 트위터에서 재밌는 이야기를 봤다. 은행에 입사하면 위조지폐를 가리는 훈련으로 진짜 돈을 계속 만지게 한다는 말을 들었다. 진짜에 익숙해지면 가짜를 접했을 때 바로 알게 된다고. 가짜를 가리기 위해 왜 가짜인지를 공부할 필요는 없다고. — 연 (@b__5k) 2017년 2월 22일 가짜를 알기 위해서 가짜를 공부할 필요가 없다는 글인데, 이 트윗을 보니 어렸을 때 봤던 갓핸드 테루 라는 의료 만화가 떠올랐다. 갓핸드 테루는 신입 의사인 마히가시 테루 가 수련을 받으며 명의가 돼가는 과정을 그린 의료만화인데, 그중에서 다음과 같은 에피소드가 나온다. 주인공 테루 가 슬럼프에 빠져 엑스레이 판독을 못 하게 되자 선배 의사가 테루 에게 과제를 하나 내준다. 어느 환자의 엑스레이 사진을 주면서 이 환자의 문제가 무엇인지 찾아오라는 것이었다. 테루 는 열심히 고민해보지만 결국 문제를 찾지 못하고 문제를 냈던 선배에게 물어보는데, 그 사진은 사실 정상인의 엑스레이 사진이었다. 테루 는 슬럼프에 빠진 자신을 놀린 거냐며 시간 낭비했다고 화냈지만, 실제 환자의 엑스레이를 보면서 선배의 의도를 알게 된다. 환자의 엑스레이를 통해 공부하면, 병의 종류에 따라서 다른 엑스레이를 보며 공부해야 하고, 엑스레이 판독을 할 때도 가능한 모든 병을 고려해봐야 한다. 하지만 정상인의 엑스레이에 한 번 익숙해 지면 익숙하지 않은 부분이 문제가 있는 부분이라고 금방 눈치챌 수 있다는 것이다. 어렸을 때는 이 장면을 그저 만화적 과장이라고 생각했다. 하지만 프로그래머로 일하다 보니 딱히 과장이 아닐 수 있다고 생각하게 됐다. 흔히들 코딩할 때 정답은 없다고 말한다. 같은 결과를 낼 수 있는 수많은 방법이 있기 때문이다. 하지만 코딩에 오답은 있다. 이는 버그가 있는 코드를 말하는 건 아니다. 버그가 있는 코드는 논할 가치도 없다. 오답은 코드를 수정했을 때 버그가 발생할 확률이 높은 코드다. 수정에 민감한 코드는 아무리 지금 버그가 없어도 오답이다. 근데

변하지 않아도 되는 코드는 죽은 코드 뿐이다.

내가 병특을 시작했던 회사에서 있었던 일이다. 그 회사는 그냥 흔한 SI 회사였는데 덕분에 코드 퀄리티는 크게 보장할 수 없었다. 정말이지 많은 것이 나를 괴롭혔지만, 그중에서 나를 가장 괴롭혔던 건 옛날에 작성되어 관리 안 되는 코드들이었다. 그 회사는 SI 회사답게 유지보수라는 명목으로 몇 년 전에 팔았던 프로젝트의 유지보수라는 이름으로 고정 수익을 벌고 있었는데, 그중에서 가장 심한 건 10년 전에 작성되었던 프로젝트도 있었다. 그 날도 여전히 그 코드에 괴롭힘당하고 있었다. 내가 괴로워하고 있으니 당시 내 사수였던 개발자 J 가 와서 한마디 해줬었다. 너무 그러지 마. 이거 그래도 네 학교 선배 K 가 병특할때 짰던 코드야. 조금씩 변경된 부분이 있지만 대부분 네 선배가 짠 거야. 위로의 말이었는지, 괴로워하는 거 티 내지 말라는 의미였는지 나는 모른다. 내가 아는 것은 그저 이게 내가 퇴사를 결심하게 된 계기가 되었다는 것이다. 어째서 저 말이 그렇게 내 마음을 흔드는 말이 되었을까? 당시에 K 가 퇴사한 건 거의 10년 가까이 된 일이었다. 즉, 저 코드는 작성된 지 거의 10년이 된 코드라는 것이다. 거기에 유지 보수하면서 추가된 기능 외에 큰 틀은 전혀 건드리지 않았었다는 것이다. 뭐 J 는 10년이 지날 만큼 안정적으로 작성된 코드라고 말하고 싶었을지도 모르겠다. 하지만 10년을 변하지 않은 코드가 좋은 코드일 리가 없다. 지난 10년간 프로그래밍 도구는 많은 발전이 있었다. 단적으로 생각해봐서 2003년에 visual studio 6.0으로 코드를 작성하는 것과 2013년에 visual studio 2013으로 코드를 작성하는 것을 생각해보자. 아무도 2013 대신 6.0을 선택할 사람은 없을 것이다. 10년이라는 시간은 이 정도의 발전을 가지고 왔다. 도구뿐이 아니다. 개발 방법론, 설계법, 분석법 모든 측면에서 지난 10년간 많은 발전이 있었다. 즉, 10년 전에 좋은 코드였다고 하더라도 지금 기준에서 좋은 코드라는 보장

Cyclomatic complexity - 코드의 복잡성을 정량적으로 측정하기

Cyclomatic Complexity Cyclomatic complexity (a.k.a. CC)는 코드의 복잡성을 나타내는 지표 중 하나다. CC를 계산하는 방법은 매우 간단하다. 단순히 코드의 컨트롤 플로우가 분기하는 부분의 개수를 세면 된다. CC를 처음 제안했던 Thomas J. McCabe는 함수 하나의 CC가 10을 넘기지 말도록 했지만 이건 76년에 나온 기준이고, 지금의 소프트웨어는 40년 전과 비교가 되지 않게 복잡해진 만큼 15나 20까지는 괜찮다고 주장하는 사람도 있다. 어찌됐든 간에 중요한 것은 CC가 커지면 커질수록 소프트웨어의 에러가 발생할 확률 1) 이 증가한다는 것이다. 최댓값을 얼마로 잡을지는 프로젝트의 성격과 팀의 성향에 따라서 다르게 잡지만, 지난 40년간 코드의 복잡도를 정적으로 측정할 수 있는 몇 안 되는 지표로써 널리 쓰이고 있다. Extended Cyclomatic Complexity 하지만 CC가 단순히 분기점만을 세기 때문에 불만을 가지는 사람들이 있었다. 그들이 불만을 가지는 이유는 크게 2가지다. 우선 CC는 단순히 분기점의 수를 세기 때문에, 실제로 같은 코드를 어떻게 표현하느냐에 따라서 값이 달라진다. 그래서 단순히 분기점을 세는 것이 아니라 조건문에 들어가는 Boolean operator( && , || )의 수를 더하는 지표가 나왔다. 이를 Extend Cyclomatic Complexity(a.k.a ECC)라고 부른다. Modified Cyclomatic Complexity CC에 다른 이유로 불만을 가지는 사람들도 있다. 원래의 CC는 switch에 사용되는 case 문의 수만큼 증가한다. 하지만 대부분의 경우 switch 문에 들어가는 구문은 매우 간단하다. CC의 원래 목적이 코드의 복잡성을 측정하기 위함이라는 것을 생각하면 실제 코드를 복잡하게 하지 않는 switch 때문에 매우 증가하는 CC는 불공평하다. 그래서 나온 것이 Modified Cyclomatic

[html5-lint] console에서 html page validate하기

WebPage를 스펙에 맞게 작성하였는지 https://html5.validator.nu/ 를 이용하여 쉽게 확인할 수 있다. 하지만 이런 방식은 웹 페이지에서 확인하는 방식이기 때문에 autotest를 만들기 어려워진다. 모질라에서도 같은 고민을 하였는지 auto test를 위해 python과 node.js에서 사용할 수 있는 html5-lint 라는 것을 만들어서 사용하고 있다. html5-lint는 validator를 다시 구현하는 방식이 아니라 https://html5.validator.nu/ 로 post request를 날려 결과를 가져오는 방식으로 동작한다. 하지만 이렇게 하면 테스트할 때마다 https://html5.validator.nu/ 에 request를 요청하게 되므로 모질라에서는 클론 페이지 를 만들어서 사용하고 있었지만, 지금은 클론 페이지가 죽어서 다시 원래의 validator.nu/ 를 이용하여 테스트하여야 한다.

잘못된 assert는 사용하지 말자

assert라는 함수는 인자로 받는 조건이 true가 아니면 예외를 발생시키는 함수로, 디버깅을 도와주거나, 코드의 가독성을 올리는 용도로 쓰인다. 게다가 릴리즈에서는 아무 일도 않기 때문에(c++의 경우 NDEBUG가 정의되었는가 아닌가로 동작이 달라진다.), 성능 저하 없이 검증 코드를 집어넣을 수 있다. 근데 릴리즈에서는 아무 동작도 하지 않는다는 특성 때문인지, assert가 가지는 implicit 한 의미를 이해 못 했는지 assert를 잘못 사용하는 때도 있다. 다음의 코드를 보고 이상한 점을 찾아보자. Connection이라는 class의 Send method에서 message를 받아서 platformConnection_(내부 구현이 어떻게 되었을지는 신경 쓰지 말자.)을 통해서 Send해주고 결과 값을 돌려준다. 그 전에 platformConnection_이 valid한지를 검사하여 valid하지 않다면 false를 돌려주는 평범한 코드다. 문제는 함수의 맨 앞에서 valid한지 아닌지 assert로 체크를 하고 있다는 것이다. 이 assert문이 가지는 의미는 절대로 valid하지 않을 때는 절대로 이 함수가 호출되지 않는다는 것이다. 그럼에도 그다음 문장에서 valid한지 않은지 검사하고 있다. 이에 대해 assert는 릴리즈 빌드에는 포함되지 않기 때문에 릴리즈 빌드를 위해서 안전한 코드를 작성해야 한다고 주장하는 사람도 있다. 하지만 이런 경우라면 애초에 assert를 쓰지 않고 조건문만을 써야 한다. assert를 썼다면 assert에 걸릴만한 조건이 들어오지 않도록 코드를 작성했어야 한다.

이 블로그의 인기 게시물

[C++] enum class - 안전하고 쓰기 쉬운 enum

Log Aggregator 비교 - Scribe, Flume, Fluentd, logstash

RAII는 무엇인가

[Python] cache 데코레이터로 최적화하기

[Web] SpeechSynthesis - TTS API