• "나쁜 코드는 깨진 유리창처럼 계속 나쁜 코드가 만들어지도록 한다."
  • "나쁜 코드는 기술 부채를 만들어 수정을 더 어렵게 하며 결국 조직의 생산성을 저하시킨다."

이 책을 추천 받은 것은 개발 쪽으로 전향한 지 얼마 안되서였던 것 같다. 인터넷에서 추천받았었는지, 아니면 국비지원 학원이 끝나갈 무렵이었는지 정확히는 기억나지 않는다. 그리고 최근에 내가 잘 따르던 선배의 강력한 추천이 한번 더 있었다.
어쨌든 토비의 스프링과 함께 한 번은 봐야지 하던 책이었고, 이번에 드디어 완독을 했다. 아니 1독을 했다고 표현해야겠다.

읽코 좋코가 이 책 보다 조금 더 쉽게 읽힌달까. 나중에 후배들을 맞이하고, 혹은 팀을 이끌어갈 때쯤 2독 3독을 해야 할 책이라고 생각된다. 충분히 많은 도움이 된 좋은 책이지만, 내 경험이 짧아 이해하기 어려운 부분도 많고 확실히 내 수준보다는 더 높았다. 아마도 TDD 라던지, 객체지향 패러다임을 잘 따르는 코드를 본 적이 없어서일까?
아무튼 프로세스를 만들 때 가져야 할 마음 가짐에 대해서 많이 생각하게 되었다. 의미를 가진 코드, 코드의 문맥, 추상화 수준과 왜 그렇게 해야 하는지의 이유도 잘 설명되었다. 코드가 마치 잘 쓰여진 소설처럼 읽힐 수 있도록 작성한다는 마음가짐으로 코딩을 하게 되었다. 단순하게 동작이 목적이 아닌 쉽게 읽힐 수 있도록 고민을 하다 보니 더 직관적이고 객체지향 구조로 코드를 짤 수 있었던 것 같다.

선배가 이 책을 추천할 때, 레거시 코드에 대해 정말 화를 내고 열변을 토했던 것으로 기억한다. 그리고 이 책을 읽으면서 그가 이 책을 추천하면서 왜 그렇게 화를 냈는지 납득했다. 저자는 나쁜 코드가 나쁜 이유에 대해서 여러 예를 들고 그중 기억에 남는 것은 위의 두 문장이다.

나 역시도 나쁜 코드를 혐오한다. 레거시 코드를 유지보수하면서 소스코드의 히스토리를 보면 왜 이런 코드가 생겼는지 납득할 수 있지만, 그렇다면 처음부터 더 좋은 구조로 작성될 순 없었는가 하는 의문이 들곤 한다. 솔직하게 말해서 나쁜 코드를 보면 화도 나고 작성자를 기둥에 묶어두고 싶다는 생각도 든다.
나를 포함한 많은 개발자들이 이 책을 읽고 객체지향 패러다임과 클린코드 원칙들을 따르는, 개발을 잘하는, 후배들에게 좋은 코드를 남기는 시니어가 될 수 있도록 갈고닦기를... 🙏🏻

 
728x90
반응형

읽코좋코

모든 전공 서적들이 빠르게 읽히지 않는데, 다른 전공서적에 비해 쉽게 읽히는 책이며 많은 공감을 하게 되었다. 제목과 내용은 동일하며 주제를 반복 강조하고 있다. 이를 위해 변수명, 함수명, 코드 컨벤션 그리고 리팩토링까지 설명하고 있다.
코드는 이해하기 쉬워야 한다, 다시 말해 코드를 읽는데 드는 비용을 줄여야 한다는 말이다. 코드 파악하는데 드는 비용이 작다는 말은 설계가 명확하고 간결하다는 의미를 내포한다.

이 책을 읽고 실제 코드로 적용할 생각을 하면 머리가 아프지만 읽는 중간 중간 이전에 보았던 코드들이 떠올랐다. 이전에 작성 했던 '성능과 가독성을 높이는 분기처리 방법'을 쓸 때 보다 시야가 더 넓어졌다. "왜?"에 대한 부분이 조금 모호했었는데, 그 부분을 채워주는 내용이였다. 그리고 내가 봐온 레거시 프로젝트들의 코드를 작성했던 개발자들에게 이 책을 던져주고 싶었다.


  1. 코드는 이해하기 쉬워야 한다
    인상 깊었던 내용은 6개월 뒤의 나 자신 또한 쉽게 이해되도록 코드를 작성하라는 내용이였다. 나 역시도 나름의 설명과 주석을 잘 붙여서 만들었다고 생각했지만 1년 뒤 해당 코드를 개선 하면서 다시 분석해 보는 헛수고를 했던 경험이 있었다. 짧은 코드가 더 좋은 코드가 아닌 읽는 순간 바로 이해되는 코드가 좋은 코드라는 뜻이다.
  2. 이름에 정보 담기
    • 구체적인 단어 사용하기
    • 이름 길이(짧은 범위에 잠깐 쓰이면 짧은 변수명, 사용 범위가 넓다면 긴 변수명, 약어 사용 지양하기 등)
    • 포맷팅으로 의미 전달하기(상수는 대문자, 클래스명은 카멜케이스 등)가 있었다.
  3. 오해할 수 없는 이름들
    • 경계를 포함하는 범위 : first, last
    • 경계를 포함/배제하는 범위 : begin, end 사용
    • 불린 : is, has, can, should 사용
    • get 남발하지 않기
    • 여러 개의 이름을 후보로 놓고 고민하기
    • '다른 사람들이 다른 의미로 해석할 여지가 있는가?'가 핵심이였다. 한 번쯤 더 생각해 보면 더 좋은 변수명을 만들 수 있다.
  4. 미학
    • 문서 작업을 하더라도 한눈에 보기 쉽게 쓰인 글이 잘 읽히듯 코드도 마찬가지다.
    • 좌우로 길게 늘어진 코드는 줄 바꿈을 하고 다른 코드들도 똑같이 맞추기
    • 헬퍼 메소드를 이용하여 지저분한 코드 깔끔하게 하기
    • 코드의 위아래 열을 맞추어 읽기 쉽게 하기
    • 코드의 순서를 '가장 중요한 것'에서 '가장 덜 중요한 것' 까지 순서대로 나열하기
    • 코드를 문단으로 만들기 (핸들러, DB 사용 등 문맥이 바뀌면 한 행을 띄우는 등 글을 쓸때 문단을 나누는 것과 동일)
    • 개인의 코드 스타일 VS 전체 코드의 일관성 = 일관성이 올바른 스타일보다 더 중요
  5. 주석에 담아야 하는 대상
    • 불필요한 설명 배제
    • 나쁜 이름에 대한 변명이 아니라 좋은 이름으로 바꿀 것
    • 작업중 생각한 통찰 등을 주석에 기록
      • ex: 하위클래스로 정리해야 할 것 같다
    • 상수의 의미를 설명할 것
    • 다른 개발자가 실수할 수 있는 부분을 예상해서 주석을 달라
      • ex : 1분 후 타임아웃 된다
    • 2, 3중 반복/조건문이 달린 함수는 무엇을 위한 것인지 요약 주석을 단다
    • 주석을 다는 것에 대한 두려움을 버려라
  6. 명확하고 간결한 주석 달기
    • 간단한 입출력 예시 사용
    • 코드의 수행 동작이 아니라 코드의 의도를 적어라
    • 파라미터에도 주석을 넣어라
    • 축약된 단어를 사용하라
      • ex : ~에서 불필요한 빈칸을 제거한다 -> 공백 제거
  7. 읽기 쉽게 흐름 제어 만들기
    • 조건문에서 유동적인 값은 왼쪽, 상대적으로 고정적인 값은 오른쪽에 쓰라
    • if/else 간단한 것을 먼저 처리하라
    • 삼항 연산자의 사용은 간단하게 쓸 상황이 아니라면 피하라
    • 중첩을 피하기 위해 함수를 중간에서 반환하라
    • 2중 if 문은 나누어서 중간에 반환하라
  8. 거대한 표현 잘게 쪼개기
    • 요약 변수 사용, 조건식의 반복되는 중요 비교 값을 상수로 만들기
    • 드모르간의 법칙 사용
    • short circuit 사용을 오용하지 말 것
      • 영리하게 작성된 코드가 혼란을 초래한다
    • 복잡한 논리를 간단하게 표현하기
    • 거대한 구문은 문맥에 따라 나누기
  9. 변수와 가독성
    • 불필요한 임시 변수, 중간 결과 저장 변수, 흐름 변수(boolean) 제거하기
    • 변수의 범위 좁히기
    • 클래스를 작은 단위로 나누기
    • 전역변수 사용 피하기
    • 변수에 다른 값을 여러번 할당하는 것 피하기
  10. 상관 없는 하위 문제 추출하기
    • 비즈니스 로직과 관계 없는 문자열 빈칸 제거, url 형식, 주소 형식등을 다루는 메소드는 분리하기
    • 재사용성을 위해 일반적인 목적을 가진 코드를 많이 만들기
    • 과유불급, 지나치게 나누지는 말기
  11. 한 번에 하나씩
    • 작성된 코드가 읽기 어렵다면, 수행하는 작업을 나열하라
    • 나열된 작업중 분리될 수 있다면 별도의 함수 또는 클래스로 나눠라
    • 파편화를 최소화 할 수 있다.
  12. 생각을 코드로 만들기
    • 논리를 명확하게 설명하기
    • 해결책을 말로 묘사하기
    • 언어에서 제공하는 라이브러리를 많이 사용해 보기
  13. 코드 분량 줄이기
    • 필요가 없는 기능을 구현하려고 애쓰지 말것
    • 코드 베이스를 작게 유지할 것
    • 요구사항에 질문을 던져 요구사항을 잘게 나누어 분석하기.
    • 표준라이브러리와 친해지기
  14. 테스트와 가독성
    • 테스트 코드는 특히 더 읽기 쉬워야 한다
    • 긴 테스트 내용은 다른 메소드로 만들기
    • 읽기 편한 에러 메세지 출력 폼 만들기
    • 좋은 테스트 입력 값 선택하기
    • 지금 작성하는 코드의 테스트 코드를 나중에 작성한다는 사실을 염두해 둘것
    • 지나친 테스트는 지양
  15. 분/시간 카운터 설계 및 구현
    • 실습 예제
 
728x90
반응형

토비의 스프링 3.1 VOL.1

스프링 사용자로서 항상 읽어야봐야 한다라는 소리에 두권을 샀지만, 엄청 어렵다는 소문에 읽을 엄두를 못 내던 책이다. 한 권에 800 페이지가 넘는 굉장한 분량에 두번의 정독 시도를 헛탕쳤었다. [유튜브] "개발바닥" 채널에서 저자 이일민님의 인터뷰와, 그 분이 이제는 스프링 부트 인강을 내시면서 이 책을 다시 시도하였고. 이번에는 1독을 끝냈다.
이제 4년차에 들어서면서 읽어보니 '어느 정도 개발을 했고, 좋은 구조와 효율을 고민해본 사람이 봐야 깊은 뜻을 더 잘 이해할 수 있겠구나' 라고 느꼈다.

이 책은 객체지향적 설계, 리팩토링, 테스트주도개발의 중요성에 대해 꾸준히 강조하고 있다. 단순하게 스프링 프레임워크의 기능 / 개념에 대한 설명도 깊게 나와있지만, 이 책의 요점은 스프링이 왜 이렇게 발전했고, 어떤 패러다임을 녹여서 만든건지 엿볼 수 있도록 도와주는 책이다. 따라서 개발 철학에 더 중점을 두고 읽어야 하는 책이라고 생각 된다.

마틴 파울러와 켄트 백이 강조하던 내용이 녹아 있으며, 아래와 같은 조언을 책 전반에 걸쳐 꾸준히 강조하고 있다.

  • '고정된 작업 흐름을 갖고 있으면서 여기저기서 자주 반복되는 코드가 있다면, 중복되는 코드를 분리할 방법을 생각해보는 습관을 기르자.'
  • '비슷한 기능이 새로 필요할 때마다 앞에서 만든 코드를 복사해서 사용할 것인가? 물론 아니어야 한다. 한두 번까지는 어떻게 넘어간다고 해도, 세번 이상 반복된다면 본격적으로 코드를 개선할 시점이라고 생각해야 한다.'

인상 깊었던 문장

인상 깊었던 문장들은 다음과 같다. 다 읽어보면 떠오르는 것이 있다. 그렇다, 대부분의 레거시 프로젝트의 소스들은 아래에서 하지 말라는 대로 개발되어 있다.

  계층형 아키텍쳐
  관심, 책임, 성격, 변하는 이유와 방식이 서로 다른 것들을 분리함으로써 분리된 각 요소의 응집도는 높여주고 서로 결합도를 낮춰줬을 때의 장점과 유익이 무엇인지 살펴봤다. 성격이 다른 모듈이 강하게 결합되어 한데 모여 있으면 한 가지 이유로 변경이 일어날 때 그와 상관이 없는 요소도 함께 영향을 받게 된다. 따라서 불필요한 부분까지 변경이 일어나고 그로 인해 작업은 더뎌지고 오류가 발생할 가능성이 높아진다. 어느 부분을 수정해야할지를 파악하기도 쉽지 않다.
  따라서 인터페이스와 같은 유연한 경계를 만들어 두고 분리하거나 모아주는 작업이 필요하다.
또, 흔히 저지르는 실수 중의 하나는 프레젠테이션 계층의 오브젝트를 그대로 서비스 계층으로 전달하는 것이다.
서블릿의 HttpServletRequest나 HttpServletResponse, HttpSession 같은 타입을 서비스 계층 인터페이스 메소드의 파라미터 타입으로 사용하면 안 된다.
계층의 경계를 넘어갈 때는 반드시 특정 계층에 종속되니 않는 오브젝트 형태로 변환해줘야 한다.
스프링을 사용하면 이런 데이터 중심의 코드를 만들 수 있을 뿐만 아니라, 실제로 매우 흔하게 발견된다.
데이터와 업무 트랜잭션 중심의 개발에 익숙한 사람들이 많고 이런 아키텍쳐를 의도적으로 선호하는 개발자도 많기 때문이다.
개발자들끼리 서로 간선없이 자신에게 할당된 기능을 독립적으로 만드는 데도 편하다.
최소한의 공통 모듈 정도만 제공되는 것을 사용하고, 그 외의 기능은 단위 업무 또는 웹 화면 단위로 만들어 진다.

하지만 이런 개발 방식은 변화에 매우 취약하다.
객체지향의 장점이 별로 활용되지 못하는데다 각 계층의 코드가 긴밀하게 연결되어 있기 때문이다.
중복을 제거하기도 쉽지 않다.
업무 트랜잭션에 따라 필드 하나가 달라도 거의 비슷한 DAO 메소드를 새로 만들기도 한다.
또한 로직을 DB와 SQL에 많이 담으면 담을수록 점점 확장성이 떨어진다.
DB는 확장에 한계가 있을 뿐 아니라 확장한다 하더라도 매우 큰 비용이 든다.
잘 작성된 복잡한 SQL 하나가 수백 라인의 자바 코드가 필요한 비지니스 로직을 한번에 처리할 수도 있다.
하지만 과연 바람직한 것일까?
이런 복잡한 sql을 누구나 쉽게 이해하고 필요에 따라 유연하게 변경할 수 있을까?
또, 복잡한 sql을 처리하기 위해 제한된 자원인 DB에 큰 부담을 주는 게 과연 바람직한 일인지 생각해볼 필요가 있다.
데이터 중심 아키텍쳐의 특징은 계층 사이의 결합도가 높은 편이고 응집도는 떨어진다는 접이다.
화면을 중심으로 하는 업무 트랜잭션 단위로 코드가 모이기 때문에 처음엔 개발하기 편하지만 중복이 많아지기 쉽고 장기적으로 코드를 관리하고 발전시키기 힘들다는 단점이 있다.
스프링은 그 개발철학과 목표를 분명히 이해하고 사용해야 한다.
자바의 근본인 OOP 원리에 충실하게 개발할 수 있으며,
환경이나 규약에 의존적이지 않은 POJO를 이용한 애플리케이션 개발은
엔터프라이즈 시스템 개발의 복잡함이 주는 많은 문제를 해결할 수 있다.
POJO 방식의 개발을 돕기 위해 스프링은 IoC/DI, AOP, PSA와 같은 기능 기술을 프레임워크와 컨테이너라는 방식을 통해 제공한다.
728x90
반응형

+ Recent posts