Clean Code
Java 리팩토링 - 상속을 위임으로 바꾸기 (Replace Inherit with Delegate)
1. 알고자 하는 것 객체지향에서 상속은 기존 기능을 재사용할 수 있는 강력한 기능을 제공한다. 하지만 상속에도 단점이 존재하며, 상속이 적절치 않은 경우가 존재한다. 이럴 때 상속을 위임(Delegate) 으로 바꾸어 해결할 수 있다. 상속을 위임으로 바꾸기 (Replace Inherit with Delegate) 2. 알게 된 것 상속은 상위 클래스의 기능을 하위 클래스가 재사용 할 수 있는 좋은 방법이다. 상속으로 불필요한 코드의 중복을 막을 수 있고, 공통 기능의 변경 시 변경점이 줄어든다. 하지만 이러한 상속이 적절하지 않은 경우가 존재한다. 상속 받는 하위 클래스의 경우 상위 클래스의 모든 기능을 지원해야 한다. 자바의 Stack 클래스의 경우, Vector를 상속 받는다. 상위 클래스인 Ve..
Java 리팩토링 - 특이 케이스 추가하기 (Introduce Special Case)
1. 알고자 하는 것 여러 메서드에서 특정 데이터를 기준으로 계속 로직이 분기된다면, 이를 아예 클래스로 분리해 코드의 길이를 대폭 줄일 수 있다. 그리고 그 중심에는 다형성이 있다. 무궁무진한 다형성의 활용도를 익히기 위해 더 열심히 공부해야겠다는 괜한 동기부여가 되는 주제인 것 같다. 특이 케이스 추가하기 (Introduce Special Case) 2. 알게 된 것 위에서 말한 "특정 데이터를 기준으로 계속 로직이 분기" 되는 상황을 특이 케이스 (Special Case)라고 정의할 수 있다. 가령, 다음과 같은 형식이다. public class Customer { private String name; private BillingPlan billingPlan; private PaymentHistor..
Java 리팩토링 - 기본형을 객체로 바꾸기 (Replace Primitive with Object)
1. 알고자 하는 것 기본은 중요하다. 하지만 코드에서 기본형(Primitive Type)은 언제나 좋지만은 않다. 필요한 기능들이 많아지면 기본형만으로는 부족한 때가 온다. 기본형만으로는 버거울 때, 어떻게 해야할까 기본형을 객체로 바꾸기 (Replace Primitive with Object) 2. 알게 된 것 특정 데이터는 초기의 개발에는 기본형(Primitive Type) 만으로 충분히 표현 가능할 수 있다. 하지만 기능이 변경되고 추가됨에 따라, 이러한 데이터를 기반으로 수행해야 하는 기능이 추가될 수 있다. (ex. type에 올바른 값이 들어오는지 validation / type의 우선순위 비교) 이 경우 기본형을 그대로 사용해 추가된 기능을 구현할 수 있지만, 코드가 직관적이지 못하고 기본..
Java 리팩토링 - 함수 인라인, 클래스 인라인 (Function Inline, Class Inline)
1. 알고자 하는 것 이전에 함수 추출하기(Extract Method) 글을 통해 코드의 내용에 직관적인 이름을 붙여 가독성을 높일 수 있다고 학습한 적이 있었다. 이러한 추출하기 기법은 함수 뿐 아니라 클래스 단위로도 가능하며, 마찬가지로 클래스로 코드의 내용을 추출해 직관적으로 코드의 가독성을 높이고 응집도를 높일 수 있다. 하지만 함수/클래스 추출하기와 반대로, 때로는 함수/클래스로 추출했던 코드를 다시 본문 코드에 옮겨넣는 것이 코드의 가독성을 높일 수 있는 상황이 있다. 이러한 리팩토링 방법을 함수/클래스 인라인 (Function / Class Inline) 이라고 한다. 함수 인라인 (Function Inline) 클래스 인라인 (Class Inline) 2. 알게 된 것 함수/클래스 추출하기..
Java 리팩토링 - 함수 옮기기 (Move Function)
1. 알고자 하는 것 프로그램을 작성할 때 모듈화가 잘 된 소프트웨어는 최소한의 지식만으로 프로그램을 변경할 수 있다. 즉, A 도메인의 기능을 변경하기 위해 최소한의 코드만을 살펴볼 수 있도록 되어 있다면 모듈화가 잘 되어있는 것이다. 반대로, A 도메인의 기능을 변경하기 위해 여러 클래스, 여러 코드를 봐야 이해할 수 있다면 모듈화가 잘 되어있지 않은 것이다. 비슷한 문맥의 코드가 응집되어 있지 않고 여러 곳에 흩어져 있고 (응집도가 낮음), 불필요하게 여러 문맥 간 서로 의존하고 있어 하나의 변경점에 대해서 의존성이 묶여있는 여러 코드가 함께 변경되어야 한다면 (의존성 높음) 모듈화가 잘 되어있지 않은 것이다. 높은 모듈화를 통해 하나의 변경사항에 대해 최소한의 코드 파악과 최소한의 코드 수정으로 ..
Java 리팩토링 - 변수 캡슐화하기 (with. Getter/Setter)
1. 알고자 하는 것 자바를 통해 개발을 하면서 클래스 내 필드를 변경하거나 가져올 때 주로 Getter, Setter를 많이 사용한다. Getter, Setter를 통해 필드를 캡슐화 함으로써 다양한 곳에서의 추적 불가능한 값의 변경을 막기 위해 사용하는 정도로만 이해하고 있었다면 이 내용을 통해 한 단계 더 깊게 알아보자. 변수 캡슐화하기 (Encapsulate Variable) 2. 알게 된 것 클래스 내 가지고 있는 변수는 말 그대로 상황에 따라 변경 되는 값이다. 특정 조건에 따라서 필드값이 변경되어야 하는 등의 상황이 그 예시에 속한다. 그 변수는 클래스 내 인스턴스 변수일 수도 있고, 클래스 변수일 수도 있다. 이 때, 단순히 변수를 public으로 열어두고 모든 곳에서 변경이 쉽게 가능하게..
Java 리팩토링 - 플래그 인수 제거하기
1. 알고자 하는 것 회사에서 코드를 작성할 때, Flag 변수를 생각보다 많이 사용했다는 것을 이번 강의를 보고 느끼게 되었다. 단순히 private 메서드 개수를 줄이기 위해 / 공통 메서드로 묶기 위해 Flag 변수를 두어 메서드 하나에서 로직을 분기했었다. 내 딴에서는 공통로직의 재사용이라는 리팩토링 명목으로 사용한 Flag 변수였지만, 이번 강의를 통해 '단순히 라인 수를 줄이는 것이 리팩토링이 아니다' 라는 의미를 한번 더 깨닫게 된 것 같다. 리팩토링은 '짧은 코드를 만드는 것'이 목적이 아니라 '의도를 명확히 / 가독성을 좋게' 하는 것이 목적임을 늘 상기하자! 플래그 인수 제거하기 2. 알게된 것 boolean, enum 타입과 같은 Flag 변수를 통해 함수 내부의 로직을 분기하는 경우..
Java 리팩토링 - 조건문을 다형성으로 바꾸기
1. 알고자 하는 것 조건문을 다형성으로 바꾸기 (Replace Conditional with PolyMorphism) 2. 알게된 것 여러 타입에 따라 각각 다른 로직으로 처리해야 하는 경우, 일반적으로 중첩 if문으로 분기하거나, switch-case 문으로 분기하곤 한다. // if문 분기 if (Type.A) { A_Logic(); } else if (Type.B) { B_Logic(); } else { C_Logic(); } // switch문 분기 switch(Type) { case A -> { A_Logic(); } case B -> { B_Logic(); } case C -> { C_Logic(); } } 하지만, 만약 타입 간 공통으로 사용되는 로직이 많고, 타입에 따라 일부분의 로직만 ..
Java 리팩토링 - 조건문 분해하기
1. 알고자 하는 것 이전 Java 리팩토링 강의 내용 모두 유익하다고 생각했지만, 유독 이 내용은 간단해보이면서도 실무에서 정말 많이 적용 가능한 리팩토링 기법이라고 생각한다. 실제로 코드리뷰 때에도 해당 부분에 대해서 얘기를 많이 했고, 대체로 누군가 짠 코드를 처음 보는 입장이라고 생각해보았을 때, 조건문을 분해(or 추출)했을 때의 가독성이 정말 높아진다고 생각한다. 내가 짠 코드를 처음 보는 사람이 쉽게 이해할 수 있는 코드를 짜는 데에 좋은 첫 걸음이 될만한 부분이라고 생각한다. 항상 좋은 코드, 읽기 쉬운 코드를 짜도록 노력하는 습관을 들이자. 조건문 분해하기 2. 알게된 것 프로그램에는 언제나 조건이 있다. if-else로 분기되는 조건문은 단순한 조건인 경우에는 이해하기 쉽다. 또한,..
Java 리팩토링 - 함수를 명령(Command)으로 바꾸기
1. 알고자 하는 것 함수를 명령으로 바꾸기 2. 알게된 것 함수를 명령으로 바꾸기 기본적으로 코드가 길어지고 이로 인해 가독성이 떨어진다면, 함수 추출(Extract Method)을 수행해 가독성을 높이고 복잡도를 낮출 수 있다. 함수 추출(Extract Method)을 수행해도 코드의 위치가 해당 위치가 아니라고 생각될 때 함수를 명령으로 바꾸는(Replace Function with Command) 방법을 고려한다. 해당 위치가 아니라고 생각된다 = 클래스의 맥락에서 해당 함수가 별도의 위치로 분리될 필요가 있다. 함수를 독립적인 객체(=Command)로 분리한다. try (FileWriter fileWriter = new FileWriter("participants.md"); PrintWriter..