profile image

L o a d i n g . . .

1. 함수 옮기기

좋은 소프트에워 설계의 핵심은 모듈화가 얼마나 잘 되어 있느냐를 뜻하는 모듈성 이다.
모듈성이란 프로그램의 어딘가를 수정하려고 할 때 해당 기능과 깊이 관련된 작은 일부만 이해해도 가능하게 해주는 능력이다.

보통 프로그램 이해도가 높아질수록 소프트웨어 요소들을 더 잘 묶는 새로운 방법을 깨우치게 된다. 그래서 높아진 이해를 반영하려면 요소들을 이리저리 옮겨야 할 수 있다.

객체 지향 프로그래밍의 핵심 모듈화 컨텍스트는 클래스다. 프로그래밍 언어들은 저마다의 모듈화 수단을 제공하며, 각각의 수단이 함수가 살아 숨 쉬는 컨텍스트를 만들어준다.

2. 필드 옮기기

class Customer {
    get plan() {return this._plan;}
    get discountRate() {return this._discountRate;}
}

--->
class Customer {
    get plan() {return this._plan;}
    get discountRate() {return this.plan.discountRate;}
}

현재 데이터 구조가 적절치 않음을 깨닫게 되면 곧바로 수정해야 한다.

예컨데 함수에 어떤 레코드를 넘길 때마다 또 다른 레코드의 필드도 함께 넘기고 있다면 데이터 위치를 옮겨야 한다. 함수에 항상 함께 건네지는 데이터 조각들은 상호 관계가 명확하게 드러나도록 한 레코드에 담는 게 가장 좋다.

변경 역시 주요한 요인이다. 한 레코드를 변경하려 할 때 다른 레코드의 필드까지 변경해야만 한다면 필드의 위치가 잘못되었다는 신호다. 구조체 여러 개에 정의된 똑같은 필드들을 갱신해야 한다면 한 번만 갱신해도 되는 다른 위치로 옮기라는 신호다.

3. 문장을 함수로 옮기기/ 4. 문장을 호출한 곳으로 옮기기

export function renderPerson(person) {
    const result = [];
    result.push(`<p>${person.name}</p>`);
    result.push(renderPhoto(person.photo));
    result.push(emitPhotoData(person.photo));
    return result.join("\n");
}


export function photoDiv(aPhoto) {
    return [
        "<div>",
        emitPhotoData(aPhoto),
        "</div>",
    ].join("\n");
}

function emitPhotoData(aPhoto) {
    return [`<p>title: ${aPhoto.title}</p>`,
        `<p>location: ${aPhoto.location}</p>`,
    `<p>date: ${aPhoto.date.toDateString()}</p>`].join("\n");

}

function renderPhoto(aPhoto) {
    return "";
}

중복 코드 제거는 가장 효과적인 코드 관리 방법 중 하나.

5. 인라인 코드를 함수 호출로 바꾸기

let appliesToMass = false;
for (const s of states) {
    if (s === "MA") appliesToMass = true;
}

함수는 여러 동작을 하나로 묶어준다. 함수의 이름이 코드의 ㅈ동작 방식보다는 목적을 말해주기 때문에 함수를 활용하면 코드를 이해하기가 쉬워진다. 함수는 중복을 없애는 데도 효과적이다. 똑같은 코드를 반복하는 대신 함수를 호출하면 된다.

6.1절과 이 것의 차이는 인라인 코드를 대체할 함수가 이미 존재하느냐의 여부다. 없어서 새로 만들어야 함녀 함수 추출하기를 적용하고, 이미 존재한다면 인라인 코드를 함수 호출로 바꾸기를 적용한다.

appliesToMass = states.includes("MA");

6. 문장 슬라이드 하기

관련된 코드를 가까이 모여두어야 이해하기 쉽다. 예컨대 하나의 데이터 구조를 이용하는 문장들은 한데 모여 있어야 좋다.

7. 반복문 쪼개기

종종 반복문 하나에서 두 일을 한꺼먼에 처리할수 있도록 두 가지 일을 수행한다.
하지만 이렇게 하면 반복문을 수정할 때마다 두가지 일 모두를 잘 이해하고 진행해야 한다. 각각의 반복문으로 분리하자.

리팩터링과 최적화는 구분하자.
최적화는 코드를 깔끔히 정리한 이후에 수행하자. 반복문을 두 번 실행하는 게 병목이라 밝혀지면 그 때 다시 하나로 합치기는 식은 죽 먹기다.

8. 반복문을 파이프라인으로 바꾸기

const names = [];
for (const i of input) {
    if (i.job === "programmer")
        names.push(i.name)
}

논리를 파이프라인으로 표현하면 이해하기 훨씬 쉬워진다. 객체가 파이프라인을 따라 흐르며 어떻게 처리되는지를 읽을 수 있기 때문이다.

const names = input
    .filter(i => i.job === "programmer")
    .map(i => i.name)
;

9. 죽은 코드 제거하기

코드는 항상 최소한으로 유지하라

혹시 다시 필요해질까 걱정할 필요없다. 우리에겐 버전 관리 시스템(git)이 있다!

복사했습니다!