함수(Functions)_1

39537 단어 CleanCodingCleanCoding

1. 함수 인자는 2개 이하가 이상적.

  • 매개변수의 제한으로 함수 테스팅을 쉽게 만들어줌.
  • 3개 이상의 인자는 가능한 피함.
  • 많은 인자를 사용해야 한다면 객체를 이용.

👋ES6의 비구조화(destructing) 구문의 장점👋

1. 함수의 시그니쳐(인자의 타입, 반환되는 값의 타입 등)를 볼때 어떤 속성이 사용되는지 즉시 알 수 있음.
2. 함수에 전달된 인수 객체의 지정된 기본타입 값을 복제하며 이는 사이드이펙트를 방지.
3. Linter를 사용하면 사용되지 않는 인자에 대해 경고해주거나 비구조화 없이 코드를 짤 수 없게 할 수 있음.
//Bad👎
function createMenu(title,body,buttonText,cancellable){
  //....
}


//Good👍
function createMenu({title,body,buttonText,cancellable}){
  //....
}
createMenu({
  title:'Foo',
  body:'Bar',
  buttonText:'Baz',
  cancellable:true
  )};

2. 함수는 하나의 행동만 해야함.

//Bad👎
function emailClients(clients) {
  clients.forEach(client => {
    const clientRecord = database.lookup(client);
    if (clientRecord.isActive()) {
      email(client);
    }
  });
}


//Good👍
function emailClients(clients) {
  clients
    .filter(isClientActive)
    .forEach(email);
}

function isClientActive(client) {
  const clientRecord = database.lookup(client);
  return clientRecord.isActive();
}

3. 함수명은 함수가 무엇을 하는지 알아야함.

//Bad👎
function AddToDate(date, month) {
  // ...
}

const date = new Date();

// 뭘 추가하는 건지 이름만 보고 알아내기 힘듭니다.
AddToDate(date, 1);


//Good👍
function AddMonthToDate(date, month) {
  // ...
}

const date = new Date();
AddMonthToDate(date, 1);

4. 함수는 단일 행동을 추상화 해야함.

  • 추상화된 이름이 여러 의미를 내포하고 있다는 그 함수는 너무 많은 일을 하게끔 설계된 것임.
  • 함수들을 나누어서 재사용가능하며 테스트하기 쉽도록 만들어야함.
//Bad👎
function parseBetterJSAlternative(code) {
  const REGEXES = [
    // ...
  ];

  const statements = code.split(' ');
  const tokens = [];
  REGEXES.forEach(REGEX => {
    statements.forEach(statement => {
      // ...
    });
  });

  const ast = [];
  tokens.forEach(token => {
    // lex...
  });

  ast.forEach(node => {
    // parse...
  });
}


//Good👍
function tokenize(code) {
  const REGEXES = [
    // ...
  ];

  const statements = code.split(' ');
  const tokens = [];
  REGEXES.forEach(REGEX => {
    statements.forEach(statement => {
      tokens.push( /* ... */ );
    });
  });

  return tokens;
}

function lexer(tokens) {
  const ast = [];
  tokens.forEach(token => {
    ast.push( /* ... */ );
  });

  return ast;
}

function parseBetterJSAlternative(code) {
  const tokens = tokenize(code);
  const ast = lexer(tokens);
  ast.forEach(node => {
    // parse...
  });
}

5. 중복된 코드를 작성하지 않음.

//Bad👎
function showDeveloperList(developers) {
  developers.forEach(developers => {
    const expectedSalary = developer.calculateExpectedSalary();
    const experience = developer.getExperience();
    const githubLink = developer.getGithubLink();
    const data = {
      expectedSalary,
      experience,
      githubLink
    };

    render(data);
  });
}

function showManagerList(managers) {
  managers.forEach(manager => {
    const expectedSalary = manager.calculateExpectedSalary();
    const experience = manager.getExperience();
    const portfolio = manager.getMBAProjects();
    const data = {
      expectedSalary,
      experience,
      portfolio
    };

    render(data);
  });
}


//Good👍
function showEmployeeList(employees) {
  employees.forEach((employee) => {
    const expectedSalary = employee.calculateExpectedSalary();
    const experience = employee.getExperience();

    let portfolio = employee.getGithubLink();

    if (employee.type === 'manager') {
      portfolio = employee.getMBAProjects();
    }

    const data = {
      expectedSalary,
      experience,
      portfolio
    };

    render(data);
  });
}

6. Object.assign을 사용해 기본 객체를 만듬.

//Bad👎
const menuConfig = {
  title: null,
  body: 'Bar',
  buttonText: null,
  cancellable: true
};

function createMenu(config) {
  config.title = config.title || 'Foo';
  config.body = config.body || 'Bar';
  config.buttonText = config.buttonText || 'Baz';
  config.cancellable = config.cancellable !== undefined ? config.cancellable : true;
}

createMenu(menuConfig);


//Good👍
const menuConfig = {
  title: 'Order',
  // 유저가 'body' key의 value를 정하지 않았다.
  buttonText: 'Send',
  cancellable: true
};

function createMenu(config) {
  config = Object.assign({
    title: 'Foo',
    body: 'Bar',
    buttonText: 'Baz',
    cancellable: true
  }, config);

  // config는 이제 다음과 동일합니다: {title: "Order", body: "Bar", buttonText: "Send", cancellable: true}
  // ...
}

createMenu(menuConfig);

7. 매개변수로 플래그를 사용하지 않음.

  • 플래그를 사용한다는 것은 그 함수가 한가지 이상의 역할을 하고 있다는 뜻.
  • boolean 기반으로 함수가 실행되는 코드는 함수를 분리
//Bad👎
function createFile(name, temp) {
  if (temp) {
    fs.create(`./temp/${name}`);
  } else {
    fs.create(name);
  }
}


//Good👍
function createFile(name) {
  fs.create(name);
}

function createTempFile(name) {
  createFile(`./temp/${name}`);
}

8. 사이드 이펙트를 피한다.

//Bad👎
// 아래 함수에 의해 참조되는 전역 변수입니다.
// 이 전역 변수를 사용하는 또 하나의 함수가 있다고 생각해보세요. 이제 이 변수는 배열이 될 것이고, 프로그램을 망가뜨리겠죠.
let name = 'Ryan McDermott';

function splitIntoFirstAndLastName() {
  name = name.split(' ');
}

splitIntoFirstAndLastName();

console.log(name); // ['Ryan', 'McDermott'];


//Good👍
function splitIntoFirstAndLastName(name) {
  return name.split(' ');
}

const name = 'Ryan McDermott';
const newName = splitIntoFirstAndLastName(name);

console.log(name); // 'Ryan McDermott';
console.log(newName); // ['Ryan', 'McDermott'];
//Bad👎
const addItemToCart = (cart, item) => {
  cart.push({ item, date: Date.now() });
};

//Good👍
const addItemToCart = (cart, item) => {
  return [...cart, { item, date : Date.now() }];
};

9. 전역 함수를 사용하지 않는다.

//Bad👎
Array.prototype.diff = function diff(comparisonArray) {
  const hash = new Set(comparisonArray);
  return this.filter(elem => !hash.has(elem));
};

//Good👍
class SuperArray extends Array {
  diff(comparisonArray) {
    const hash = new Set(comparisonArray);
    return this.filter(elem => !hash.has(elem));
  }
}

좋은 웹페이지 즐겨찾기