CleanCode TIL (2022.02.12)

Henry Choยท2022๋…„ 2์›” 12์ผ
0

๋…ธ๊ฐœ๋ถ

๋ชฉ๋ก ๋ณด๊ธฐ
19/31

DAY 21

๐Ÿ”–ย ์˜ค๋Š˜ ์ฝ์€ ๋ฒ”์œ„ : Final mission


๐Ÿค“ย ์ฑ…์—์„œ ๊ธฐ์–ตํ•˜๊ณ  ์‹ถ์€ ๋‚ด์šฉ

Final mission์„ ์œ„ํ•œ ์ด์ •๋ฆฌ

  • ์šฐ๋ฆฌ๋Š” ์ฝ”๋“œ์˜ ์ €์ž๋‹ค. ๋…์ž์™€ ์ž˜ ์†Œํ†ตํ•  ์ˆ˜ ์žˆ๋Š” ๊นจ๋—ํ•œ ์ฝ”๋“œ๋ฅผ ์“ธ ์ฑ…์ž„์ด ์žˆ๋‹ค
  • ์ฝ”๋“œ๋ฅผ ์ฝ๊ธฐ ์‰ฝ๊ฒŒ ๋งŒ๋“ค๋ฉด ์งœ๊ธฐ๋„ ์‰ฝ๋‹ค
  • ์ค‘๋ณต ์ค„์ด๊ธฐ, ํ‘œํ˜„๋ ฅ ๋†’์ด๊ธฐ, ์ดˆ๋ฐ˜๋ถ€ํ„ฐ ๊ฐ„๋‹จํ•œ ์ถ”์ƒํ™” ๊ณ ๋ คํ•˜๊ธฐ โ†’ ์ง„์งœ ๋ฌธ์ œ์— ์‹ ๊ฒฝ ์“ธ ์—ฌ์œ  ์ƒ๊น€
  • ์ข‹์€ ์ด๋ฆ„์„ ์ง€์œผ๋ ค๋ฉด ์‹œ๊ฐ„์ด ๊ฑธ๋ฆฌ์ง€๋งŒ ์ข‹์€ ์ด๋ฆ„์œผ๋กœ ์ ˆ์•ฝํ•˜๋Š” ์‹œ๊ฐ„์ด ํ›จ์”ฌ ๋” ๋งŽ๋‹ค.
  • ๋ณ€์ˆ˜๊ฐ€ ๊ธธ๋ฉด ์˜คํžˆ๋ ค ๊ฒ€์ƒ‰ํ•˜๊ธฐ ์‰ฝ๋‹ค.
  • ๋ฐœ์Œํ•˜๊ธฐ ์‰ฌ์šด ์ด๋ฆ„์„ ์‚ฌ์šฉํ•˜๋ผ โ†’ ์  ์•ผ๋ฌด๋‹คํž˜์ฆˆ ๊ธˆ์ง€
  • ์˜ˆ์œ์ด๋ฆ„์€ ์‚ฌ๋žŒ์—๊ฒŒ ํด๋ž˜์Šค๋Š” ์ปดํŒŒ์ผ๋Ÿฌ์—๊ฒŒ
  • ์ถ”์ƒ์ ์ธ ๊ฐœ๋… ํ•˜๋‚˜์—๋Š” ์ผ๊ด€๋œ ๋‹จ์–ด๋ฅผ ์„ ํƒํ•ด ๊ณ ์ˆ˜ํ•˜๋ผ
  • IDE์˜ ์ž๋™์™„์„ฑ์„ ์ƒ๊ฐํ•ด์„œ๋ผ๋„ ๋ถˆํ•„์š”ํ•œ ์ ‘๋‘์‚ฌ ๋‹ค ๋ถ™์ด์ง€๋ง์ž
  • ํ•จ์ˆ˜์—์„œ ๋“ค์—ฌ์“ฐ๊ธฐ ์ˆ˜์ค€์€ 1๋‹จ์ด๋‚˜ 2๋‹จ์„ ๋„˜์–ด์„œ๋ฉด ์•ˆ๋œ๋‹ค.
  • ํ•œ๊ฐ€์ง€(์ง€์ •๋œ ํ•จ์ˆ˜ ์ด๋ฆ„ ์•„๋ž˜์—์„œ ์ถ”์ƒํ™” ์ˆ˜์ค€์ด ํ•˜๋‚˜์ธ ๋‹จ๊ณ„๋งŒ ์ˆ˜ํ–‰) ๋งŒ ํ•ด๋ผ
  • ํ•จ์ˆ˜ ์ธ์ˆ˜๋Š” ์ ์„ ์ˆ˜๋ก ์ข‹๋‹ค.
  • ๋ถ€์ˆ˜ ํšจ๊ณผ๋ฅผ ์ผ์œผํ‚ค์ง€ ๋งˆ๋ผ!
  • ๋ช…๋ น๊ณผ ์กฐํšŒ๋ฅผ ๋ถ„๋ฆฌํ•˜๋ผ!
  • ์˜ค๋ฅ˜ ์ฝ”๋“œ๋ณด๋‹ค ์˜ˆ์™ธ๋ฅผ ์‚ฌ์šฉํ•˜๋ผ!
  • 500์ค„์„ ๋„˜์ง€์•Š๋Š” ํ‰๊ท  200์ค„์˜ ํŒŒ์ผ๋กœ๋„ ์ปค๋‹ค๋ž€ ์‹œ์Šคํ…œ์„ ๊ตฌ์ถ•ํ•  ์ˆ˜ ์žˆ๋‹ค
  • ์‹ ๋ฌธ ๊ธฐ์‚ฌ์ฒ˜๋Ÿผ ์ž‘์„ฑํ•˜๋ผ: ์ถ”์ƒํ™” โ†’ ์„ธ๋ถ€์ , ์œ ์‚ฌ๊ฐœ๋…์€ ๊ฐ€๊นŒ์ด
  • ๊ฐ์ฒด๋Š” ์ƒˆ ํƒ€์ž…์„ ์ถ”๊ฐ€ํ•˜๊ธฐ๋Š” ์‰ฝ์ง€๋งŒ ์ƒˆ ๋™์ž‘์„ ์ถ”๊ฐ€ํ•˜๊ธฐ๋Š” ์–ด๋ ต๋‹ค
  • ์ž๋ฃŒ ๊ตฌ์กฐ๋Š” ์ƒˆ ํƒ€์ž…์„ ์ถ”๊ฐ€ํ•˜๋Š”๊ฑด ์–ด๋ ต์ง€๋งŒ ์ƒˆ ๋™์ž‘์„ ์ถ”๊ฐ€ํ•˜๊ธฐ๋Š” ์‰ฝ๋‹ค
  • ์šฐ์ˆ˜ํ•œ ๊ฐœ๋ฐœ์ž๋Š” ๋ฌด์กฐ๊ฑด ๊ฐ์ฒด์ง€ํ–ฅ์ด ์•„๋‹ˆ๋ผ ๊ฒฝ์šฐ์— ๋”ฐ๋ผ์„œ๋Š” ์ ˆ์ฐจ์ง€ํ–ฅ์˜ ์ž๋ฃŒ๊ตฌ์กฐ๋„ ์ž˜ ์“ด๋‹ค
  • ์˜ค๋ฅ˜๋ณด๋‹ค (๋ฏธํ™•์ธ)์˜ˆ์™ธ๋ฅผ ํ™œ์šฉํ•˜๋ผ
  • ์˜ˆ์™ธ๋ฅผ ์ผ์œผํ‚ค๋Š” try-catch ๋จผ์ € ์™„์„ฑ ์‹œํ‚ค๊ณ  ๋กœ์ง์„ ์ถ”๊ฐ€ํ•˜์ž
  • Error wrapper class ๋ฅผ ํ™œ์šฉํ•ด์„œ ์˜์กด์„ฑ์„ ์ค„์ด์ž
  • ํŠน์ˆ˜์ƒํ™ฉ์„ ๊ธฐ๋ณธ ๊ฐ’์œผ๋กœ ๋ฆฌํ„ดํ•จ์œผ๋กœ์„œ ๋ถˆํ•„์š”ํ•œ ์—๋Ÿฌ ์ฒ˜๋ฆฌ(์ค‘๋‹จ)๋ฅผ ์ œ๊ฑฐ
  • NULL์„ ๋ฐ˜ํ™˜ํ•˜์ง€ ๋ง๊ณ  ์˜ˆ์™ธ๋‚˜ ํŠน์ˆ˜ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜
  • ๋ฉ”์„œ๋“œ๋กœ NULL์„ ์ „๋‹ฌํ•˜์ง€ ๋ง๊ณ  ์ƒˆ๋กœ์šด ์˜ˆ์™ธ๋ฅผ ๋˜์ง€๊ฑฐ๋‚˜ assert๋ฌธ ํ™œ์šฉ
  • ์ž๋™ํ™”๋œ ๋‹จ์œ„ ํ…Œ์ŠคํŠธ ์ŠˆํŠธ๋Š” ๋ณ€๊ฒฝ์ด ์‰ฌ์›Œ์ง€๊ฒŒ ํ•จ โ†’ ์„ค๊ณ„์™€ ์•„ํ‚คํ…์ฒ˜๋ฅผ ์ตœ๋Œ€ํ•œ ๊นจ๋—ํ•˜๊ฒŒ ๋ณด์กด ๊ฐ€๋Šฅ
  • ๊ฐ€๋…์„ฑ์€ ์‹ค์ œ ์ฝ”๋“œ๋ณด๋‹ค ํ…Œ์ŠคํŠธ ์ฝ”๋“œ์—์„œ ๋” ์ค‘์š”ํ•˜๋‹ค โ†’ Build-Operate-Check ํŒจํ„ด
  • ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋Š” ์‹ค์ œ์ฝ”๋“œ๋งŒํผ ํšจ์œจ์ ์ผ ํ•„์š”๋Š” ์—†๋‹ค โ†’ ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ์—์„œ ์ˆ˜ํ–‰๋˜๊ธฐ ๋•Œ๋ฌธ
  • ๊ฐœ๋… ๋‹น assert๋ฌธ ์ˆ˜๋ฅผ ์ตœ์†Œ๋กœ ์ค„์ด์ž
  • ํ…Œ์ŠคํŠธ ํ•จ์ˆ˜ ํ•˜๋‚˜๋Š” ๊ฐœ๋… ํ•˜๋‚˜๋งŒ ํ…Œ์ŠคํŠธ
  • ํ…Œ์ŠคํŠธ๋Š” Fast, Independent, Repeatable, Self-Validating, Timely ํ•ด์•ผํ•œ๋‹ค
  • ํด๋ž˜์Šค ์ฑ…์ž„์˜ ๊ฐœ์ˆ˜๋Š” ์ž‘์•„์•ผ ํ•œ๋‹ค โ†’ ๊ฐ„๊ฒฐํ•œ 25๋‹จ์–ด ๋‚ด์™ธ
  • ์ž‘์€ ์„œ๋ž์„ ๋งŽ์ด ๋‘๊ณ  ๊ธฐ๋Šฅ๊ณผ ์ด๋ฆ„์ด ๋ช…ํ™•ํ•œ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋‚˜๋ˆ ๋„ฃ๊ธฐ
  • ํด๋ž˜์Šค๋ฅผ ๋ถ„๋ฆฌํ•˜์—ฌ ์‘์ง‘๋„๋ฅผ ๋†’์—ฌ๋ผ
  • ํด๋ž˜์Šค๋ฅผ ์ž‘๊ฒŒ ๋ถ„๋ฆฌํ•˜์—ฌ ๋ณ€๊ฒฝํ•˜๊ธฐ ์‰ฝ๋„๋ก ํ•œ๋‹ค
  • ๊ตฌ์ฒด์ ์ธ ๊ตฌํ˜„๋ณด๋‹ค๋Š” ์ถ”์ƒํ™”๋ฅผ ํ†ตํ•ด ๋ณ€๊ฒฝ์œผ๋กœ๋ถ€ํ„ฐ ๊ฒฉ๋ฆฌํ•œ๋‹ค
  • SRP, OCP, DIP ์›์น™ ์ง€ํ‚ค๊ธฐ

1. ํ•œ๊ฐ€์ง€(์ง€์ •๋œ ํ•จ์ˆ˜ ์ด๋ฆ„ ์•„๋ž˜์—์„œ ์ถ”์ƒํ™” ์ˆ˜์ค€์ด ํ•˜๋‚˜์ธ ๋‹จ๊ณ„๋งŒ ์ˆ˜ํ–‰) ๋งŒ ํ•ด๋ผ

๐Ÿฅฒ **Before**
const handleConnect = () => {
    let config = data[dbIdx];
    localStorage.setItem("alias", config.alias);
    localStorage.setItem("config", JSON.stringify(config));
    execPost("/connect", {
      config: config,
    })
      .then((res) => {
        console.log(res.data);
        if (res.data === "CONNECTED") {
          setIsConnected(true);
          history.push("/dashboard");
        }
      })
      .catch((err) => {
        console.log(err);
      });
  };
๐Ÿ˜ **After**
const handleConnect = () => {
		let config = data[dbIdx];
		saveConnect();
    moveToDashboard();
  };

const saveConnect = () => {
  localStorage.setItem("alias", config.alias);
  localStorage.setItem("config", JSON.stringify(config));
}

const moveToDashbaord = () => {
		execPost("/connect", {
      config: config,
    })
      .then((res) => {
        console.log(res.data);
        if (res.data === "CONNECTED") {
          setIsConnected(true);
          history.push("/dashboard");
        }
      })
      .catch((err) => {
        console.log(err);
      });
}
  • handleConnect์—์„œ ํ•˜๋Š” ์ผ์ด ์—ฌ๋Ÿฌ๊ฐ€์ง€์—ฌ์„œ ๊ฐ๊ฐ์˜ ํ•จ์ˆ˜๋กœ ๋ถ„๋ฆฌํ•˜์—ฌ saveConnect์™€ moveToDashboard ๋ฅผ ์ˆ˜ํ–‰
  • argument์— ๋Œ€ํ•œ ๊ฒƒ์€ ํ•จ์ˆ˜ ๋ฐ–์˜ ๊ฒƒ์„ ์จ๋„ ๊ดœ์ฐฎ์€๊ฑด์ง€ ๋‹ค์‹œ ๊ฒ€ํ† ๊ฐ€ ํ•„์š”ํ•˜๋‹ค

2. ๋ฐœ์Œํ•˜๊ธฐ ์‰ฌ์šด ์ด๋ฆ„์„ ์‚ฌ์šฉํ•˜๋ผ

๐Ÿฅฒ **Before**
const toYYYYMMDD = (date) =>
    new Date(date - date.getTimezoneOffset() * 60000)
      .toISOString()
      .split("T")[0];
๐Ÿ˜ **After**
const generateDate = (date) =>
    new Date(date - date.getTimezoneOffset() * 60000)
      .toISOString()
      .split("T")[0];
  • ์ฑ…์—์„œ genymdhms์  ์•ผ๋ฌด๋‹คํž˜์ฆˆ ๋ผ๋Š” ์ด๋ฆ„์„ ๋ดค์„๋•Œ๋Š” ๋ฐ•์žฅ๋Œ€์†Œํ–ˆ๋‹ค. ํ•˜์ง€๋งŒ ๋‚˜์—๊ฒŒ๋„ ์žˆ์—ˆ๋‹ค.. ํˆฌ์™€์ด์™€์ด์™€์ด์™€์ด์— ์— ๋””๋”” ๊ฐ€...
  • ๋‹น์žฅ ํ•จ์ˆ˜ ์ด๋ฆ„์„ ๋ฐ”๊ฟจ๋‹ค โ†’ generateDate ๋กœ

3. NULL์„ ๋ฐ˜ํ™˜ํ•˜์ง€ ๋ง๊ณ  ์˜ˆ์™ธ๋‚˜ ํŠน์ˆ˜ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜

๐Ÿฅฒ **Before**
function closePool(name) {
  if (Object.prototype.hasOwnProperty.apply(POOLS, [name])) {
    const pool = POOLS[name];
    delete POOLS[name];
    if (typeof pool.close === "function") {
      return pool.close();
    } else {
      return null;
    }
  }
}
๐Ÿ˜ **After**

function closePool(name) {
  if (Object.prototype.hasOwnProperty.apply(POOLS, [name])) {
    const pool = POOLS[name];
    delete POOLS[name];
    if (typeof pool.close === "function") {
      return pool.close();
    } else {
      throw Error("Could not close pool")
    }
  }
}
  • Pool์„ close ํ•  ์ˆ˜ ์—†์„ ๋•Œ null์„ returnํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ํ™•์‹คํ•œ Error ์„ throw ํ•˜๋Š” ๊ฒƒ์œผ๋กœ ๋ณ€๊ฒฝ

๐Ÿค”ย ๋– ์˜ค๋ฅด๋Š” ์ƒ๊ฐ

  • ์ผ๋‹จ ์ˆ˜์ •ํ•  ์ฝ”๋“œ์˜ ์–‘์ด ๋ถ€์กฑํ–ˆ๋‹ค. ์ง€๊ธˆ๊นŒ์ง€ ์ž‘์„ฑํ•œ ์ฝ”๋“œ๋‚˜ ๋ ˆํฌ์˜ ๊ฐœ์ˆ˜๋Š” ๋งŽ๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ์œผ๋‚˜ ์‹ค์ œ๋กœ ์‚ดํŽด๋ณด๋ฉด ๋Œ€๋ถ€๋ถ„์˜ ์ฝ”๋“œ๊ฐ€ ํ”„๋ก ํŠธ์—”๋“œ์ด๊ณ  ๋‹ˆ๊ผฌ์ƒ˜์˜ ๊ฐ•์˜๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์ด๋ฏธ ์ž‘์€ ํ•จ์ˆ˜๋กœ ์ž˜ ์ชผ๊ฐœ์ ธ ์žˆ์–ด ์˜ˆ์‹œ๋ฅผ ์ฐพ๊ธฐ๊ฐ€ ๋„ˆ๋ฌด ์–ด๋ ค์› ๋‹ค.

๐Ÿ”Žย ์งˆ๋ฌธ

๐Ÿ“ย ์†Œ๊ฐ 3์ค„ ์š”์•ฝ

  • ๋ง‰์ƒ ๋‚˜ ์ž์‹ ์˜ ์ฝ”๋“œ์—์„œ ์ฑ…์˜ ๋‚ด์šฉ์„ ์ ์šฉํ•˜์—ฌ ๋”๋Ÿฌ์›€์„ ์ฐพ์œผ๋ ค๋‹ˆ ์–ด๋ ค์› ๋‹ค
  • ์ฒญ์†Œํ•  ๊ฑฐ๋ฆฌ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๊ฒŒ ์Šคํฌ๋ž˜์น˜๋ถ€ํ„ฐ ์ž‘์„ฑํ•˜๋Š” ์ฝ”๋“œ์˜ ์–‘์„ ๋Š˜๋ ค์•ผ ๊ฒ ๋‹ค
  • Refactoring์€ ์ •๋ง ๋งŽ์€ ์‹œ๊ฐ„๊ณผ ๋…ธ๋ ฅ์„ ๋“ค์—ฌ ์ง€์†์ ์œผ๋กœ ์ˆ˜ํ–‰ํ•ด์•ผ๊ฒ ๋‹ค
profile
Full stack tech visionary

0๊ฐœ์˜ ๋Œ“๊ธ€