🎁[속보] 인프런 내 깜짝 선물 출현 중🎁

[인프런 워밍업 클럽 BE 클린코드 & 테스트 스터디] 발자국 1주차

[인프런 워밍업 클럽 BE 클린코드 & 테스트 스터디] 발자국 1주차

1주차 발자국 정리

 

[섹션 2]

  • 추상과 구체

    • 추상 : 중요한 정보는 가려서 남기고, 덜 중요한 정보는 생략

    • 추상으로부터 구체를 유추하지 못 하는 이유

      • 추상화 과정에서 중요 정보를 부각시키지 못함

      • 해석자가 동일하게 공유하는 문맥이 없음

    • 적절한 추상화는 도메인 문맥 안에서, 중요한 핵심 개념만 남기는 것

  • 이름 짓기

    • 단수와 복수 구분

      • 끝에 -(e)s를 붙여 데이터가 단수인지, 복수인지 구분

    • 이름 줄이지 않기

      • 자주 사용하는 줄임말이 이해될 수 있는 것은 문맥 때문

    • 은어/방언 사용하지 않기

      • 일부/현재 팀원만 아는 용어 금지

      • 도메인 용어 사전 정의

    • 좋은 코드 보고 습득

      • 비슷한 상황에서 자주 사용하는 단어, 개념 습득

  • 메서드와 추상화

    • 한 메서드의 주제는 반드시 하나다.

    • 생략할 정보와 의미를 부여하고 드러낼 정보를 구분

  • 메서드 선언

    • 메서드명

      • 추상화된 구체를 유추할 수 있는, 적절한 의미가 담긴 이름

      • 파라미터와 연결지어 더 풍부한 의미 전달 가능

    • 파라미터

      • 타입, 개수, 순서를 통해 의미를 전달

      • 외부 세계와 소통하는 창

    • 반환 타입

      • 메서드 시그니처에 납득이 가는, 적절한 타입의 반환값 돌려주기

      • void 대신 충분히 반환할 만한 값이 있는지 고민

  • 추상화 레벨

    • 하나의 세계 안에서는, 추상화 레벨이 동등해야 한다.

    • 추상화 레벨을 주변 코드와 동등하게 구성

  • 매직 넘버, 매직 스트링

    • 의미를 갖고 있으나, 상수로 추출되지 않은 숫자, 문자열 등

    • 상수 추출로 이름을 짓고, 의미를 부여함으로써 가독성 및 유지 보수성이 상승한다.

       


 

[섹션 3]

  • 뇌 메모리 작게 쓰기

    • 인지한다는 것 자체가 메모리를 사용하는 것

    • 추상화를 통해서 인지할 정보를 추려내기

  • Early Return

    • else문을 쓴다는 것은 이전 if문의 조건을 기억해야 하는 것

    • 메모리 작게 쓰기의 중요성을 생각하면 이전 조건 기억을 줄여야 한다.

    • 빠른 return문을 통해 이전 조건을 기억하지 않도록 하는 기법

  • 사고의 depth 줄이기

    • 중첩 분기문, 중첩 반복문

      • 메서드 분리로 1차원 반복문으로 구성할 수 있다.

      • 중첩 구조가 사고하는 데 도움이 된다면 메서드 분리할 필요가 없다.

    • 사용할 변수는 가깝게 선언하기

  • 공백 라인을 대하는 자세

    • 공백 라인도 의미를 가진다.

       

    • 복잡한 로직의 의미 단위를 나눔으로써, 읽는 사람에게 추가 정보 제공 가능

  • 부정어를 대하는 자세

    • 부정 연산자 코드는 가독성이 떨어지고, 생각하는 것 자체가 비효율적이다.

       

    • 메서드 네이밍에 부정의 의미를 담는 것이 생각하기 더 편하다.

    • 부정어구를 쓰지 않아도 되는 상황인지 체크

    • 부정의 의미를 담은 다른 단어가 존재하는지 고민 or 부정어구로 메서드명 구성

  • 해피 케이스와 예외 처리

    • 예외가 발생할 가능성 낮추기

    • 어떤 값의 검증이 필요한 부분은 주로 외부 세계와의 접점

      • 사용자 입력, 객체 생성자, 외부 서버의 요청 등

    • 의도한 예외와 예상하지 못한 예외를 구분하기

      • 사용자에게 보여줄 예외와 개발자가 보고, 처리해야 할 예외 구분

    • Null을 대하는 자세 (Optional에 관하여)

      • Optional은 비싼 객체이다. 꼭 필요한 상황에서 반환 타입을 사용한다.

      • Optional을 파라미터로 받지 않도록 한다. (분기 3가지)

        • Optional이 가진 데이터가 null인지 아닌지 + Optional 자체가 null인지

      • Optional을 반환받았다면 최대한 빠르게 해소

        • 분기문을 만드는 isPresent() - get() 대신 다른 API 사용

          • ex) orElseGet(), orElseThrow(), ifPresent(), ifPresentOrElse()

          • orElse() : 항상 실행, 확정된 값일 때 사용, 호출할 필요가 없을 도 실행

          • orElseGet() : null인 경우 실행, 값을 제공하는 동작 정의

          • orElseThrow() : null인 경우 실행, 예외 동작 정의


 

[섹션 4]

  • 추상의 관점으로 바라보는 객체 지향

    • 관심사의 분리, 높은 응집도, 낮은 결합

  • 객체 설계하기 (1)

    • 절차 지향에서 잘 보이지 않았던 개념을 가시화

    • 관심사가 한 군데로 모이기 때문에 유지보수성을 상승시킨다.

      • 객체 내부에서 객체가 가진 데이터의 유효성 검증 책임을 가질 수 있다.

    • 여러 객체를 사용하는 입장에서는 구체적인 구현에 신경쓰지 않고, 보다 높은 추상화 레벨에서 도메인 로직을 다룰 수 있다.

    • 새로운 객체를 만들 때, 주의할 점

      • 1개의 관심사로 명확하게 책임이 정의되어 있는지 확인하기

      • 생성자, 정적 팩토리 메서드에서 유효성 검증이 가능하다.

      • setter 사용 자제, 외부 세계 데이터로 변경해야 하는 경우, update~ 같이 의도를 드러내는 네이밍을 쓰자.

      • 필드의 수는 적을수록 좋다.

  • SRP : Single Responsibility Principle (단일 책임 원칙)

    • 하나의 클래스는 단 한 가지의 변경 이유만을 가져야 한다.

    • 객체가 가진 공개 메서드, 필드, 상수 등은 해당 객체의 단일 책임에 의해서만 변경 되는가?

    • 관심사의 분리

    • 높은 응집도, 낮은 결합도

  • OCP : Open-Closed Principle (개방 폐쇄 원칙)

    • 확장에는 열려 있고, 수정에는 닫혀 있어야 한다.

    • 추상화와 다형성을 활용해서 OCP를 지킬 수 있다.

  • LSP : Liskov Substitution Principle (리스코프 치환 원칙)

    • 상속 구조에서, 부모 클래스의 인스턴스를 자식 클래스의 인스턴스로 치환할 수 있어야 한다.

      • 자식 클래스는 부모 클래스의 책임을 준수하며, 부모 클래스의 행동을 변경하지 않아야 한다.

    • LSP를 위반하면, 상속 클래스를 사용할 떄 오동작, 예상 밖의 예외가 발생하거나, 이를 방지하기 위한 불필요한 타입 체크가 동반될 수 있다.

  • ISP : Interface Segregation Principle (인터페이스 분리 원칙)

    • 클라이언트는 자신이 사용하지 않는 인터페이스에 의존하면 안 된다.

    • ISP를 위반하면, 불필요한 의존성으로 인해 결합도가 높아지고, 특정 기능의 변경이 여러 클래스에 영향을 미칠 수 있다.

  • DIP : Dependency Inversion Principle (의존성 역전 원칙)

    • 상위 수준의 모듈은 하위 수준의 모듈에 의존해서는 안 된다. 둘 모두 추상화에 의존해야 한다.

    • 의존성의 순방향 : 고수준 모듈이 저수준 모듈을 참조하는 것

    • 의존성의 역방향 : 고수준, 저수준 모듈이 모두 추상화에 의존하는 것

       

    • 저수준 모듈이 변경되어도, 고수준 모듈에는 영향이 가지 않는다.

       

       



[섹션 5]

  • 상속과 조합

    • 상속은 시멘트처럼 굳어지는 구조, 수정이 어렵다.

    • 조합과 인터페이스를 활용하는 것이 유연한 구조

      • 상속을 통한 코드의 중복 제거가 주는 이점보다, 중복이 생기더라도 유연한 구조 설계가 주는 이점이 더 크다.

  • Value Object

    • 도메인의 어떤 개념을 추상화하여 표현한 값 객체

    • 값으로 취급하기 위해서, 불변셩, 동등성, 유효성 검증 등을 보장해야 한다.

      • 불변성 : final 필드 사용, setter 금지

      • 동등성 : 서로 다른 인스턴스여도 내부의 값이 같으면 같은 값 객체로 취급
        equals() & hashCode() 재정의 필요

      • 유효성 검증 : 객체가 생성되는 시점에 값에 대한 유효성을 보장하기

      • Value Object vs Entity

        • Entity는 식별자가 존재한다. 식별자가 아닌 필드의 값이 달라도, 식별자가 같으면 동등한 객체로 취급한다.

        • Value Object는 식별자 없이, 내부의 모든 값이 다 같아야 동등한 객체로 취급한다.

    • 일급 컬렉션

      • 컬렉션을 포장하면서, 컬렉션만을 유일하게 필드로 가지는 객체

      • 컬렉션을 추상화하며 의미를 담을 수 있고, 가공 로직의 보금자리가 생긴다.

      • 만약, getter로 컬렉션을 반환할 일이 생긴다면, 외부 조작을 피하기 위해 꼭 새로운 컬렉션으로 만들어서 반환, new 사용

    • Enum의 특성과 활용

      • Enum은 상수의 집합이며, 상수와 관련된 로직을 담을 수 있는 공간이다.

      • 특정 도메인 개념에 대해 그 종류와 기능을 명시적으로 표현해줄 수 있다.

      • 만약, 변경이 정말 잦은 개념은 Enum 보다 DB로 관리하는 것이 나을 수 있다.

    • 다형성 활용하기

      • 인터페이스 구현을 통하여 여러 개의 구현 클래스들을 인터페이스로 관리

    • 숨겨져 있는 도메인 개념 도출하기

      • 도메인 지식은 만드는 것이 아니라 발견하는 것

      • 객체 지향은 현실을 100% 반영하는 도구가 아니라, 흉내내는 것이다.

      • 설계할 때는 근식적, 거시적 관점에서 최대한 미래를 예측하고, 시간이 지나 만약 틀렸다는 것을 인지하면 언제든 돌아올 수 있도록 코드를 만들어야 한다.



[Day2 Mission]

https://taey-coding.tistory.com/75

 

[Day4 Mission]

https://taey-coding.tistory.com/77

댓글을 작성해보세요.


채널톡 아이콘