= Clean Code = * [http://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882 CleanCode book] * [http://www.cleancoders.com/ CleanCoders] * 쩌네 이런데가 있네요. 안경끼고 손가락질 하는 분 엉클 밥 같으신데..? - [서지혜] * [https://code.google.com/p/support/wiki/CodeReviews Google Code Review System] * [https://code.google.com/p/google-styleguide/ google coding style guide] * [http://refactoring.com/ Martin Fowler의 refactoring home] * [http://blog.goyello.com/2013/05/17/express-names-in-code-bad-vs-clean/?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed%3A+goyello%2FuokR+%28Goyelloblog%29 Express names in code: Bad vs Clean] * [http://dogfeet.github.io/progit/progit.ko.pdf git 사용과 관련된 pro git이라는 책의 한국어 번역본. 상당히 자세히 나와 있다고 하네요] == 5월 4일 == * 스터디 킥오프 * 도서 : [http://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882 Clean Code] * [서지혜]의 my-calculator 코드를 피어 리뷰함. == 5월 11일 == * Clean Code 읽은 부분에 대해 토론(Chap 01, Chap 09) * Chapter 2 Meaningful Names - Naming Convention * 클래스의 이름을 지을 때는 -info, -data와 같은 일반적인 이름을 쓰지 말라. * Account를 만들면 되지 AccountInfo라는 클래스를 만들 필요는 없다. Account 클래스 내부에 들어가는 정보가 Info니까. * -List 라는 식의 이름을 지을 때는 정말로 List의 API들을 지원할 때에만 -List라고 붙여주는것이 좋다. 이름을 저렇게 지으면 -List의 API들을 지원할 것 같은 느낌이 들기 때문에 아닐 경우에는 -s나 다른 방식으로 하는게 좋을 것. * 아래와 같은 식으로 Account내부의 정보를 하나로 묶으면 AccountInfo 클래스와 getAccountInfo()등이 있을법하지 않은가? -> 저런 구조 자체가 잘못됐을 수 있다. getAccountInfo()와 같은 방법이 아니라 다른 방법으로 일을 시키는 모양이 더 낫다. {{{ Class Account { private AccountInfo info; }; }}} * Chapter 9 Unit Tests * 문제를 들었을 때 테스트코드를 먼저 생각하는 습관을 들여야 할 것 같다. 문제를 해결하는 코드를 먼저 짜려고 하면 결국 테스트코드 작성이 아니라 직접 테스트를 하게 되는 듯 하다. * 피드백을 빨리 받기 위해서 테스트를 실시. 피드백을 받고 고칠 때까지의 주기가 짧아야 함. 코드를 짜고 유닛테스트를 만드는 것도 안되는건 아님. 피드백을 바로 받을 수 있으면 됨. * 코드를 깨끗하게 하고 싶으면 테스트 코드도 깨끗하게 유지해야 한다. 테스트 코드가 더러워지면 테스트를 잘 안하게 되니까 코드도 더러워지게 된다. * 테스트 시에는 올바른 input이 제대로 들어오는지를 먼저 확인하고 나서 코드가 잘못되었는지 생각해볼 것. * 실제로는 쓰지 않는데 테스트를 위한 메소드를 추가하게 되는 경우가 있을 수 있지 않은가? -> java의 경우는 reflection을 사용하면 메소드의 추가 없이 처리가 가능한 경우도 있지만 그것보다도 테스트용 framework(mockito 등)를 사용하는것이 좋다. * [http://oddpoet.net/blog/2010/08/02/a-new-look-at-test-driven-development-kr/ BDD, Given/When/Then] * gerrit 설치 * [http://alblue.bandlem.com/2011/02/gerrit-git-review-with-jenkins-ci.html 참고 데모 동영상] * [https://gist.github.com/benelog/2922437 버전관리가 필요한 이유를 깨닫는 어떤 사람] * [http://www.filewiki.net/xe/index.php?&vid=blog&mid=textyle&act=dispTextyle&search_target=title_content&search_keyword=gerrit&x=-1169&y=-20&document_srl=10376 gerrit install guide] * [http://whatwant.tistory.com/419 위와는 좀 다른 참고 사이트] - 이쪽이 전체적인 흐름이나 아파치 설정 관련은 좀 더 보기 괜찮은 것 같다. * [http://u1aryz.blogspot.kr/2011/12/gerrit-error-gerritsite-not-set.html Gerrit기동시에「** ERROR: GERRIT_SITE not set」] * 헐ㅋㅋㅋ 번역하니까 인스토루디레쿠토리로 나온닼ㅋㅋㅋ 전 그냥 환경변수 설정 해버렸습니다. 절대경로 쓰다가 베이스 디렉토리 한번 날려먹고 가능하면 피해범위 적도록 경로 이동해서 조작하거든요. - [서지혜] * next : git과 연동 * Git + Gerrit + Jenkins 전체 결합을 통해 코드 버그를 줄여보자 * [http://rein.kr/blog/archives/3156] == 5월 18일 == * 함수 * 플래그는 추하다 * [http://c2.com/cgi/wiki?GuardClause guard clause]를 쓰세요! * 함수는 하나의 일을 하는게 좋다고 하는데 플래그를 쓴다는 것은 함수가 플래그의 값에 따라서 다른 값을 한다고 말하는 것이므로. * 차라리 다른 일을 하는 함수를 여러개 만드는게 더 낫다. * abstraction level * String.append와 PathParser.render는 둘이 서로 문자열을 합치는 작업을 하더라도 직접적인 연산을 하는 것과 추상적인 연산을 하는 것의 차이로 서로 추상화 수준이 다르다고 할 수 있다. * 추상화 수준이 서로 다른 코드가 섞여있으면 보기에도 좋지 않다. * 추상화 레벨이 달라지는 것을 막기 위해서는 코드를 짧게 하고 메소드로 많이 나누면 한 코드 내에서 추상화 레벨이 달라지는 것을 막을 수 있다. * 함수 인자는 적을수록 좋다. * 함수 인자가 많아지게 되면 사용자가 인자들에 대해서 이해를 하기 힘들다. * 테스트 코드를 작성할 때 인자들의 조합 수에 따라 테스트 케이스가 늘어날 수 있기 때문에. * Error Handling * 에러를 방지하거나, 처리하는 코드 때문에 함수의 본 임무를 파악하기 힘들게 되면 안됩니다. * Consider using try-catch-finally instead of if statement. * Don't return null. * Returning null or undefined (Javascript) {{{ var array = stringObject.match(/regexp/); // if there is no match, then the function returns null, if not returns array. if(!array){ // handle and return } array.forEach(/* handle found strings */) ... }}} * Returning emtpy object (Javascript) {{{ var array = stringObject.match(/regexp/) || []; // if the function returns null, then substitute empty array. array.forEach(/* handle found strings */) /* You can handle empty array with "array.length === 0" statement in anywhere after array is set. */ }}} * Don't pass null. == 후기 == * 민관 * + : 코드 리팩토링을 해봐서 좋았다. 화이트보드에 적어가면서 읽어본 부분 공유하니까 정리된 느낌. * - : 프로젝트 방식과 방향이 흐릿한 느낌이다. * F : 시간을 컴팩트하게 진행하고 싶다. 늘어지는 경향이 있다. * 진경 * + : 리팩토링을 시도해보았다. 다른 사람의 코드를 리팩토링 할 수 있다는 생각을 하게 되었다. * - : 본인의 코드를 리뷰받고 싶었는데 정리가 되지 않아 받지 못했다. * F : 주중에도 스터디를! 온라인 협업 툴을 이용할 수 있다. * 영주 * + : 책 얘기만 한게 아니라 책의 예제를 시도해봤다. * - : 각자 예제를 리팩토링했다. 따로 논 느낌. * 사실 그런 느낌이 들어도 결국 코드 짜는 부분은 따로 할 수밖에 없는 것 같으니 어쩔 수 없는 것 같기도 하지만요. - [서영주] * F : 스터디를 제대로 하고 있는지 알고싶다. (멘토가 있었으면 좋겠다?) * 코칭을 받고 싶다는 말인듯 - [서지혜] * 가르쳐주는 것 까지는 아니고 잘 하고 있는건지 아닌지를 알 수 있었으면 좋겠다는거죠. 목표 얘기 하신건 확실히 제대로 하고 있는지 참고가 될 것 같습니다. - [서영주] * 네 그래서 일부러 코칭이라고 썼어요ㅋㅋ 멘토링은 아닌 것 같고 티칭은 지양하고싶고, 스터디가 잘 되어가고 있는지를 확인하고 싶다는 맥락에선 코칭이 제일 유사한 것같아서리.. - [서지혜] * 희정 * + : 처음 나올때 떨렸는데 많이 신경 써 줘서 좋았다. * - : 배경지식이 부족한 듯 하다. * F : 스터디중에 어떻게 진행해야 하나에 대한 얘기를 너무 많이 한다. * 지혜 * + : 다른 사람들이 리팩토링 하는 것을 보았다. 새로운 사람 추가 * - : 리팩토링을 할 때 리팩토링에 대한 요구사항, 리팩토링을 멈출 수 있는 수준을 제시하지 못하였다. * '이것'을 제시할 수가 있나? * F : 스터디 첫날 정했던 각자의 목적과 목표(어디갔지?)를 통해 스터디가 제대로 진행되어 가고 있는지 체크할 수 있을것. * 그러나 자신의 실력이 더 나음을 어떻게 비교할 수 있을까? [http://www.intropsych.com/ch07_cognition/learning_curve.html 학습 곡선]도 무시할 수 없다. == 5월 25일 == * ajax (callback에 대한 이해를 위해) * javascript를 이용한 비동기 http 요청. * UI를 그리는 흐름(thread)과 http 요청에 대한 흐름(thread)이 따로 존재함. * http 요청 쪽은 언제 작업이 끝날지 알 수 없음. * callback 함수라는 것을 이용해서 작업이 끝났을 때 처리할 방법을 정할 수 있다. * 진경이 코드(CauBooks) 살펴보기 * javascript 소스 코드에서 한꺼번에 인자를 넘기는 방식. * 로그인 성공, 실패에 따른 callback 함수를 한 번에 넘기고 있다. * 현재는 callback 함수에 이름을 붙여서 인자에 넣고 있지만 주로 익명 함수를 쓰는 js의 특징이나 프로그래머가 직접 이름을 붙여서 관리를 해야 하는 등의 불편함을 고려하여 다른 방식으로 수정하고 싶다. * 한꺼번에 { id:, password:, success:, fail: }을 하나의 객체로 만들어서 넘기는 방식. * id, password와 success, fail은 관계가 별로 없는데 같이 묶어서 넘기면 나중에 login 내에서 각각의 파트를 또 뽑아내야 한다. * 객체가 넘어가는 거니까 특정 property의 유무에 따라 에러를 일으킬 수 있다. * module.login(id, password).success(function() {...}).fail(function() {...})으로 수정할 경우. * 각 callback 함수에 대한 의도가 보다 잘 드러남. * 좋은 코드? * 현재 CleanCode에서 좋은 코드로 너무 가독성만을 중시하고 있는 것은 아닌가. * 읽을 사람의 수준을 고려하는 것도 필요하다. (너무 다 풀어 쓴 코드보다는 읽는 사람이 이해할 수 있을 정도의 난이도 + 효율적인 코드가 낫지 않은가) * 동감합니다. 제가 클린코드 스터디를 하는 이유는 궁극적으로 생산성 향상입니다(제가 요즘 강조하는? ㅋㅋ). 지혜 누나가 언급했듯 코드는 일단 동작해야 하는 것이 첫 번째. 제 취향대로 약간 추상화하자면 요구사항을 충족하는 것. 임베디드 개발에서는 퍼포먼스 향상을 위해 '정석적인(?)' 구조나 방법론을 깨는 경우도 있습니다. 요구사항을 충족하지 못 하면, 실질적으로는 아무 것도 생산하지 않은 것과 같을 수도 있으니까요. - [정진경] * 산문이냐 운문이냐의 차이라는 생각이 듭니다. - [서지혜] * [서지혜]의 my-calculator 테스트 코드 리뷰 * spec에 지정되어 있지 않은 경우에 테스트 코드를 작성해야 하는가? * spec에 지정되어 있지 않다는건 무슨 의미지?? - [서지혜] * 예를들면 입력이 들어왔을 때 A라는 출력이 나와야 한다고만 spec에 정의돼있으면 입력이 없을 때에 대한 테스트 코드는 무슨 기준으로 작성하느냐 또는 에러처리를 해야 하는가에 대한 기준을 말하는것 같습니다. - [서영주] * 아, 그런말 한 것 같네요. 이경우는 코드가 아니라 요구사항(아키텍처) 단계에서 정의가 필요한 일이네요. - [서지혜] * 실제 일하는데서는 어떤가요? 이런 부분에 대한 요구사항이 없을 경우에는 어떤식으로 처리를 하는지가 궁금합니다. 먼저 처리하고 어떻게 처리했다고 따로 보고하나요? 아니면 없으니까 이런걸 정의해줘야 한다고 건의를 하고 대답이 오면 그 때 처리를 하나요? - [서영주] *[https://github.com/styleguide/ruby Ruby StyleGuide] - 코딩 스타일 자체보다 왜 그런 스타일을 선택했는지에 대해 생각해 보는 것이 중요함. === 회고 === 1. 지혜 + : 회사에서 짐을 나르다가 왔는데(이삿짐 나름.. 주말에.. 젠장), 오기를 잘 한 것 같다. - : 원래 올 계획이 아니었기 때문에 필요한 노트북이나 책 등을 챙겨오지 못 했다. 1. 서영주 + : 무작정 클린 코드에 대해 이야기를 했었는데 좋은 코드에 대한 얘기를 하면서 클린 코드에 대해 다시 생각하게 됨. - : 좋은 코드를 구해 오자고 했는데 하다 보니 생각보다 어려워서 못 찾아온 것에 대한 미안함. 1. 진경 + : 서영주가 코드에 대해 리뷰를 하고 생각을 적어 준 것. -> 누가 코드를 봐 줬으니 다음 주에 또 작업을 할 동기가 됨. - : 스터디 시간의 경계선이 아직 뚜렷하지 않음. f : - 줄이고 + 늘리게 1. 박희정 <= 자기 코드 들고 오면 좋겠다 + : 초반에 callback, ajax에 대해 따로 설명을 해 준 게 좋았음 - : 말하는 내용을 완전히 이해하기가 힘들다. 1. 서민관 + : 따로 준비 해 온 게 없었지만 그래도 다른 분들 덕분에 진행이 잘 되었다. 준비를 하지 않더라도 참가에 의미가 있다는 생각을 할 수 있게 되었다. - : 시간 줄일 수 없을까? 책진행? 코드 진행? 진행을 어떤 식으로 해야 할지 아직도 매끄럽지 않은 느낌이 있다. = 6월 1일 = * [http://docs.oracle.com/javase/specs/jls/se7/jls7.pdf java se7 spec] * guava 코드 * [서영주]의 xml 파서 * [서민관]의 셀룰러 오타마타 게임 == 회고 == 1. [서지혜] 1. [서영주] 1. [정진경] 1. [박희정] 1. [서민관] = 6월 8일 = 1. 4장 코멘트 1. CleanCoders 강의 맛보기. 1. 에피소드 1은 1달러여서 싼 줄 알았는데 그 이후부턴 12달러...ㅠㅠ 1. 지원금으로 구매하는게 좋겠음. 1. SE titan 코드 리뷰 1. 회식 - 7만원 지원받음 == 회고 == 1. [서지혜] 회고를 회식으로 적을 뻔 했다. 1. [서영주] 1. [정진경] 1. [박희정] 1. [서민관] 1. [안혁준] 1. [고한종] = 6월 22일 = * [정진경], [김남규](환영!), [박희정] * 남규 C 코드 리뷰. 아직 채점되지 않은 과제물이라 코드는 나중에..? * 꿀잠 * 제가 지루한 강의를 하는 바람에... - [정진경] * 원래 내가 있어야 했는데 개인적인 사정으로 다른 쪽에서 시간을 많이 쓰는 바람에... ㅠㅠ - [서민관] = 8월 24일 = * 김남규, 박희정, 서민관, 서영주, 정진경 * Ch. 11 Systems * Separate Constructing a System from Using It. * 생성과 사용을 분리했을 시의 장점 - 객체 사용 코드는 대개 application 레벨인 경우가 많은데, 객체 생성 방법이 바뀌어도 사용 부분은 그대로 유지할 수 있다. - 객체 생성시에 다양한 추가 작업들(proxy, lazy initialization 등)이 가능하다. * 생성 * [http://wiki.zeropage.org/wiki.php/Gof/AbstractFactory Factory Pattern] - Factory를 사용하기 때문에 복잡한 객체의 생성이나 객체의 실제 모양을 숨길 수 있다. - application 단계에서 Factory를 통해서 직접 객체를 생성하기 때문에 해당 객체의 생성 순간을 application에서 통제 할 수 있다. * Dependency Injection - 객체의 책임을 깔끔하게 나눌 수 있다. - 시스템의 구조가 복잡해 질 수 있다. * 횡단 관심사의 처리(AOP) : DB 접속, transaction, log 등 다양한 모듈들에서 동일하게 나타나는 작업들 * Java Proxies : 객체 생성 시에 proxy를 거치게 하는 방법을 통해 해당 객체의 메소드 호출시 다양한 부가 작업들(횡단 관심사)을 처리할 수 있다. 다만 사용이 복잡하고 사용시에도 아래의 방법들에 비해 제한이 좀 있다. * EJB, Spring ... : 해당 framework에서 제공하는 다양한 방법들을 통해 xml, annotation 등의 간단한 설정으로 횡단 관심사에 관한 코드를 작성하지 않고도 해당 기능들을 자신의 프로그램에 넣을 수 있다. = 8월 31일 = * 김남규, 박희정, 서민관, 서영주, 정진경 * Ch. 12 창발성 * 창발 현상 * 작은 부분을 보았을 때는 나타나지 않는 특성이 전체를 보았을 때는 나타나는 경우를 말한다. * 코드의 성능 개선을 위한 부분적인 리팩토링이 이어지다 보면 어떤 패턴이 나타나는 경우를 예로 들 수 있다. * 인터페이스 분리 원칙 (ISP) * 어떤 객체의 사용자에게 그 사용자한테 필요한 메소드만 있는 인터페이스를 제공하라. * proxy pattern in javascript * 자바스크립트에서 지원하는 apply 함수와 arguments로 함수의 인자값을 받아올 수 있는 것을 이용해 외부의 라이브러리 사용 없이도 간단하게 proxy를 구현할 수 있다. jquery-aop 등의 외부 라이브러리도 있다. {{{ (function() { var proxied = console.log; console.log = function() { alert(arguments[0]); // 이렇게 apply의 앞 혹은 뒤로 실행되기를 원하는 기능을 호출한다. return proxied.apply(this, arguments); }; })(); }}} = 2013년 11월 09일 = [Challengers3] * 김남규, 박희정, 서민관, 서영주, 정진경, 신형준 = comment me = * 스터디 이름 정합시다. 아름다움을 추구하니까 소니 에릭슨? - [서지혜] * 아름다운 걸로 하자면 unit sphere 같은 게 아름다울 것 같긴 한데... 그건 좀 아닌 것 같죠 -_-;; - [서민관] * 음.. 공학자의 아름다움이군... - [서지혜] * Beautiful Code -[김태진] * 후기를 +, -, F 방식으로 나누어 작성했네요! 좋은 방식인듯ㅋㅋ - [김민재] * 엇 난 거슬려서 바꿀랬는데 그냥 냅둬야지ㅋㅋ - [서지혜] * 진경 8/24일자 wiki 내용 작성해줘서 고마워 - [서민관]