• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    迪恩网络公众号

hienvd/clean-code-javascript: Clean Code cho Javascript: một số lời khuyên ...

原作者: [db:作者] 来自: 网络 收藏 邀请

开源软件名称:

hienvd/clean-code-javascript

开源软件地址:

https://github.com/hienvd/clean-code-javascript

开源编程语言:

JavaScript 100.0%

开源软件介绍:

Original Repository: ryanmcdermott/clean-code-javascript

clean-code-javascript

Mục lục

  1. Giới thiệu
  2. Biến
  3. Hàm
  4. Đối tượng và Cấu trúc dữ liệu
  5. Lớp
  6. SOLID
  7. Testing
  8. Xử lí đồng thời
  9. Xử lí lỗi
  10. Định dạng
  11. Viết chú thích
  12. Các ngôn ngữ khác

Giới thiệu

Humorous image of software quality estimation as a count of how many expletives you shout when reading code

Những nguyên tắc kỹ thuật phần mềm, từ cuốn sách Clean Code của Robert C. Martin's, được áp dụng cho ngôn ngữ JavaScript. Đây không phải là một hướng dẫn về cách viết code Javascript mà là hướng dẫn về cách viết các đoạn code dễ đọc hiểu, tái sử dụng và tái cấu trúc được trong Javascript.

Không phải mọi nguyên tắc ở đây phải được tuân thủ một cách nghiêm ngặt, và thậm chí chỉ có một ít trong số đó được sử dụng phổ biến. Ở đây, nó chỉ là một hướng dẫn - không hơn không kém, nhưng chúng được hệ thống hóa thông qua kinh nghiệm thu thập được qua nhiều năm của các tác giả của cuốn sách Clean Code

Ngành kỹ thuật phần mềm chỉ phát triển được hơn 50 năm, và chúng ta vẫn đang học rất nhiều. Một khi kiến trúc phần mềm trở thành phổ biến, có lẽ sau đó chúng ta sẽ có thêm nhiều luật lệ khó hơn phải tuân theo. Còn giờ đây, hãy để những hướng dẫn này như là một tiêu chuẩn để đánh giá chất lượng các đoạn code Javascript mà bạn và team của bạn tạo ra.

Biết những hướng dẫn này thôi sẽ không thể ngay lập tức làm bạn trở thành một lập trình viên phần mềm tốt hơn được, và làm việc với chúng trong nhiều năm cũng không có nghĩa bạn sẽ không gặp bất cứ sai lầm nào. Mỗi đoạn code bắt đầu như một bản thảo đầu tiên, giống như đất sét được nặn nhào và cho tới cuối cùng thì nó sẽ lộ diện hình hài. Cuối cùng, chúng ta gọt tỉa những khuyết điểm khi chúng ta xem xét lại nó cùng với các đồng nghiệp. Đừng để bản thân bạn bị đánh bại bởi những bản thảo đầu tiên, thứ mà vẫn cần phải được chỉnh sửa. Thay vào đó hãy đánh bại những dòng code.

Biến

Sử dụng tên biến có nghĩa và dễ phát âm

Không tốt:

const yyyymmdstr = moment().format('YYYY/MM/DD');

Tốt:

const currentDate = moment().format('YYYY/MM/DD');

về đầu trang

Sử dụng cùng từ vựng cho cùng loại biến

Không tốt:

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

Tốt:

getUser();

về đầu trang

Sử dụng các tên có thể tìm kiếm được

Chúng ta sẽ đọc code nhiều hơn là viết chúng. Điều quan trọng là code chúng ta viết có thể đọc được và tìm kiếm được. Việc đặt tên các biến không có ngữ nghĩa so với chương trình, chúng ta có thể sẽ làm người đọc code bị tổn thương tinh thần. Hãy làm cho các tên biến của bạn có thể tìm kiếm được. Các công cụ như buddy.jsESLint có thể giúp nhận ra các hằng chưa được đặt tên.

Không tốt:

// 86400000 là cái quái gì thế?
setTimeout(blastOff, 86400000);

Tốt:

// Khai báo chúng như một biến global.
const MILLISECONDS_IN_A_DAY = 86400000;

setTimeout(blastOff, MILLISECONDS_IN_A_DAY);

về đầu trang

Sử dụng những biến có thể giải thích được

Không tốt:

const address = 'One Infinite Loop, Cupertino 95014';
const cityZipCodeRegex = /^[^,\\]+[,\\\s]+(.+?)\s*(\d{5})?$/;
saveCityZipCode(address.match(cityZipCodeRegex)[1], address.match(cityZipCodeRegex)[2]);

Tốt:

const address = 'One Infinite Loop, Cupertino 95014';
const cityZipCodeRegex = /^[^,\\]+[,\\\s]+(.+?)\s*(\d{5})?$/;
const [, city, zipCode] = address.match(cityZipCodeRegex) || [];
saveCityZipCode(city, zipCode);

về đầu trang

Tránh hại não người khác

Tường minh thì tốt hơn là ẩn.

Không tốt:

const locations = ['Austin', 'New York', 'San Francisco'];
locations.forEach((l) => {
  doStuff();
  doSomeOtherStuff();
  // ...
  // ...
  // ...
  // Khoan, `l` làm cái gì vậy?
  dispatch(l);
});

Tốt:

const locations = ['Austin', 'New York', 'San Francisco'];
locations.forEach((location) => {
  doStuff();
  doSomeOtherStuff();
  // ...
  // ...
  // ...
  dispatch(location);
});

về đầu trang

Đừng thêm những ngữ cảnh không cần thiết

Nếu tên của lớp hay đối tượng của bạn đã nói lên điều gì đó rồi, đừng lặp lại điều đó trong tên biến nữa.

Không tốt:

const Car = {
  carMake: 'Honda',
  carModel: 'Accord',
  carColor: 'Blue'
};

function paintCar(car, color) {
  car.carColor = color;
}

Tốt:

const Car = {
  make: 'Honda',
  model: 'Accord',
  color: 'Blue'
};

function paintCar(car, color) {
  car.color = color;
}

về đầu trang

Sử dụng những tham số mặc định thay vì kiểm tra các điều kiện lòng vòng

Không tốt:

function createMicrobrewery(name) {
  const breweryName = name || 'Hipster Brew Co.';
  // ...
}

Tốt:

function createMicrobrewery(breweryName = 'Hipster Brew Co.') {
  // ...
}

về đầu trang

Hàm

Đối số của hàm (lý tưởng là ít hơn hoặc bằng 2)

Giới hạn số lượng param của hàm là một điều cực kì quan trọng bởi vì nó làm cho hàm của bạn trở nên dễ test hơn. Trường hợp có nhiều hơn 3 params có thể dẫn đến việc bạn phải test hàng tấn test case khác nhau với những đối số riêng biệt.

1 hoặc 2 đối số là trường hợp lý tưởng, còn trường hợp 3 đối số thì nên tránh nếu có thể. Những trường hợp khác (từ 3 params trở lên) thì nên được gộp lại. Thông thường nếu có nhiều hơn 2 đối số thì hàm của bạn đang cố thực hiện quá nhiều việc rồi đấy. Trong trường hợp ngược lại, phần lớn thời gian một đối tượng cấp cao sẽ là đủ để làm đối số.

Kể từ khi Javascript cho phép tạo nhiều đối tượng một cách nhanh chóng, mà không cần nhiều lớp có sẵn, bạn có thể sử dụng một đối tượng nếu bạn cần truyền nhiều đối số.

Để làm cho rõ ràng một hàm mong đợi những thuộc tính gì, bạn có thể sử dụng cấu trúc destructuring của ES6. Điều này có một số ưu điểm:

  1. Khi một ai đó nhìn vào hàm, những thuộc tính nào được sử dụng sẽ trở nên rõ ràng ngay lập tức.
  2. Destructuring cũng sao chép lại các giá trị ban đầu được chỉ định của đối tượng đối số được truyền vào hàm. Điều này có thể giúp ngăn chặn các ảnh hưởng phụ. Chú ý: các đối tượng và mảng được destructure từ đối tượng đối số thì không được sao chép lại.
  3. Linter có thể sẽ cảnh báo bạn về những thuộc tính không sử dụng, điều mà không thể xảy ra nếu không có destructuring.

Không tốt:

function createMenu(title, body, buttonText, cancellable) {
  // ...
}

Tốt:

function createMenu({ title, body, buttonText, cancellable }) {
  // ...
}

createMenu({
  title: 'Foo',
  body: 'Bar',
  buttonText: 'Baz',
  cancellable: true
});

Về đầu trang

Hàm chỉ nên giải quyết một vấn đề

Đây là quy định quan trọng nhất của kỹ thuật phần mềm. Khi một hàm thực hiện nhiều hơn 1 việc, chúng sẽ trở nên khó khăn hơn để viết code, test, và suy luận. Khi bạn có thể tách biệt một hàm để chỉ thực hiện một hành động, thì sẽ dễ dàng hơn để tái cấu trúc và code của bạn sẽ dễ đọc hơn nhiều. Nếu bạn chỉ cần làm theo hướng dẫn này thôi mà không cần làm gì khác thì bạn cũng đã giỏi hơn nhiều developer khác rồi.

Không tốt:

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

Tốt:

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

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

Về đầu trang

Tên hàm phải nói ra được những gì chúng làm

Không tốt:

function addToDate(date, month) {
  // ...
}

const date = new Date();

// Khó để biết được hàm này thêm gì thông qua tên hàm.
addToDate(date, 1);

Tốt:

function addMonthToDate(month, date) {
  // ...
}

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

Về đầu trang

Hàm chỉ nên có một lớp trừu tượng

Khi có nhiều hơn một lớp trừu tượng thì hàm của bạn đang làm quá nhiều. Chia nhỏ các hàm ra sẽ làm cho việc test và tái sử dụng dễ dàng hơn.

Không tốt:

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...
  });
}

Tốt:

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...
  });
}

Về đầu trang

Xóa code trùng lặp

Tuyệt đối tránh những dòng code trùng lặp. Code trùng lặp thì không tốt bởi vì nếu bạn cần thay đổi cùng một logic, bạn phải sửa ở nhiều hơn một nơi.

Hãy tưởng tượng nếu bạn điều hành một nhà hàng và bạn theo dõi hàng tồn kho: bao gồm cà chua, hành tây, tỏi, gia vị, vv.... Nếu bạn có nhiều danh sách quản lý, thì tất cả chúng phải được thay đổi khi bạn phục vụ một món ăn có chứa cà chua. Nếu bạn chỉ có 1 danh sách, thì việc cập nhật ở một nơi thôi.

Thông thường, bạn có những dòng code lặp lại bởi vì bạn có 2 hay nhiều hơn những thứ chỉ khác nhau chút ít, mà chia sẻ nhiều thứ chung, nhưng sự khác nhau của chúng buộc bạn phải có 2 hay nhiều hàm riêng biệt để làm nhiều điều tương tự nhau. Xóa đi những dòng code trùng có nghĩa là tạo ra một abstraction có thể xử lý tập những điểm khác biệt này chỉ với một hàm/module hay class.

Có được một abstraction đúng thì rất quan trọng, đó là lý do tại sao bạn nên tuân thủ các nguyên tắc SOLID được đặt ra trong phần Lớp. Những abstraction không tốt có thể còn tệ hơn cả những dòng code bị trùng lặp, vì thế hãy cẩn thận! Nếu bạn có thể tạo ra một abstraction tốt, hãy làm nó! Đừng lặp lại chính mình, nếu bạn không muốn đi cập nhật nhiều nơi bất cứ khi nào bạn muốn thay đổi một thứ gì đó.

Không tốt:

function showDeveloperList(developers) {
  developers.forEach((developer) => {
    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);
  });
}

Tốt:

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);
  });
}

Về đầu trang

Thiết lập những đối tượng mặc định với Object.assign

Không tốt:


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
热门推荐
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap