레이블이 code quality인 게시물을 표시합니다. 모든 게시물 표시
레이블이 code quality인 게시물을 표시합니다. 모든 게시물 표시

2018-04-29

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의 장점에 관해서 쓴 글이다. 근데 여전히 GraphQL을 쓸지는 모르겠다. 복잡한 웹 서버를 짤 일이 있으면 모르겠는데 요새는 웹 서버라기보다는 그냥 간단한 툴의 UI를 웹으로 사용하는 정도로만 웹 코딩을 하고 있다. 이 정도 수준의 앱에서는 GraphQL을 사용하는 것이 오버헤드가 더 클 것 같다. 사실 반대로 말하면 뭘 써도 상관 없는 크기라서 GraphQL을 써도 된다. 하지만 다른 라이브러리에 디펜던시 없이 구현할 수 있는 REST에 비해서 GraphQL을 쓰려면 GraphQL을 구현하는 라이브러리를 써야 하므로 의존성을 추가해야 하는데 아직 그만한 필요성을 못 느끼겠다.

GO's New Brand

GO가 새 로고를 발표했다. 드디어 이상한 쥐를 버린 줄 알았는데 Gopher는 마스코트로 여전히 남겨두는 듯 하다.

Flask 1.0 Released

Flask가 드디어 1.0이 됐다. 사실 전에도 0.X인걸 신경 쓰지 않고 썼기 때문에 상관없지만 1.0을 쓰면 괜히 기분이 좋다.

2018-02-23

좋은 코드를 많이 봐야 한다

 얼마 전 트위터에서 재밌는 이야기를 봤다.

 가짜를 알기 위해서 가짜를 공부할 필요가 없다는 글인데, 이 트윗을 보니 어렸을 때 봤던 갓핸드 테루라는 의료 만화가 떠올랐다. 갓핸드 테루는 신입 의사인 마히가시 테루가 수련을 받으며 명의가 돼가는 과정을 그린 의료만화인데, 그중에서 다음과 같은 에피소드가 나온다.
 주인공 테루가 슬럼프에 빠져 엑스레이 판독을 못 하게 되자 선배 의사가 테루에게 과제를 하나 내준다. 어느 환자의 엑스레이 사진을 주면서 이 환자의 문제가 무엇인지 찾아오라는 것이었다. 테루는 열심히 고민해보지만 결국 문제를 찾지 못하고 문제를 냈던 선배에게 물어보는데, 그 사진은 사실 정상인의 엑스레이 사진이었다. 테루는 슬럼프에 빠진 자신을 놀린 거냐며 시간 낭비했다고 화냈지만, 실제 환자의 엑스레이를 보면서 선배의 의도를 알게 된다. 환자의 엑스레이를 통해 공부하면, 병의 종류에 따라서 다른 엑스레이를 보며 공부해야 하고, 엑스레이 판독을 할 때도 가능한 모든 병을 고려해봐야 한다. 하지만 정상인의 엑스레이에 한 번 익숙해 지면 익숙하지 않은 부분이 문제가 있는 부분이라고 금방 눈치챌 수 있다는 것이다.
 어렸을 때는 이 장면을 그저 만화적 과장이라고 생각했다. 하지만 프로그래머로 일하다 보니 딱히 과장이 아닐 수 있다고 생각하게 됐다.

 흔히들 코딩할 때 정답은 없다고 말한다. 같은 결과를 낼 수 있는 수많은 방법이 있기 때문이다. 하지만 코딩에 오답은 있다. 이는 버그가 있는 코드를 말하는 건 아니다. 버그가 있는 코드는 논할 가치도 없다. 오답은 코드를 수정했을 때 버그가 발생할 확률이 높은 코드다. 수정에 민감한 코드는 아무리 지금 버그가 없어도 오답이다.
 근데 프로젝트를 진행하다 보면 이런 오답 같은 코드들이 많이 보인다. 이런 오답 코드를 작성하는 이유는 보통 제대로 된 방법으로 코딩하면 시간이 많이 들고 귀찮기 때문이다. 그래서 약간의 편법을 쓰면 일을 빠르게 진행할 수 있을 거로 생각하기 때문이다. 뭐 가끔은 프로젝트가 끝날 때까지 아무 문제가 없을 수도 있다. 하지만 어떤 이유로든 코드를 수정하게 되면 큰일이 발생한다.

 그렇다면 오답과 오답이 아닌 코드를 어떻게 구분할 수 있을까? 문제가 됐던 프로젝트를 열심히 분석하면 어떻게 수정할지 알 수 있을까? 문제가 된 프로젝트를 분석하면 무엇이 문제였는지는 알 수 있을 것이다. 하지만 어떻게 수정할지는 알기 어렵다. 아마 다른 오답 코드를 작성할 것이다. 오답이 아닌 코드를 만들기 위해서는 잘 짜여있는 코드를 많이 봐두는 것이 중요하다. 좋은 코드에 충분히 익숙해져 있으면, 오답 코드를 봤을 때 어색함이 느껴진다. 그래서 프로그래머로서 성장하기를 원한다면 참여하고 있는 프로젝트 외에 자신보다 잘하는 사람들이 진행하는 프로젝트의 코드를 꾸준히 보는 것이 가장 중요하다고 생각한다.

 아마 그 어색함이 무엇인지 모르는 사람은 이해하기 어려울 것이다. 사실 나도 그랬다. 한 5년쯤 전이었을 것이다. 같은 회사에서 일했던 뛰어난 프로그래머에게 어떻게 하면 그렇게 할 수 있는지 물어봤던 적이 있다. 그때 그분이 했던 정확한 단어는 기억이 안 나지만 비슷한 느낌의 말을 했었다. 그리고 그때 나의 반응은 정말 '그게 무슨 소리인가요?'였다. 그때 들은 조언이 그냥 코드를 보다 보면 알게 된다는 것이었다. 그리고 지금 생각해보면 그 조언을 더 빨리 따랐으면 좋았을 것으로 생각한다.
 사실 프로그래밍 공부를 할 때, 다른 사람이 짠 코드를 분석하는 것은 가장 재미없는 일이다. 읽을 가치가 있는 좋은 프로젝트는 대부분 많은 코드를 가지고 있고, 읽고 분석하는데 시간이 많이 들기 때문에 귀찮고 하기 싫은 일일 때가 많다. 특히 많은 프로그래머는 다른 사람이 짠 코드를 읽는 것보다 자신의 코드를 작성하고 실제 돌아가는 것을 보는 걸 좋아한다. 하지만 만약 더 이상 실력이 늘지 않는다고 생각한다면, 슬럼프에 빠진 것이 아닌지 걱정된다면, 한 번 유명한 다른 프로젝트를 분석해보는 것을 추천한다. 지금까지 보이지 않았던 다른 것이 보이게 될 것이다.

2015-06-21

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

 내가 병특을 시작했던 회사에서 있었던 일이다.

 그 회사는 그냥 흔한 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년 전에 좋은 코드였다고 하더라도 지금 기준에서 좋은 코드라는 보장은 할 수 없다.

 당시 그 회사는 코드의 이력관리를 전혀 안 했기 때문에1) 당시 K가 작성한 코드가 어떤 코드였는지 알 수 없었다. 하지만 내가 보고 있던 코드는 10년 전 기준으로도 좋은 코드였을 거라고 말할 수 없는 그런 코드였다. 개발에서 가장 중시하는 abstraction이나 flexibility를 전혀 고려하지 않고 전역변수들로 가득 차 있던 그런 코드를 아직 수정하지 않고 있던 회사를 도저히 믿을 수 없었다.

 심지어 그 당시 코드는 10년간 전혀 변경이 없던 코드도 아니었다. 앞에서도 말했듯이 당시에 유지 보수라는 명목으로 계약하고 꾸준히 이것저것 기능들을 추가했었다. 글 불구하고 코드스멜들을 전혀 제거하지 않았다는 것은 더더욱 그 회사를 믿지 못하는 계기가 되었다.


1) 난 21세기에 이메일로 패치도 아닌 코드 전체를 주고받으며 작업하게 될 거라고는 상상도 못 했다.

2015-01-17

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 Complexity(a.k.a. MCC)다. MCC는 case 문의 개수와 상관없이 switch 문이 수를 1만 증가시킨다.


 앞에서도 말했듯이 CC나 그 변종들은 계산이 간단하고 대부분의 경우에 유용하기 때문에 실제로 많이 쓰이는 지표 중 하나다. 하지만 CC는 어디까지나 분기가 많으면 코드가 복잡해진다는 경험에 기반을 두는 지표다. 따라서 일의 성격에 따라서 CC가 높을 때 코드의 가독성이 높아지는 경우도 있다.
 게다가 성능이나 다른 요소들로 인해 코드의 간결성을 포기해야 하는 경우도 있기 때문에 어느 정도로 엄격하게 규칙을 적용해야 하는지는 프로젝트의 성격에 따라 달라진다.

1) 정확히는 에러가 있는 함수를 수정했을 때 다른 에러가 발생할 확률이 증가한다.

2014-03-08

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

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

2014-01-23

잘못된 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에 걸릴만한 조건이 들어오지 않도록 코드를 작성했어야 한다.