/ 개발

개발자 원칙

개발자 원칙

오류를 만날 때가 가장 성장하기 좋을 때다.

엔지니어의 실력은 얼마나 많은 오류와 장애를 만나고 이를 해결했는지 여부에 따라 갈린다.

어떻게 더 나은 개발자로 나아갈 수 있는가?

  1. 오류가 발생하면 소스 코드 레벨에서 이해하자.

    왜 구글에 검색하는 방법이 아니라, 소스 코드 레벨에서 이해하자라고 하는걸까?

    검색으로 문제를 해결하고 끝내버리면 실제로 깊은 지식을 얻기가 어렵다.

  2. 알아낸 지식을 글로 공개하라.

    소스 레벨에서 이해한 내용을 글로 공개하고, 오래 기억할 수 있게하면서 다른 사람의 조언도 들을 기회로 만들어라.

  3. 정말인지 소스 코드로 확인하기 자바7 -> 자바8로 가면 CPU 사용량이 줄어든다. 그렇게만 알고 자바8로 업그레이드 하지 말고, 이유를 알아내라. 실제로 소스 코드를 뜯어봐야 작동 원리를 이해할 수 있다.
  4. 결과물을 내 것으로 만들기 타이밍 공격 -> abcdef.startsWith(“b”) 는 당연히 false 이다. 문자열의 첫 알파벳인 a 가 b와 다르기 떄문.

    그런데 어느 정도 긴 문자열이고, 반복을 많이 한다면 실패 응답이 돌아오기까지의 시간을 측정해서 암호를 추측할 수 있게 된다.

    늘 시간복잡도가 빠르기만해서 좋은 것은 아니다.

개발을 하며 순간마다 떠오르는 이런 의문들에 대해서 가볍게 넘어가지 말자. 하나하나 쌓이다보면 좋은 기술력이 될 것이다.

디자인이랑 무엇인가?

아주 작은 단위의 코드에 적용되는 원칙?

KISS: Keep It Simple, Stupid (제발 클래스나 메서드를 간단하게 만들라는 법칙) DRY: Do not Repeat Yourself, (반복되는 기능이나 객체를 하나로 만들어서 관리하라는 법칙) YAGNI: You Ain’t Gonna Need it (코드를 적어나가다 보면 갑자기 머릿속에서 떠오르는 필요한 기능이 있어서 막 적지만 결국 안 쓴다는 법칙)

SOLID 원칙?

SRP : 단일 책임 원칙 (각 클래스는 하나의 정보만을 가지게 만들어야 한다) OCP : 개방 폐쇄 원칙 (확장에는 열려있으며 변경에는 닫혀 있어야 한다) LSP : 리스코프 치환 원칙 (인터페이스의 서브타이핑은 인터페이스에 정의된 형태를 최대한 유지해야 한다?) ISP : 인터페이스 분리 원칙 (인터페이스는 최소한으로 유지하라) DIP : 의존 관계 역전 원칙 (상위 레벨의 모듈이나 인터페이스가 서브 클래스나 타이핑에 영향을 받아서는 안된다)

이러한 디자인의 원칙은 있는데, 소프트웨어 디자인 에 대한 정의는 어딨을까?

디자인 은 뭘까? 한글로 번역하면 설계 인데, 사전에 따르면

건축물 설립이나 토지 공사, 기계의 제작 따위에서 그 목적에 따라 실제적인 계획을 세우고 구체적으로 도면을 그려 명시하는 일

이라는 의미로 해석이 가능한데, 설계를 하는 방법에 완벽한 것이 없다. 그리고 설계도면을 보고 똑같은 건축물이 나오는 것과는 달리 소프트웨어의 설계를 보고 같은 결과물이 나오기는 힘들다.

설계는 시스템이 어떤 요구사항을 만족시키는 조건을 정의하는 것이다. 라는 개념에서 바라보자.

가령 드론은 날 수 있어야 한다 라는 요구사항을 예시로 든다면 이런 요구사항을 만족한다는 것을 증명할 수 있는, 아주 세밀하고 상세한 조건을 정의해야 한다. 화성의 대기 상태를 파악하고, 화성을 분석하는 등의 파악이 필요하다.

나의 메이저 버전을 업그레이드 하는 마이너 원칙들

개발자는 평생 공부하는 직업이다. 신기술을 탐험하는 숙명을 가진 직업이 개발자다.

나만의 속도로 가라. 방향을 잘 정하고 자신의 속력을 잘 파악해라.

그렇다면 나만의 속도는 어떻게 인지할 수 있을까? -> ‘낯선 방식으로 해결하기’ 학습은 익숙한 것을 의식하지 않고 반복하는 게 아니라, 낯선 것을 의도를 갖고 배우는 것

어떤 대상이 물어보더라도 그 사람이 이해하기 쉽게 설명할 수 있어야 진짜로 ‘아는 것’ 이다.

형식지 -> 암기로 터득한 지식 -> 쉽게 잊을 수 있다.

암묵지 -> 직접 체험해서 체화한 지식 -> 쉽게 잊혀지지 않는다.

결국 둘 다 필요하긴 하다..

남들에게 자존심을 세우기보다 나의 자존감을 채워라

다른 사람들이랑 비교하지말고 하루하루 자신이 성장해나가는 것을 느껴라

목표를 세세하게 나누어서 하나씩 해결해나가는 성취감을 느껴라

혼자 프로그래밍하면 스스로 방향을 바꾸는것을 쉽게 인지하지 못한다. -> 짝 프로그래밍

서로 과정을 기록하고 공유하는 맥락이 제일 중요하다.

의도적으로 실수해라

의도적으로 실수해서 어떻게 되는지 체화했다.

누구나 실수할 수 있다고 가정하고 최종 릴리즈가 되기 전에 실수를 찾아낼 수 있는 안정적인 흐름을 만들어야 한다.

소프트웨어 개발은 유연하게 해라. 다른 사람의 의견을 듣고 서로 공유해라

실패해라 -> 코드를 완성 못해도 좋다. 자신이 생각한 방향으로 시도해보고 실패하는 것은 의미가 있다. 테스트 조건을 가정하고, 결과를 예측하고, 생각이 맞았는지 -> 그러고 나서 개선해라. -> 정리해서 오픈 소스 형태로 공유해라.

달리는 기차의 바퀴를 갈아 끼우기

여러 번의 개발 문화에 대한 질문을 정리하다보니, 어느정도의 행동 강령이 된 세 가지가 있다고 한다.

밥값

Make it work, then make it better (“일단 동작하게 만들다음, 더 좋게 만들어라”)

일단 동작하게 만들어라

일단 동작하게 만들어라, 라는 말은 이해하기 어렵지 않다. 어떻게든 요구사항을 만족해서 정상적으로 수행되도록 하라는 것이다.

사실 이렇게만 보면 언젠간 가능해보이지만 현실은 제약사항이 좀 붙는다. 시간, 비용, 인원 등의 자원에 해당하는 것이 대표적인 제약사항일 것이다.

이러한 제약 조건들을 극복하고 제대로 동작하는 코드를 제때 만드는 것을 글쓴이는 밥값 이라고 부른다. 밥값에는 난이도에 제약은 크게 없다. 만약 신입이 일을 너무 어려워한다면 쉬운 일을 줌으로써 밥값을 하도록 할 수도 있다.

지금 당장 요구사항을 만족하면서 잘 돌아가는 코드가 없다면, 미래에 그 조직이 유지될 수 있을까?

아마 불가능할 것이다. 따라서 지금 당장 실행되는 코드가 있어야 미래에 더 좋은 코드를 만들 수 있다.

더 좋게 만들어라

더 좋게 만들어라 라는 말은 생각해볼 것이 좀 있다.

더 좋은 것의 기준이 뭘까? 더 좋은 코드는 어떤 코드일까?

더 좋은 코드

대체로 더 좋은 코드라는 말을 쓸 때 가독성, 성능, 유연성 을 제시한다.

가독성은 말 그대로 코드를 읽기 쉬워짐으로써 기능이나 버그 수정에 훨씬 용이하다. 가독성이 좋은 코드는 좋은 관행 을 따른다.

  • 줄 바꿈, 탭, 들여쓰기 등등에서 모두와의 약속을 지켜라. 변수명을 지을때도 습관을 지켜라. 예외를 던지기로 했으면 예외를 던져라, null을 반환하기로 했으면 null을 반환해라.
  • 코멘트가 필요없어도 이해 되는 코드는 매우 훌륭하다. 그러나 흐름을 설명하는 코멘트나 반드시 필요한 코멘트를 적는 것에는 주저하지 말자.
  • 코드가 짧은 것이 읽기 좋다. 함축적인 코드보다는 명시적인 코드가 읽기 좋다.
  • 삭제해야 할 코드를 굳이 주석으로 남겨두지 마라. Git 이 알아서 보관해준다.

성능은 매우 중요한 조건이지만 대부분의 경우에서는 우선순위가 높지 않다.

섣부른 최적화는 모든 악의 근원이다.

최적화의 규칙

1. 하지 마라.
2. 아직 하지 마라 (전문가 전용)

성능이 좋은 코드는 대부분 이해하기 어렵다. 정말 성능이 필요한 코드가 있다면 어느 코드가 대부분의 자원을 사용하는지, 프로파일링을 해야한다. 그런 코드들을 격리하고 적절한 시점에 최적화해라.

유연성이 있고 어려운 코드 보다는 유연성이 없더라도 쉬운 코드가 더 좋은 코드이다.

유연성에는 추상화가 필요하다. 그러나 추상화를 숭배하고 남발하지는 마라.

if 문을 극단적으로 배제하고, Factory 를 과도하게 사용하고, 클린 코드와 SOLID 를 ‘과도하게’ 숭배하면서 추상화를 챙기지 마라.

잘못된 추상화보다는 중복이 낫다.

일단 Make it work 를 챙겨라. 그리고 가독성을 최우선으로 챙겨라. 성능과 유연성은 그 다음이다.

기술 부채란?

기술 부채는 당면한 기술적인 문제 해결을 뒤로 미루고, 시급한 비지니스 문제 해결을 우선시하는 일이 반복되면서, 언젠가부터 기술이 비즈니스의 발목을 잡는 상황을 재정적인 부채에 빗단 말이다.

빚을 내서 돈을 쓰면 이자를 댓가로 지불을 해야하는 것 처럼, 기술적인 문제 해결을 뒤로 미루고 비즈니스를 우선시하면 개발 지연과 품질 저하라는 대가를 지불해야 한다.

그렇게 기술 부채가 늘어나면 결국 전면 재개발을 해야하거나 서비스 중단이라는 결과로 이어질지도 모른다.

앞에서 우선 동작하게 하라고 했는데 이러면 기술 부채가 늘어나지는 않을까? 라고 생각할 수 있다. 분명히 동작하게 만든 뒤에는 더 좋은 코드로의 개선이 필요하다.

이럴 때 필요한 것이 보이스카웃 캠핑 규칙이다.

언제나 발견했을 때보다 깨끗하게 해놓고 캠핑장을 떠나라.

수정한 코드는 원래 코드보다는 깨끗해야 한다. 최소한 더 나빠지면 안된다.

물론 현실에서 이렇게 관리하는 건 쉽지 않다. 최소한 더 나빠지지 않게 관리를 하면서 시간을 들여 천천히 더 좋은 개선 방향을 설정하고 실행해야한다.

최근에는 레거시 코드라는 말은 마치 기술 부채와도 비슷한 뉘앙스로 쓰인다.

하나씩 뜯어고쳐야 할 코드라는 의미로 보이는데, 방대한 레거시 부채를 빠른 시일내로 고치려고 한다면 레거시 코드의 양을 보고 좌절할지도 모른다. 천천히 시간을 들여 고쳐라.

부채 청산의 시작은 자동화된 테스트를 확보하는 것이다. 테스트 코드를 작성하면서 부채를 관리할 수 있다면, 그것은 더 이상 부채가 아니다.

현실에서 기술 부채가 없는 개발은 불가능하다. 우리가 지향해야 하는 목표는 기술 부채를 잘 식별해서, 관리 가능한 부채로 만드는 것이다.

삽질

기존에 잘 굴러가던 코드를 다시 발명하는 짓은 삽질일까? 보통은 잘 굴러가는 바퀴를 다시 발명할 필요는 없다. 하지만 개발자는 다르다. 내가 자주 사용하는, 미래에도 자주 사용할 기술이라면 다시 발명해 볼 필요도 있다.

잘 굴러가던 코드를 다시 작성해보면서 작동 원리등의 지식과 경험을 배울 수 있고 운이 좋다면 더 좋은 코드로의 개선도 가능할 것이다.

은탄환

모든 문제를 해결할 수 있는 은탄환은 개발자한테는 없다.

코드를 많이 읽고, 많이 쓰고, 많이 생각해라.

코드 리뷰를 할때 많이 읽어라. 기왕 읽을거면 좋은 코드를 읽어라. 여러 번 반복해서 읽되, 한 줄 읽는데 시간을 너무 많이 쓰지는 마라.

글쓴이가 이 코드를 왜 썼는지 의도(컨텍스트)도 같이 파악하면서 읽어라.