[인프런 워밍업 클럽 BE 클린코드 & 테스트 스터디] 발자국 1주차
1주차 발자국 정리 [섹션 2]추상과 구체추상 : 중요한 정보는 가려서 남기고, 덜 중요한 정보는 생략추상으로부터 구체를 유추하지 못 하는 이유추상화 과정에서 중요 정보를 부각시키지 못함해석자가 동일하게 공유하는 문맥이 없음적절한 추상화는 도메인 문맥 안에서, 중요한 핵심 개념만 남기는 것이름 짓기단수와 복수 구분끝에 -(e)s를 붙여 데이터가 단수인지, 복수인지 구분이름 줄이지 않기자주 사용하는 줄임말이 이해될 수 있는 것은 문맥 때문은어/방언 사용하지 않기일부/현재 팀원만 아는 용어 금지도메인 용어 사전 정의좋은 코드 보고 습득비슷한 상황에서 자주 사용하는 단어, 개념 습득메서드와 추상화한 메서드의 주제는 반드시 하나다.생략할 정보와 의미를 부여하고 드러낼 정보를 구분메서드 선언메서드명추상화된 구체를 유추할 수 있는, 적절한 의미가 담긴 이름파라미터와 연결지어 더 풍부한 의미 전달 가능파라미터타입, 개수, 순서를 통해 의미를 전달외부 세계와 소통하는 창반환 타입메서드 시그니처에 납득이 가는, 적절한 타입의 반환값 돌려주기void 대신 충분히 반환할 만한 값이 있는지 고민추상화 레벨하나의 세계 안에서는, 추상화 레벨이 동등해야 한다.추상화 레벨을 주변 코드와 동등하게 구성매직 넘버, 매직 스트링의미를 갖고 있으나, 상수로 추출되지 않은 숫자, 문자열 등상수 추출로 이름을 짓고, 의미를 부여함으로써 가독성 및 유지 보수성이 상승한다. [섹션 3]뇌 메모리 작게 쓰기인지한다는 것 자체가 메모리를 사용하는 것추상화를 통해서 인지할 정보를 추려내기Early Returnelse문을 쓴다는 것은 이전 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 EntityEntity는 식별자가 존재한다. 식별자가 아닌 필드의 값이 달라도, 식별자가 같으면 동등한 객체로 취급한다.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