항상 코드를 재사용할 수 있는 것은 아니다. 다른 개발자가 구현한 해결책이 자신의 사례에 맞지 않는 가정을 하거나, 그 해결책이 자신에게는 필요 없는 다른 기능과 함께 구성된 경우가 있을 수 있기 때문이다. 따라서 이러한 점을 적극적으로 고려해 향후에 재사용이 가능하도록 의도적으로 코드를 작성하고 구조화하는 것이 바람직하다.
가정으로 인해 코드가 취약해지고 활용도가 낮아져 재사용하기에 안전하지 않을 수 있다. 코드의 어느 부분에서 어떤 가정이 이루어졌는지 정확히 추적하는 것은 어렵기 때문에 다른 개발자들이 주의하지 않으면 빠질 수 있는 기분 나쁜 함정이 될 수 있다.
Article
클래스 내부의 getAllImages()
함수는 기사에 이미지가 포함된 섹션을 찾을 때까지 여러 섹션을 확인하며 해당 섹션의 이미지를 반환한다.
하지만 개발자는 이 함수를 이미지가 포함된 섹션이 하나만 있을거라 가정해 이미지를 포함하는 섹션을 발견하자마자 해당 섹션의 이미지를 반환하고 종료하도록 코드를 작성했다.
그럼 이 함수를 호출하는 쪽에서 이러한 가정을 알 수가 없다는게 가장 큰 문제이다.
즉, getAllImages()
함수는 기사의 모든 이미지를 반환하지 않는다는 사실을 어떻게 해결할 수 있을까?
이미지 섹션이 하나만 있다는 가정은 가치가 없을 수도 있다.
📌 섣부른 최적화
대부분의 경우에는 최적화를 하느라고 애쓰기보다는 코드를 읽기 쉽고 유지보수 가능하며, 견고하게 만드는 데에 집중하는 것이 좋다.
여러 이미지 섹션으로된 기사를 지원하지 않도록 하면 가정을 강제적으로 할 수 있다.
const getOnlyImageSection = (sections) => {
const imageSections = sections.filter((section) => isContainImages(section));
if(imageSections.length > 1) {
return;
}
// imageSections 배열에서 첫 번째 섹션의 이미지 반환
}
가정이 필요하다면 다른 개발자가 그 가정으로 인해 오류에 빠지지 않도록 최선을 다해야 한다.
기본값을 제공하려면 두 가지 가정이 필요하다.
- 어떤 기본값이 합리적인지
- 더 상위 계층의 코드는 기본값을 받든지 명시적으로 설정된 값을 받든지 상관하지 않는다.
낮은 수준에서의 코드는 여러 곳에서 광범위하게 재사용되므로 낮은 층위의 코드의 기본값 반환은 재사용성을 해칠 수 있다. 기본값을 정의하는 코드의 계층이 낮을수록 그 가정이 적용되는 상위 계층은 더 많아지기 때문이다.
이 부분을 읽고 합성
키워드가 생각났다.
프론트엔드 관점에서는 합성
을 이용해 상위에서 하위 컴포넌트를 더 유연하게 사용할 수 있을 것이다.
interface ButtonProps {
label?: string;
// ...
}
const Button = ({ label = 'button', ... }: ButtonProps) => {
return <button>{label}</button>
}
대신 상위 컴포넌트에서 하위로 의존성을 주입해 구현 세부 정보를 재설정하도록 작성하면 재사용성과 적응성이 보장된다.
const Button = ({ ... }: PropsWithChildren<ButtonProps>) => {
return <button>{children}</button>
}
어떤 기본값을 사용할지에 대한 결정을 호출하는 쪽에서 하도록 하면 코드의 재사용성이 향상된다.
일반적으로 함수가 필요한 것만 받도록 하면 코드는 재사용성이 향상되고 이해하기도 쉬워진다.
setTextColor()
는 텍스트의 색상만 변경하고 나머지 스타일 정보는 그대로 유지하는 함수이다.
만약 이 함수의 매개변수로 텍스트의 모든 스타일 정보를 넘긴다면(TextOptions 인스턴스) 텍스트의 색상만 변경하지 않는 것처럼 보일 수 있다.
따라서 인스턴스를 매개변수로 넘기는 것은 불필요하며 함수는 필요한 것만 매개변수로 받는 것이 바람직하다.
제네릭을 사용하면 코드를 일반화하는 것이 아주 쉽다.
하드 코딩으로 string 타입을 지정하면 일반화를 제한한다. 제네릭을 사용하면 타입을 구체적으로 명시할 필요가 없다.
function saveDocument(content: string) {}
function saveDocument<T>(content: T) {}
saveDocument('대충 글');
saveDocument(image);
saveDocument(video);
이렇게 제네릭을 사용하면 어떤 것이든 문서에 저장할 수 있게 된다.