头图

Good code is not only code that can be run, but also code that can be easily read, reused and refactored by others, because in addition to implementing functions, most of the code is maintained by you or other members of the team of.

Although this article focuses on writing clean and tidy JavaScript ES6 code, and is not related to any framework, most of the examples mentioned below are also applicable to other languages. In addition, the following examples are also mainly from Robert C. The recommendations adopted in Martin's book Clean Code are not meant to be strictly followed.

variable

Use meaningful names

The naming of variables should be descriptive and meaningful. The rule of thumb is that most JavaScript variables should use camelCase.

// 错误 ❌
const foo = "JDoe@example.com";
const bar = "John";
const age = 23;
const qux = true;

// 正确 ✅
const email = "John@example.com";
const firstName = "John";
const age = 23;
const isActive = true
Note that variable names of Boolean type usually seem to be answering questions, for example:
isActive
didSubscribe
hasLinkedAccount

Avoid adding unnecessary context

No need to add redundant context in a specific object or class

// 错误 ❌
const user = {
  userId: "296e2589-7b33-400a-b762-007b730c8e6d",
  userEmail: "JDoe@example.com",
  userFirstName: "John",
  userLastName: "Doe",
  userAge: 23,
};

user.userId;

// 正确 ✅
const user = {
  id: "296e2589-7b33-400a-b762-007b730c8e6d",
  email: "JDoe@example.com",
  firstName: "John",
  lastName: "Doe",
  age: 23,
};

user.id;

Avoid hard coding

Make sure to declare meaningful and searchable constants instead of directly using a constant value. Global variables are recommended to use serpentine nomenclature (SCREAMING_SNAKE_CASE)

// 错误 ❌
setTimeout(clearSessionData, 900000);

// 正确 ✅
const SESSION_DURATION_MS = 15 * 60 * 1000;

setTimeout(clearSessionData, SESSION_DURATION_MS);

function

Use descriptive names

The function name can be very long, long enough to describe its role. Generally, the function contains the verb to describe what it does, but the function that returns a Boolean value is an exception. Generally, it is an answer "yes" or "no". In the form of the question, the function naming should also be camel case.

// 错误 ❌
function toggle() {
  // ...
}

function agreed(user) {
  // ...
}

// 正确 ✅
function toggleThemeSwitcher() {
  // ...
}

function didAgreeToAllTerms(user) {
  // ...
}

Use default parameters

Using default values directly is more concise than short-circuit syntax or adding judgment statements in functions. It is worth noting that short-circuit syntax applies to all false , such as false , null , undefined , '' , "" , 0 and NaN . The default parameters only replace undefined .

// 错误 ❌
function printAllFilesInDirectory(dir) {
  const directory = dir || "./";
  //   ...
}

// 正确 ✅
function printAllFilesInDirectory(dir = "./") {
  // ...
}

Limit the number of parameters

This one is controversial. The function parameter should be more than 161ac4760898aa, which means that the function parameter is 0, 1 or 2, if the third parameter is needed, please explain:

  • Function needs to be split
  • Related parameters can be aggregated into objects to pass
// 错误 ❌
function sendPushNotification(title, message, image, isSilent, delayMs) {
  // ...
}

sendPushNotification("New Message", "...", "http://...", false, 1000);

// 正确 ✅
function sendPushNotification({ title, message, image, isSilent, delayMs }) {
  // ...
}

const notificationConfig = {
  title: "New Message",
  message: "...",
  image: "http://...",
  isSilent: false,
  delayMs: 1000,
};

sendPushNotification(notificationConfig);

Don't do too much in one function

In principle, a function only does one thing. This principle can help us reduce the volume and complexity of the function, and it can also better test, debug and refactor. The number of lines of code of a function is to judge whether the function is An indicator of doing too much, it is generally recommended that the length of a function is less than 20~30 lines.

// 错误 ❌
function pingUsers(users) {
  users.forEach((user) => {
    const userRecord = database.lookup(user);
    if (!userRecord.isActive()) {
      ping(user);
    }
  });
}

// 正确 ✅
function pingInactiveUsers(users) {
  users.filter(!isUserActive).forEach(ping);
}

function isUserActive(user) {
  const userRecord = database.lookup(user);
  return userRecord.isActive();
}

Avoid using flag variables

The flag variable means that the function can be further simplified

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

// 正确 ✅
function createFile(name) {
  fs.create(name);
}

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

Don't repeat yourself (DRY)

Duplicated code is not a good signal. You copy and paste N times. Next time this part of the code is modified, you will have to modify N places at the same time.

// 错误 ❌
function renderCarsList(cars) {
  cars.forEach((car) => {
    const price = car.getPrice();
    const make = car.getMake();
    const brand = car.getBrand();
    const nbOfDoors = car.getNbOfDoors();

    render({ price, make, brand, nbOfDoors });
  });
}

function renderMotorcyclesList(motorcycles) {
  motorcycles.forEach((motorcycle) => {
    const price = motorcycle.getPrice();
    const make = motorcycle.getMake();
    const brand = motorcycle.getBrand();
    const seatHeight = motorcycle.getSeatHeight();

    render({ price, make, brand, seatHeight });
  });
}

// 正确 ✅
function renderVehiclesList(vehicles) {
  vehicles.forEach((vehicle) => {
    const price = vehicle.getPrice();
    const make = vehicle.getMake();
    const brand = vehicle.getBrand();

    const data = { price, make, brand };

    switch (vehicle.type) {
      case "car":
        data.nbOfDoors = vehicle.getNbOfDoors();
        break;
      case "motorcycle":
        data.seatHeight = vehicle.getSeatHeight();
        break;
    }

    render(data);
  });
}

Avoid side effects

In JavaScript, the preferred mode should be functional rather than imperative. In other words, to ensure the purity of the function, side effects can modify the shared state and resources, which will cause the code to be unstable and difficult to test, and troubleshooting will also be Particularly tricky, all side effects should be managed centrally. If you need to modify the global state, you can define a unified service to modify.

// 错误 ❌
let date = "21-8-2021";

function splitIntoDayMonthYear() {
  date = date.split("-");
}

splitIntoDayMonthYear();

// Another function could be expecting date as a string
console.log(date); // ['21', '8', '2021'];

// 正确 ✅
function splitIntoDayMonthYear(date) {
  return date.split("-");
}

const date = "21-8-2021";
const newDate = splitIntoDayMonthYear(date);

// Original vlaue is intact
console.log(date); // '21-8-2021';
console.log(newDate); // ['21', '8', '2021'];

In addition, if a variable object is passed in as a parameter of a function, the parameter should be a cloned object of the parameter when returning it instead of directly modifying the object and returning it.


// 错误 ❌
function enrollStudentInCourse(course, student) {
  course.push({ student, enrollmentDate: Date.now() });
}

// 正确 ✅
function enrollStudentInCourse(course, student) {
  return [...course, { student, enrollmentDate: Date.now() }];
}

Concurrent

Avoid using callbacks

callback function too messy, so ES6 provides us with Promise allows us to use chained callbacks, of course Async/Await provides a more concise solution that allows us to write more linear code

// 错误 ❌
getUser(function (err, user) {
  getProfile(user, function (err, profile) {
    getAccount(profile, function (err, account) {
      getReports(account, function (err, reports) {
        sendStatistics(reports, function (err) {
          console.error(err);
        });
      });
    });
  });
});

// 正确 ✅
getUser()
  .then(getProfile)
  .then(getAccount)
  .then(getReports)
  .then(sendStatistics)
  .catch((err) => console.error(err));

// 正确 ✅✅
async function sendUserStatistics() {
  try {
    const user = await getUser();
    const profile = await getProfile(user);
    const account = await getAccount(profile);
    const reports = await getReports(account);
    return sendStatistics(reports);
  } catch (e) {
    console.error(err);
  }
}

Error handling

Handle thrown exceptions and rejected promises

Correct handling of exceptions can make our code more streamlined, and it will be more convenient to troubleshoot problems.

// 错误 ❌
try {
  // 可能出错的代码
} catch (e) {
  console.log(e);
}

// 正确 ✅
try {
  // 可能出错的代码
} catch (e) {
  // 比 console.log 更合适
  console.error(e);

  // 通知用户
  alertUserOfError(e);

  // 通知服务器
  reportErrorToServer(e);

  // 使用自定义的异常处理
  throw new CustomError(e);
}

Annotation

Only add comments for complex logic

Don't add comments excessively, just add to the complex logic.

// 错误 ❌
function generateHash(str) {
  // 哈希变量
  let hash = 0;

  // 获取字符串的长度
  let length = str.length;

  // 如果长度是空的就返回
  if (!length) {
    return hash;
  }

  // 遍历字符
  for (let i = 0; i < length; i++) {
    // 获取字符 code
    const char = str.charCodeAt(i);

    // 为 hash 赋值
    hash = (hash << 5) - hash + char;

    // 转换为 32 位的整型
    hash &= hash;
  }
}

// 正确 ✅
function generateHash(str) {
  let hash = 0;
  let length = str.length;
  if (!length) {
    return hash;
  }

  for (let i = 0; i < length; i++) {
    const char = str.charCodeAt(i);
    hash = (hash << 5) - hash + char;
    hash = hash & hash; // 转换为 32 位的整型
  }
  return hash;
}

version control

There is no need to write code modification history, version management (such as git) has done this for us.


// 错误 ❌
/**
 * 2021-7-21: Fixed corner case
 * 2021-7-15: Improved performance
 * 2021-7-10: Handled mutliple user types
 */
function generateCanonicalLink(user) {
  // const session = getUserSession(user)
  const session = user.getSession();
  // ...
}

// 正确 ✅
function generateCanonicalLink(user) {
  const session = user.getSession();
  // ...
}

This article briefly discusses some ES6 code. Most of the principles can be applied to other programming languages. Using these principles may take time, but in the long run it can guarantee your code. The readability and scalability.


夜色镇歌
55 声望2 粉丝