클린 코드 연습 - 파트 2

수년 동안 코드 리뷰에서 다른 사람들의 코드를 읽으면서 나는 나쁜 코드를 잡는 '눈'을 개발했고, 내가 설계한 시나리오를 읽으면 당신도 그것을 개발할 수 있다고 생각합니다.

다음 예제는 반드시 결함이 있는 코드는 아닙니다. 내 말은, 버그가 없고 작업을 수행하지만 가능한 한 유지 관리할 수 없다고 가정합니다. 각 예를 읽고 문제를 식별하고 문제를 해결하기 위해 무엇을 할 것인지 생각하십시오.

시나리오 4




const chemicalSymbols = {
  Sodium: "Na",
  Hydrogen: "H",
  Helium: "He",
  Oxigen: "O",
};

function getSymbol(name) {
  const symbol = chemicalSymbols[name];
  if (symbol) {
    return symbol;
  }

  console.log("symbol not found");
  return "not found";
}


뭐가 문제 야?



(위의 코드를 완료할 때까지 읽지 마십시오)

이 시나리오의 문제는 오류 처리가 부족하다는 것입니다. 화학 기호가 발견되지 않으면 기호가 발견되었는지 여부를 쉽게 결정할 수 없기 때문에 함수 호출자에게 도움이 되지 않는 문자열을 반환합니다. 이 메시지는 함수 체인을 통해 전파되어 원하지 않는 동작을 유발할 수 있습니다.

해결책



이 문제를 해결하는 방법은 더 나은 로그를 갖고 일반 반환 값과 다른 유형의 항목을 반환하는 것입니다. 예를 들어 문자열 대신 null입니다.

function getSymbol(name) {
  const symbol = chemicalSymbols[name];
  if (symbol) {
    return symbol;
  }
  console.log(`getSymbol:: symbol not found for ${name}`);
  return null;
}


그러나 훨씬 더 나은 대안은 오류를 발생시키는 것입니다. 이렇게 하면 문제가 있는 경우 오류가 전파를 방지하고 처리되지 않으면 프로그램이 중단됩니다. 항상 try/catch를 사용하여 오류를 처리할 수 있습니다.

function getSymbol(name) {
  const symbol = chemicalSymbols[name];
  if (symbol) {
    return symbol;
  }
  throw new Error(`symbol not found for ${name}`);
}


시나리오 5




function getDisplayImage(article, watermark) {
  let image
  if(article.image && article.displayImage) {
    if(watermark){
      image = applyWatermark(article.image, watermark)
    } else {
      image = article.image
    }
  } else {
    image = null
  }

  return image
}


뭐가 문제 야?



이 함수에는 if 문이 중첩된 세 가지 가능한 응답이 있습니다. 이는 코드를 더 복잡하고 유지 관리하기 어렵게 만들기 때문에 좋지 않은 습관입니다. 이 예는 비교적 이해하기 쉽지만 더 복잡한 방법에서는 그 뒤에 있는 논리를 이해하기가 정말 어려울 수 있습니다.

해결책



이 논리를 더 작고 이해하기 쉬운 덩어리로 나누는 유용한 패턴은 "조기 반환"입니다. 첫 번째if와 반환null의 역 비교를 즉시 수행할 수 있습니다. 그런 다음 기사 이미지를 더 이상 확인할 필요가 없으므로 다른 문을 중첩할 필요가 없습니다.

function getDisplayImage(article, watermark) {
  let image
  if(!article.image || !article.displayImage) {
    return null
  }
  if(watermark){
    return applyWatermark(article.image, watermark)
  }
  return image
}


시나리오 6




if (
  typeof AUTH_ENABLED === 'string' &&
  AUTH_ENABLED === 'true' &&
  !skipAuthentication &&
  user.email
) {
  console.info('Welcome back, ' + user.name);
}


뭐가 문제 야?



부울 비교가 너무 많습니다. 첫눈에 무슨 일이 일어나고 있는지 이해하기가 정말 어렵습니다. 이 블록의 무언가를 변경해야 하는 경우 버그를 도입하지 않고 변경하는 것이 매우 복잡할 것입니다.

해결책



명명된 부울을 사용하여 평가를 단순화할 수 있습니다. 의미 있는 이름을 가진 상수에 값을 할당하면 거의 일반 영어처럼 읽고 이해하기 쉬운 결과를 얻을 수 있습니다.

const authEnabled = typeof AUTH_ENABLED === 'string' && AUTH_ENABLED === 'true';
const authIsEnforced = authEnabled && !skipAuthentication;
const userLoggedIn = user && user.email;

if(authIsEnforced && userLoggedIn) {
  console.info('Welcome back, ' + user.name);
}


그리고 이것이 이 게시물의 마지막 연습이었습니다. 시리즈의 파트 1에 대한 연습을 검토할 수 있음을 기억하십시오.

좋은 웹페이지 즐겨찾기