6.10 여러 함수를 변환 함수로 묶기 배경 정보가 사용되는 곳마다 같은 도출 로직이 반복되는 경우 → 검색과 갱신을 한 곳에서 처리할 수 있고 로직 중복을 막을 수 있음 변환 함수: 원본 데이터를 입력받아서 필요한 정보를 도출한 뒤, 각각을 출력 데이터의 필드에 넣어 반환 - 도출 과정을 검토할 일이 생긴 경우 변환 함수만 확인하면 됨 원본 데이터가 코드 안에서 갱신될 때는 여러 함수를 클래스로 묶기(6.9) 변환 함수는 가공한 데이터를 새로운 레코드에 저장하여 원본 데이터가 수정되면 일관성이 깨질 수 있음 절차 1. 변환할 레코드를 입력받아서 값을 그대로 반환하는 변환 함수 만들기 - 깊은 복사로 처리. 변환 함수가 원본 레코드를 바꾸지 않는지 검사하는 테스트 만들기 2. 묶을 함수 중 함수 하나를 ..
[REFACTORING] 6.9 여러 함수 클래스로 묶기 배경 함수 호출 시 인수로 전달되는 공통 데이터를 중심으로 함수들을 묶어 클래스로 만들기 - 함수들이 공유하는 공통환경을 더 명확히 표현 - 함수에 전달되는 인수를 줄여 함수 호출을 간결하게 만들 수 있음 장점 - 클라이언트가 객체의 핵심 데이터를 변경할 수 있음 - 파행 객체들을 일관되게 관리할 수 있음 최상위 함수로 두면 못 보고 지나칠 수 있음 중첩 함수로 두면 테스트하기 까다로움 절차 1. 함수들이 공유하는 공통 데이터 레코드를 캡슐화(7.1)한다. - 공통 데이터가 레코드 구조로 묶여 있지 않다면 매개변수 객체 만들기(6.8)부터 진행 2. 공통 레코드를 사용하는 함수 각각을 새 클래스로 옮긴다(함수 옮기기(8.1)). - 공통 레코드의 ..
6.8 매개변수 객체 만들기 배경 동일한 다수의 인수를 받는 함수가 여럿인 경우 인수들을 묶어주는 작업 데이터들을 데이터 구조로 묶으면 데이터 사이의 관계가 명확해지고 함수가 받는 매개변수 수가 줄어들며 같은 데이터 구조를 사용하는 모든 함수가 항상 똑같은 이름을 사용하기 때문에 일관성을 높여줌 이 리팩터링을 통해 코드를 근본적으로 바꿔줄 수 있음 - 매개변수 객체 만들기를 진행한 후 데이터 구조에 담길 데이터에 공통으로 적용되는 동작을 추출해서 함수로 만들기 공용 함수를 나열하거나 함수들과 데이터를 합쳐 클래스로 만들기 → 문제 영역을 훨씬 간결하게 표현하는 새로운 추상 개념으로 격상되면서 코드의 개념적인 그림을 다시 그릴 수 있음 절차 1. 적당한 데이터 구조가 아직 마련되어 있지 않다면 새로 만든다..
6.7 변수 이름 바꾸기 배경 명확한 프로그래밍의 핵심: 이름 짓기 → 코드의 의도를 설명해 줌 절차 1. 폭넓게 쓰이는 변수라면 변수 캡슐화하기(6.6)을 고려한다. 2. 이름을 바꿀 변수를 참조하는 곳을 모두 찾아서 하나씩 변경한다. - 다른 코드베이스에서 참조하는 변수는 외부에 공개된 변수이므로 이 리팩터링을 적용할 수 없다. - 변수 값이 변하지 않는다면 다른 이름으로 복제본을 만들어서 하나씩 점진적으로 변경한다. 하나씩 바꿀 때마다 테스트한다. const cpyNm = "티스토리" // 변수명을 바꾸고 cpyNm -> companyName const companyName = "티스토리" // 새 변수를 기존 변수명으로 만들어 참조하게 만든 후 점진적으로 변경 const cpyNm = compan..
0.0 변수 캡슐화하기 배경 함수는 전달 함수 방식을 이용하면 돼서 데이터보다 다루기 수월함 - 전달 함수: 기존 함수를 없애지 않고 기존 함수가 새로 만든 호출하는 방식 데이터는 참조하는 모든 부분을 바꿔주어야 함 유효 범위가 넓어질수록 다루기 어려워짐(전역 데이터) → 접근할 수 있는 범위가 넓은 데이터를 옮길 때는 그 데이터의 접근을 독점하는 함수를 만드는 식으로 캡슐화 데이터 재구성이라는 어려운 작업을 함수 재구성이라는 단순한 작업으로 변환 데이터 캡슐화는 데이터를 변경하고 사용하는 코드를 감시할 수 있는 수단이 되어 변경 전 검증이나 변경 후 추가 로직을 쉽게 더할 수 있음 변수를 참조하는 코드를 캡슐화하면 자주 사용하는 데이터에 대한 결합도를 낮출 수 있음 = 객체 지향에서 객체의 데이터를 p..
6.5 함수 선언 바꾸기 = 함수 이름 바꾸기 배경 함수 - 프로그램을 작은 부분으로 나누는 수단 - 시스템의 구성 요소를 조립하는 연결부 역할 이름만으로 본문 코드가 무슨 일을 하는지 알 수 있도록 함수 이름을 지어야 함(주석을 참고하여 네이밍해보기) → 한 번에 적절한 이름을 짓기 어려움, 더 나은 이름이 떠올랐을 때 변경할 것 매개변수 - 전화번호 포매팅 함수의 매개변수가 사람인 경우 매개변수를 전화번호로 바꿔 결합을 제거해 줌 - 마감일을 넘겼는지 확인해주는 함수의 매개변수로 인터페이스를 받으면 여러 정보를 받을 필요가 없음, 대여일을 받는다면 추가 정보가 필요함 → 결합을 제거하는 것이 항상 옳은 것이 아니라 때에 따라 적절히 사용해야 함 절차 ① 간단한 절차 함수 선언과 호출문들을 단번에 고칠..
6.3 변수 추출하기 ↔ 변수 인라인하기(6.4) 배경 표현식이 너무 복잡해서 이해하기 어려운 경우 지역 변수를 활용하여 표현식 쪼개기 변수 이름을 통해 코드의 목적을 명확하게 드러낼 수 있음 디버거에 중단점을 지정하거나 상태를 출력하는 문장을 추가할 수 있어 디버깅에도 도움이 됨 현재 함수 안에서만 의미가 있다면 변수로 추출, 함수를 벗어나 넓은 문맥에서 의미가 있다면 함수로 추출 절차 1. 추출하려는 표현식에 부작용은 없는지 확인한다. 2. 불변 변수를 하나 선언하고 이름을 붙일 표현식의 복제본을 대입한다. 3. 원본 표현식을 새로 만든 변수로 교체한다. 4. 테스트한다. 5. 표현식을 사용하는 곳을 찾아 하나씩 변수로 교체하면서 테스트한다. 6.4 변수 인라인하기 ↔ 변수 추출하기(6.3) 배경 -..
6.2 함수 인라인하기 ↔ 함수 추출하기(6.1) 배경 목적이 분명히 드러나는 이름을 가진 짧은 함수를 사용해야 코드가 명료해지고 이해하기 쉬워짐 그러나 함수 본문이 이름만큼 명확하다면 인라인한다. - 리팩터링 과정에서 잘못 추출한 함수 - 간접 호출을 너무 과하게 쓰는 함수(단순 위임만을 위한 함수가 너무 많아 위임 관계가 복잡하게 얽혀있는 경우) 절차 1. 다형 메서드(polymorphic method)인지 확인한다. - 서브 클래스에서 오버라이드하는 메서드는 인라인하면 안 된다. 2. 인라인할 함수를 호출하는 곳을 모드 찾는다. 3. 각 호출문을 함수 본문으로 교체한다. 4. 하나씩 교체할 때마다 테스트한다. - 인라인 작업을 한 번에 처리할 필요 없음. 인라인하기 까다로운 부분이 있다면 남겨두고 ..
함수 추출하기(6.1) ↔ 함수 인라인하기(6.2) 변수 추출하기(6.3) ↔ 변수 인라인하기(6.4) 함수 선언 바꾸기(6.5) - 함수 이름 변경 변수 이름 바꾸기(6.7) - 변수 이름 변경 매개변수 객체 만들기(6.8) - 자주 함께 사용되는 인수들 묶기 추출은 결국 이름 짓기이며 함수 구성과 이름 짓기는 가장 기본적인 저수준 리팩터링 여러 함수를 클래스로 묶기(6.9) - 함수를 그룹으로 묶기 여러 함수를 변환 함수로 묶기(6.10) - 읽기 전용 데이터 다루기 단계 쪼개기(6.11) 묶은 모듈들의 작업 처리 과정을 명확한 단계로 구분 짓기 6.1 함수 추출하기 ↔ 함수 인라인하기(6.2) 배경 코드가 무슨 일을 하는지 파악한 다음 독립된 함수로 추출하고 목적에 맞는 이름 붙이기 독립된 함수로 ..
테스트 작성 - 개발 효율을 높여줌 - 리팩터링 시 불가피하게 저지르는 실수를 잡아줌 4.1 자가 테스트 코드의 가치 실제 코드를 작성하고, 버그를 수정하는 것보다 현재 상황 파악, 설계 고민, 버그 찾기 시간을 많이 씀 버그를 해결하는 과정에서 또 다른 버그를 만들기도 하고, 이 버그를 찾느라 시간을 보냄 모든 테스트를 완전히 자동화하고 그 결과까지 스스로 검사하게 만들자 테스트를 작성하려면 소프트웨어를 위한 코드 외에 부가적인 코드를 상댱량 작성해야 하기 때문에 이렇게 개발하기 어렵지만, 테스트를 작성하고 자주 실행하면 추가된 코드 양이 많지 않아 버그 발생 지점을 찾기 쉬워져 프로그래밍 속도를 높여줌 테스트를 작성하기 좋은 시점은 프로그래밍을 시작하기 전. 원하는 기능을 위해 무엇이 필요한지 고민하..
