우아한 테크코스 5기 1차 심사에 합격했다..! 🥳 정말 이 날만을 기다리면서도, 합격하지 못할 수도 있다는 마음에 불안한 하루들을 보냈었다. 프리코스가 끝난 이후에도 혹여나 합격할 경우를 대비해서 꾸준히 복습하면서 대비를 해왔고, 휴학하지 않은 재학생이기에 시간이 부족해서 학교 시험은 중간, 기말 모두 포기했다. (F만 안받으면 된다는 마음가짐) 사실 열심히 한다고 해서 누가 붙는다는 보장을 해주는 것도 아니지만, 결과는 생각하지 않기로 마음먹고 매일 매일 최선을 다해왔다. 그저 '성장하는 것'에 목표를 뒀다. 1차 합격 연락을 받은 지금은, 그런 노력을 우아한테크코스에게 인정받은 것 같아 되게 기쁘다. 아직 최종 코테가 남았지만 말이다..! 우아한테크코스에 가까워질수록, 더욱 매력적인 과정으로 다가오..
테스트는 빠르게 작성되어야 한다. 하지만, '잘' 작성되어야 한다. TDD 법칙 세 가지 TDD는 어떤 법칙인가? 많은 사람들이 '코드를 짜기 전 단위 테스트부터 짜는 것'을 떠올릴 것이다. 하지만 이 규칙은 빙산의 일각에 불과하다. 다음 세 가지 법칙을 살펴보자. 실패하는 단위 테스트를 작성할 때까지 실제 코드를 작성하지 않는다. 컴파일은 실패하지 않으면서 실행이 실패하는 정도로만 단위 테스트를 작성한다. 현재 실패하는 테스트를 통과할 정도로만 실제 코드를 작성한다. 이렇게 세 가지 규칙을 따르면서 테스트 코드를 작성하면, 매일 수십 개, 매달 수백 개에 달하는 테스트 케이스가 나온다. 이렇게 일하면 사실상 실제 코드를 전부 테스트하는 테스트 케이스가 나온다. 하지만 방대한 테스트 코드는 심각한 관리 ..
시스템에 들어가는 모든 소프트웨어를 직접 개발하는 경우는 드물다. 패키지, 오픈소스를 이용하는 경우가 많다. 때로는 사내 다른 팀이 제공하는 컴포넌트를 사용한다. 이 장에서는 소프트웨어 경계를 깔끔하게 처리하는 기법과 기교를 살펴본다. 외부 코드 사용하기 인터페이스 제공자와 인터페이스 사용자 사이에는 특유의 긴장이 존재한다. 패키지 제공자나 프레임워크 제공자는 적용성을 최대한 넓히려 애쓴다. 사용자는 자신의 요구에 집중하는 인터페이스를 바란다. 이런 긴장으로 인해 시스템 경계에서 문제가 생길 소지가 많다. 예를 들어 java.util.map은 다양한 인터페이스를 제공한다. clear, containsKey, containsValue ... 하지만 이렇게 유언성이 큰 만큼, 문제가 생길 여지도 많다. 만약..
좋은 코드는 오류나 예외에 대한 대응 메커니즘을 가지고 있어야 한다. 문제가 생기지 않는 코드는 없다. 하지만 문제가 생겼을 때 바로 잡을 책임은 프로그래머에게 있다. 오류 처리는 중요하다. 하지만 이로 인해 프로그램의 논리를 이해하기 어려워진다면, 그것은 깨끗한 코드라 부르기 어렵다. 이 장에서는 깨끗하면서 튼튼한 코드를 만드는 방법에 대해 알아본다. 오류 코드보다 예외를 사용하라 예전에는 예외를 지원하지 않는 프로그래밍 언어가 많았다. 그렇기에 오류 코드를 반환하거나 오류 플래그를 설정하는 방법이 전부였다. if (A예외 발생) { return A_예외_발생; if (B예외 발생) { return B_예외_발생; } ... } 문제가 무엇일까? depth가 늘어난다. 이 말인 즉슨 이해하기 어려운 코..
자료 추상화 다음 두 클래스를 보자. // 1 public class Point { public double x; public double y; } // 2 public interface Point { double getX(); double getY(); void setCartesian(double x, double y); double getR(); double getTheta(); void setPolar(double r, double theta); } 1번은 클래스 구현을 외부로 노출하고, 2번은 구현을 완전히 숨긴다. 둘 중 어떤 클래스가 '나은' 구현일까? 답은 2번이다. 자료를 세세하게 공개하기보다는 추상적인 개념으로 표현하는 게 좋다. 즉, 추상화가 중요하다. 그러나 사실 두 클래스 모두 좋은..
프로그래머라면 형식을 깔끔하게 맞춰 코드를 짜야 한다. 코드 형식을 맞추기 위한 간단한 규칙을 정하고 그 규칙을 따라야 한다. 형식을 맞추는 목적 코드 형식은 의사소통의 일환이다. 의사소통은 전문 개발자의 일차적인 의무다. 오늘 구현한 기능이 다음 버전에서 바뀔 확률은 아주 높다. 그렇다면 오늘 구현한 코드의 가독성도 중요하지 않을까? 코드의 내용 뿐만 아니라 코드 그 자체도 유지보수에 영향을 미친다. 적절한 행 길이를 유지하라 200줄이 넘어가지 않는 파일들로도 커다란 시스템을 구축할 수 있다. 항상 그런 것은 아니지만, 가급적 작은 파일이 큰 파일보다 이해하기 쉽다. 신문 기사처럼 작성하라 좋은 신문 기사의 특징이 무엇일까? 위에서 아래로 추상화 수준이 낮아진다. 즉, 처음에는 커다란 주제를 던져주고..
나쁜 코드에 주석을 달지 마라. 새로 짜라. 잘 달린 주석은 어떤 정보보다 유용하다. 하지만 대부분의 경우는 그렇지 않다. 오히려 코드를 이해하기 어렵게 만들고, 오래되고 조잡한 주석은 거짓과 잘못된 정보를 퍼뜨린다. 주석은 '순수하게 선하지' 못하다. 주석은 고의가 아니더라도 거짓말을 할 수 있다. 주석은 오래될수록 코드에서 멀어진다. 주석까지 유지보수하기란 불가능하다. 코드는 변화하고 진화한다. 주석이 언제나 코드를 따라갈 수는 없다. 따라서 가능한 주석을 줄이도록 노력해야 한다. 주석은 나쁜 코드를 보완하지 못한다 코드에 주석을 추가하는 일반적인 이유는 코드 품질이 나쁘기 때문이다. 표현력이 풍부하고 깔끔하며 주석이 거의 없는 코드가 복잡하고 어수선하며, 주석이 많이 달린 코드보다 훨씬 좋다. 즉,..
작게 만들어라! 함수를 만드는 첫번째 규칙은 '가능한 작게' 이다. 왜 이런 이야기가 나오는 걸까? 논문이나 명확한 증거 자료가 있는 것은 아니지만, 적어도 프로그래밍이 등장한 이후부터 단 한번도 틀린 적이 없는 '진리'이기 때문이다. 또한, 함수의 깊이(depth)는 1단이나 2단을 넘어서면 안된다. 그래야 읽고 이해하기 쉬워진다. 한 가지만 해라! 한 메소드에서 여러 일을 처리하는 경우가 있다. 함수는 한 가지 일을 해야 한다. 한 가지 일만 잘해야 한다. 그렇다면 '한 가지'의 판단 기준은 무엇일까? 추상화 수준이 판단 기준이다. 지정된 함수 이름 아래에서 추상화 수준이 하나인 단계만 수행한다면 그 함수는 한가지 작업만 한다. 우리가 함수를 만드는 이유도 큰 문제를 여러 문제로 나누어 해결하기 위함..
의도를 분명하게 밝혀라 변수나 함수, 클래스명은 다음과 같은 굵직한 질문에 모두 답할 수 있어야 한다. 존재 이유는? 수행 기능은? 사용 방법은? 좋은 코드는 맥락이 드러나야 한다. 예를 들어 다음과 같은 코드가 존재한다. 무슨 의도인지 단번에 이해할 수 있는가? public void change(List list) { for (Car i : list) { i.move(1); } } 좋은 코드는 아래와 같이 맥락이 잘 드러나야 한다. public final int FORWARD = 1; public void moveForward(List cars) { for (Car car : cars) { car.move(FORWARD); } } 그릇된 정보를 제공하지 마라 코드에서 그릇된 단서를 유추할 수 있도록..
마지막 미션이 종료되었다. 후련함보다는 아쉬움이 크지만 내가 겪었던 경험들, 고민했던 부분들을 적어보려고 한다! 주관 100% 로 작성하는 것이니, 틀린 내용이 있을 수도 있고, 이에 대해서는 댓글로 지적해주시면 감사하겠습니다ㅎㅎ 프리코스를 통해 성장한 나의 종착점, MVC 패턴 나는 4주차 미션을 시작하기 전까지 객체에 관한 궁금증이 많았다. 3주차 미션을 마친 시점에서 내가 가진 고민은 다음과 같았다. 객체에게 자율성을 어느정도까지 부여해야 하는가? 3주차 미션을 통해 객체에게 자율성을 부여해야 한다는 사실은 알게 되었다. 그러나 어느정도까지 부여해야 하는지 고민을 지속했다. 즉, 객체 분리의 기준점은 무엇일지 고민했다. 디스커션에도 올려보고, 이것저것 찾아보았지만 명확한 답을 찾지 못했다. 이런 고..