ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Javascript Clean Code에 관하여
    Javascript 2021. 4. 11. 18:50

    자바스크립트 클린코드에 대한 관점들이 많이 있습니다.

     

    다른사람들을 위한 코드를 작성하는 것이 좋고, 또 그 자체로도 본인에게도 매우 도움이 되기 때문에 어떻게 보면, 클린코드는 좋은 개발자의 덕목에 필수불가결하다고 할 수 있습니다.

     

    여전히 어지럽고 난해한 코드를 작성하는 법, 아무도 알아보지 못하게 코드를 작성하는 법에 대한 책들이 있긴 하지만, 저는 그런 관점에 대해서는 자기 자신이 자신이 없기 때문이라는 생각만 듭니다.

     

    이 글에서는 자바스크립트 관점에서만 다룹니다.

     

    1. 강력한 타입 체크

    == 대신에 ===를 사용하세요.

    0 == false // true
    0 === false // false
    2 == "2" // true
    2 === "2" // false
    
    // 예시
    const val = "123";
    
    if (val === 123) {
      console.log(val);
      // 콘솔이 찍히지 않습니다.
    }
    
    if (val === "123") {
      console.log(val);
      // 콘솔이 찍힙니다.
    }

    2. 변수 이름

    변수 이름을 잘 지으세요.

     

    BAD

    let daysSLV = 10;
    
    let y = new Date().getFullYear();
    
    let ok;
    
    if (user.age > 30) {
      ok = true;
    }

    GOOD

    const MAX_AGE = 30;
    
    let daysSinceLastVisit = 10;
    
    let currentYear = new Date().getFullYear();
    
    ...
    
    const isUserOlderThanAllowed = user.age > MAX_AGE;

    조금 길어지더라도 자세하게 내용을 적어주는 것이 다른사람들이 보기에 더 이해가 쉬울 것입니다.

    하지만, 불필요한 단어는 피해야합니다.

     

    BAD

    let nameValue;
    let theProduct;

    GOOD

    let name;
    let product;

     

    문맥을 외워야하도록 만들지 마세요.

    BAD

    const products = ["T-Shirt", "Shoes", "Watches", "Bags"];
    
    products.forEach(p => {
      doSomething();
      doSomethingElse();
      .
      .
      .
      // p가 뭐야?
      register(p);
    });

    GOOD

    const products = ["T-Shirt", "Shoes", "Watches", "Bags"];
    
    products.forEach(product => {
      doSomething();
      doSomethingElse();
      .
      .
      .
      register(product);
    });

     

    문맥을 불필요하게 추가하지마세요.

    BAD

    const product = {
      productId: 1,
      productName: "T-Shirt",
      productPrice: 8.99,
      productUnits: 12
    };
    
    ...
    
    product.productName;

    불필요하게 product가 prefix로 모두 들어간 모습입니다.

     

     

    GOOD

    const product = {
      id: 1,
      name: "T-Shirt",
      price: 8.99,
      units: 12
    };
    
    ...
    
    product.name;

    동일한 유형의 변수에 동일한 어휘 사용하기

    BAD

    getUserInfo();
    getClientData();
    getCustomerRecord();

    GOOD

    getProduct();

    3. 함수

    길고 설명이 충분히 되는 함수이름을 사용하세요.

    특정 동작을 나타내는 것을 고려할 때 함수 이름은 인수의 의도뿐만 아니라 그 뒤에있는 의도를 완전히 드러내는 동사 또는 구문이어야합니다.

    BAD

    function email(user) {
      // 실행
    }
    

    GOOD

    function sendEmailUser(emailAddress) {
      // 실행
    }
    

    긴 인수를 피하세요.

    인수가 적을수록 함수를 테스트하기가 더 쉽습니다.

    BAD

    function getProducts(fields, fromDate, toDate) {
      // 실행
    }

    GOOD

    function getProducts({ fields, fromDate, toDate }) {
      // 실행
    }
    
    getProducts({
      fields: ['id', 'name', 'price', 'units],
      fromDate: '2020-07-01',
      toDate: '2020-07-22'
    });

    브라우저 지원 여부에 따라 조건 인수 대신에 기본 타입 인수를 사용하세요.

    BAD

    function createShape(type) {
      const shapeType = type || "circle";
      // ...
    }

    GOOD

    function createShape(type = "circle") {
      // ...
    }

     

    단일 기능 내에서 여러 작업 실행 하지 마세요.

     

    BAD

    function notifyUsers(users) {
      users.forEach(user => {
        const userRecord = database.lookup(user);
        if (userRecord.isVerified()) {
          notify(user);
        }
      });
    }

     

    GOOD

    function notifyVerifiedUsers(users) {
      users.filter(isUserVerified).forEach(notify);
    }
    
    function isUserVerified(user) {
      const userRecord = database.lookup(user);
      return userRecord.isVerified();
    }

     

    Object.assign을 사용해서 기본 개체를 세팅하세요.

     

    BAD

    const shapeConfig = {
      type: "circle",
      width: 150,
      height: null
    };
    
    function createShape(config) {
      config.type = config.type || "circle";
      config.width = config.width || 300;
      config.height = config.height || 300;
    }
    
    createShape(shapeConfig);

    GOOD

    const shapeConfig = {
      type: "circle",
      width: 150
      // height를 제외시켜둔 상태
    };
    
    function createShape(config) {
      config = Object.assign(
        {
          type: "circle",
          width: 300,
          height: 300
        },
        config
      );
      ...
    }
      
    createShape(shapeConfig);

    플래그는 함수가해야하는 것보다 더 많은 일을하고 있음을 알려주기 때문에 매개 변수로 사용하지 마십시오.

     

    BAD

    function createFile(name, isPublic) {
      if (isPublic) {
        fs.create(`./public/${name}`);
      } else {
        fs.create(name);
      }
    }

    GOOD

    function createFile(name) {
      fs.create(name);
    }
    
    function createPublicFile(name) {
      createFile(`./public/${name}`);
    }

     

    기존 개체를 확장해야하는 경우 네이티브 개체의 프로토 타입 체인에 함수를 만드는 대신 ES 클래스 및 상속을 사용하십시오.

     

     

    BAD

    Array.prototype.myFunction = function myFunction() {
      // 실행
    };

     

    GOOD

    class SuperArray extends Array {
      myFunc() {
        // 실행
      }
    }

     

    4. 조건문

     

    부정 조건문을 피하세요.

     

    BAD

    function isPostNotPublished(post) {
      // 실행
    }
    if (!isPostNotPublished(post)) {
      // 실행
    }
    

     

    GOOD

    function isPostPublished(user) {
      // 실행
    }
    if (isPostPublished(user)) {
      // 실행
    }
    

     

     

    단축 속성을 사용하세요.

     

    BAD

    if (isValid === true) {
      // 실행
    }
    if (isValid === false) {
      // 실행
    }

     

    GOOD

    if (isValid) {
      // 실행
    }
    if (!isValid) {
      // 실행
    }
    

     

    조건문을 피하고 다형성과 상속을 사용하세요.

     

    BAD

    class Dog {
      // ...
      getBreed() {
        switch (this.type) {
          case "GermanShepherd":
            return this.getStandardSize("GermanShepherd");
          case "JackRussellTerrier":
            return this.getStandardSize("JackRussellTerrier");
          case "ShibaInu":
            return this.getStandardSize("ShibaInu");
        }
      }
    }

     

    GOOD

    class Dog {
      // ...
    }
    
    class GermanShepherd extends Dog {
      // ...
      getStandardSize() {
        return this.standardSize;
      }
    }
    
    class JackRussellTerrier extends Dog {
      // ...
      getSize() {
        return this.standardSize;
      }
    }
    
    class ShibaInu extends Dog {
      // ...
      getSize() {
        return this.standardSize;
      }
    }

     

     

    5. ES 클래스 사용

     

    이제는 조금 더 클래스 사용을 선호해야할 필요가 있습니다.

     

    BAD

    const Product = function(name) {
      if (!(this instanceof Product)) {
        throw new Error("Instantiate Product with `new` keyword");
      }
      this.name = name;
    };
    
    Product.prototype.getSize = function getSize() { /**/ };
    
    const Tshirt = function(name, color) {
      if (!(this instanceof Tshirt)) {
        throw new Error("Instantiate Tshirt with `new` keyword");
      }
      Product.call(this, name);
      this.color = color;
    };
    
    Tshirt.prototype = Object.create(Product.prototype);
    Tshirt.prototype.constructor = Tshirt;
    Tshirt.prototype.printColor = function printColor() { /**/ };

     

    GOOD

    class Product {
      
      constructor(name) {
        this.name = name;
      }
      
      getDiscount() {
        /* ... */
      }
    }
    
    class Tshirt extends Product {
      
      constructor(name, color) {
        super(name);
        this.color = color;
      }
      
      getSize() {
        /* ... */
      }
    }

     

    메소드 체이닝을 사용하세요.

    코드가 덜 장황 해집니다. 클래스에서 모든 함수의 끝에 이것을 반환하고 추가 클래스 메서드를 연결할 수 있습니다.

     

    BAD

    class Product {
      
      constructor(name) {
        this.name = name;
      }
      
      setPrice(price) {
        this.price = price;
      }
      
      setUnits(units) {
        this.units = units;
      }
      
      save() {
        console.log(this.name, this.price, this.units);
      }
    }
    
    const product = new Product("Bag");
    
    product.setPrice(23.99);
    product.setUnits(12);
    product.save();

     

    GOOD

    class Product {
      
      constructor(name) {
        this.name = name;
      }
      
      setName(name) {
        this.name = name;
        // 체이닝을 위해서 리턴
        return this;
      }
      
      setPrice(price) {
        this.price = price;
        // 체이닝을 위해서 리턴
        return this;
      }
      
      save() {
        console.log(this.name, this.price, this.units);
        // 체이닝을 위해서 리턴
        return this;
      }
    }
    
    const product = new Product("T-Shirt")
        .setName("Jeans")
        .setAge(31.99)
        .save();

    6. Eval 사용 금지

    Eval 함수를 사용하면 JavaScript 컴파일러에 문자열을 전달하고 JavaScript로 실행할 수 있습니다..

    eval("alert('Hi');");

    Eval 기능은 안전하지 않고 악의적인 프로그래머가 악용할 수있는 잠재적인 위협 벡터를 열어주므로 피해야합니다.

     

    7. JS Lint를 사용하세요.

    JSLint는 JavaScript 코드의 일반적인 문제를 식별하는 데 도움이되는 훌륭한 도구입니다.

    예를 들어 Visual Studio Code에는 컴파일 타임 (또는 수동)에서 오류를 확인할 수있는 JSLint용 추가 기능이 있습니다.

    이렇게하면 코드가 더 깔끔해지며 성가신 버그가 프로덕션에 표시되는 것을 방지하는 데 도움이됩니다.

     

    8. 일반화를 피하세요.

    일반적으로 반복하지 않도록 자기 자신이 최선을 다해야 합니다.

    중복 코드를 최소화하고, 함수 및 데드 코드와 같은 나쁜 코드를 작성하지 않기 위해 꼼꼼하게 노력해야 할 것입니다.

    주석처리하지말고 데드코드 같은경우 삭제를 해버리세요.

     

    감사합니다.

     

     

    출처 : javascript.plainenglish.io/javascript-clean-code-best-practices-461c24c53cae

     

     

     

     

Designed by Tistory.