当前位置: 首页 > news >正文

淄博网站制作定制ps个人网站建设

淄博网站制作定制,ps个人网站建设,获取网站状态,如何做优酷网站赚钱Variables:变量 使用有意义的可发音的变量名 Bad: var yyyymmdstr moment().format(YYYY/MM/DD);Good: var yearMonthDay moment().format(YYYY/MM/DD);使用可搜索的命名 在开发过程中#xff0c;我们阅读代码的时间会远远超过编写代码的时间#xff0c;因此保证代码的可读… Variables:变量 使用有意义的可发音的变量名 Bad: var yyyymmdstr moment().format(YYYY/MM/DD);Good: var yearMonthDay moment().format(YYYY/MM/DD);使用可搜索的命名 在开发过程中我们阅读代码的时间会远远超过编写代码的时间因此保证代码的可读性与可搜索会非常重要。切记没事不要坑自己。 Bad: //525600到底啥意思 for (var i 0; i 525600; i) {runCronJob(); }Good: // 声明为全局变量 var MINUTES_IN_A_YEAR 525600; for (var i 0; i MINUTES_IN_A_YEAR; i) {runCronJob(); }使用说明性质的临时变量 Bad: let cityStateRegex /^(.)[,\\s](.?)\s*(\d{5})?$/; saveCityState(cityStateRegex.match(cityStateRegex)[1], cityStateRegex.match(cityStateRegex)[2]);Good: let cityStateRegex /^(.)[,\\s](.?)\s*(\d{5})?$/; let match cityStateRegex.match(cityStateRegex) let city match[1]; let state match[2]; saveCityState(city, state);避免摸不着头脑的临时变量 在遍历或者mapping过程中需要避免短小无意义的变量命名。 Bad: var locations [Austin, New York, San Francisco]; locations.forEach((l) {doStuff();doSomeOtherStuff();.........// Wait, what is l for again?dispatch(l); });Good: var locations [Austin, New York, San Francisco]; locations.forEach((location) {doStuff();doSomeOtherStuff();.........dispatch(location); });避免添加不需要的内容 如果你的类名/实例名已经能够表述某些信息那么在类/实例的属性中就不需要重复命名。 Bad: var Car {carMake: Honda,carModel: Accord,carColor: Blue };function paintCar(car) {car.carColor Red; }Good: var Car {make: Honda,model: Accord,color: Blue };function paintCar(car) {car.color Red; }Short-circuiting 优于条件选择 Bad: function createMicrobrewery(name) {var breweryName;if (name) {breweryName name;} else {breweryName Hipster Brew Co.;} }Good: function createMicrobrewery(name) {var breweryName name || Hipster Brew Co. }函数 函数参数最好不超过两个 限制函数的参数数目还是比较重要的它能够方便对于函数的测试避免需要进行不同的Case测试时把代码变得一团糟。我们应该尽可能地控制参数数目小于或等于两个如果你的参数数目多于两个那么建议使用高阶对象进行适当封装。 Bad: function createMenu(title, body, buttonText, cancellable) {... }Good: var menuConfig {title: Foo,body: Bar,buttonText: Baz,cancellable: true }function createMenu(menuConfig) {... }函数应当遵循单一职责原则 这一条算是迄今为止软件工程中最重要的原则之一了。如果我们给单一函数赋予了过多的职责那么其很难被用于组合、测试等。而如果你保证函数的单一职责性质那么相对其重构难度、代码可读性也会更好。 Bad: function emailClients(clients) {clients.forEach(client {let clientRecord database.lookup(client);if (clientRecord.isActive()) {email(client);}}); }Good: function emailClients(clients) {clients.forEach(client {emailClientIfNeeded(client);}); }function emailClientIfNeeded(client) {if (isClientActive(client)) {email(client);} }function isClientActive(client) {let clientRecord database.lookup(client);return clientRecord.isActive(); }函数命名应该反映其功能 Bad: function dateAdd(date, month) {// ... }let date new Date();// 很难从函数名中获知该函数到底是谁加上谁 dateAdd(date, 1);Good: function dateAddMonth(date, month) {// ... }let date new Date(); dateAddMonth(date, 1);函数应当只是一层抽象 这一条类似于单一职责原则不过更倾向于关注函数的抽象程度如果我们在单一函数中添加了过多的抽象层同样会降低的函数可读性、增加重构难度。 Bad: function parseBetterJSAlternative(code) {let REGEXES [// ...];let statements code.split( );let tokens;REGEXES.forEach((REGEX) {statements.forEach((statement) {// ...})});let ast;tokens.forEach((token) {// lex...});ast.forEach((node) {// parse...}) }Good: function tokenize(code) {let REGEXES [// ...];let statements code.split( );let tokens;REGEXES.forEach((REGEX) {statements.forEach((statement) {// ...})});return tokens; }function lexer(tokens) {let ast;tokens.forEach((token) {// lex...});return ast; }function parseBetterJSAlternative(code) {let tokens tokenize(code);let ast lexer(tokens);ast.forEach((node) {// parse...}) }移除重复代码 在任何情况下都不要去容许重复代码的存在。重复代码指那些修改单一逻辑时需要修改多个代码片的代码交集JavaScript本身是弱类型语言相对而言编写泛型函数会更加容易。 Bad: function showDeveloperList(developers) {developers.forEach(developers {var expectedSalary developer.calculateExpectedSalary();var experience developer.getExperience();var githubLink developer.getGithubLink();var data {expectedSalary: expectedSalary,experience: experience,githubLink: githubLink};render(data);}); }function showManagerList(managers) {managers.forEach(manager {var expectedSalary manager.calculateExpectedSalary();var experience manager.getExperience();var portfolio manager.getMBAProjects();var data {expectedSalary: expectedSalary,experience: experience,portfolio: portfolio};render(data);}); }Good: function showList(employees) {employees.forEach(employee {var expectedSalary employee.calculateExpectedSalary();var experience employee.getExperience();var portfolio;if (employee.type manager) {portfolio employee.getMBAProjects();} else {portfolio employee.getGithubLink();}var data {expectedSalary: expectedSalary,experience: experience,portfolio: portfolio};render(data);}); }使用默认参数代替或运算 Bad: function writeForumComment(subject, body) {subject subject || No Subject;body body || No text; }Good: function writeForumComment(subject No subject, body No text) {... }使用 Object.assign 设置默认值 Bad: var menuConfig {title: null,body: Bar,buttonText: null,cancellable: true }function createMenu(config) {config.title config.title || Fooconfig.body config.body || Barconfig.buttonText config.buttonText || Bazconfig.cancellable config.cancellable undefined ? config.cancellable : true;}createMenu(menuConfig);Good: var menuConfig {title: null,body: Bar,buttonText: null,cancellable: true }function createMenu(config) {Object.assign(config, {title: Foo,body: Bar,buttonText: Baz,cancellable: true}); }createMenu(menuConfig);避免在参数中使用Flags 有的开发者会使用Flags来控制函数执行不同的逻辑流不过就如我们在上文中提及的单一职责原则我们应当将函数拆分为不同的部分然后在外层调用上根据Flags调用不同的函数。 Bad: function createFile(name, temp) {if (temp) {fs.create(./temp/ name);} else {fs.create(name);} }Good: function createTempFile(name) {fs.create(./temp/ name); }function createFile(name) {fs.create(name); }避免冗余副作用 如果某个函数除了接收输入值与返回值之外还做了其他事那么就称其具有副作用。典型的副作用譬如写文件、修改某些全局变量、修改内存参数等等。在编程中我们不可避免的需要产生副作用譬如上面例子中我们需要写入到某个外部文件。而你应当做的就是将所有的写文件操作由某个服务统一处理而不应该将写文件的操作分散到数个类或者函数中。这一点最大的优势在于避免了不同对象之间共享状态共享的可变状态可是万恶之源啊。 Bad: // 定义全局变量 // 如果我们有其他的函数引用了该变量那么我们就无法预测该变量类型 var name Ryan McDermott;function splitIntoFirstAndLastName() {name name.split( ); }splitIntoFirstAndLastName();console.log(name); // [Ryan, McDermott]; Good: function splitIntoFirstAndLastName(name) {return name.split( ); }var name Ryan McDermott var newName splitIntoFirstAndLastName(name);console.log(name); // Ryan McDermott; console.log(newName); // [Ryan, McDermott]; 避免污染全局函数 JavaScript中有个不太好的实践就是修改某个全局函数将其指向其他的库或者自定义函数不过这个会对某个懵懂的用户造成困恼。如果你想给JavaScript原生的Array添加一个diff函数支持来展示两个数组的差异。你可以选择将函数挂载到Array.prototype不过很有可能跟其他打算占用这个位置的库起冲突。我们更建议使用ES6的classes并且使用继承方式去添加新的功能函数。 Bad: Array.prototype.diff function(comparisonArray) {var values [];var hash {};for (var i of comparisonArray) {hash[i] true;}for (var i of this) {if (!hash[i]) {values.push(i);}}return values; }Good: class SuperArray extends Array {constructor(...args) {super(...args);}diff(comparisonArray) {var values [];var hash {};for (var i of comparisonArray) {hash[i] true;}for (var i of this) {if (!hash[i]) {values.push(i);}}return values;} }优先选择函数式编程而不是命令式编程 JavaScript并不像Haskell这样纯粹的函数式编程语言不过其对于实践函数式编程的理念还是很推崇的。函数式编程可读性更好也更易于测试。 Bad: const programmerOutput [{name: Uncle Bobby,linesOfCode: 500}, {name: Suzie Q,linesOfCode: 1500}, {name: Jimmy Gosling,linesOfCode: 150}, {name: Gracie Hopper,linesOfCode: 1000} ];var totalOutput 0;for (var i 0; i programmerOutput.length; i) {totalOutput programmerOutput[i].linesOfCode; }Good: const programmerOutput [{name: Uncle Bobby,linesOfCode: 500}, {name: Suzie Q,linesOfCode: 1500}, {name: Jimmy Gosling,linesOfCode: 150}, {name: Gracie Hopper,linesOfCode: 1000} ];var totalOutput programmerOutput.map((programmer) programmer.linesOfCode).reduce((acc, linesOfCode) acc linesOfCode, 0);封装条件选择 Bad: if (fsm.state fetching isEmpty(listNode)) {/// ... }Good: function shouldShowSpinner(fsm, listNode) {return fsm.state fetching isEmpty(listNode); }if (shouldShowSpinner(fsmInstance, listNodeInstance)) {// ... }避免负类条件 Bad: function isDOMNodeNotPresent(node) {// ... }if (!isDOMNodeNotPresent(node)) {// ... }Good: function isDOMNodePresent(node) {// ... }if (isDOMNodePresent(node)) {// ... }避免使用条件选择 很多人第一次听到这个概念都会觉得不可思议没有if条件选择语句的话又该如何编程呢在这里我们推荐使用多态性来达成这一目标因为如果在函数或类中嵌入过多的if语句会导致该函数或者类破坏单一职责原则。 Bad: class Airplane {//...getCruisingAltitude() {switch (this.type) {case 777:return getMaxAltitude() - getPassengerCount();case Air Force One:return getMaxAltitude();case Cesna:return getMaxAltitude() - getFuelExpenditure();}} }Good: class Airplane {//... }class Boeing777 extends Airplane {//...getCruisingAltitude() {return getMaxAltitude() - getPassengerCount();} }class AirForceOne extends Airplane {//...getCruisingAltitude() {return getMaxAltitude();} }class Cesna extends Airplane {//...getCruisingAltitude() {return getMaxAltitude() - getFuelExpenditure();} }避免依赖于类型检测 很多时候我们会依赖于JavaScript输入的参数类型来进入不同的控制流不过鉴于JavaScript本身是弱类型语言我们还是应该避免这种实践。第一个方法就是使用较为一致性的接口。 Bad: function travelToTexas(vehicle) {if (vehicle instanceof Bicycle) {vehicle.peddle(this.currentLocation, new Location(texas));} else if (vehicle instanceof Car) {vehicle.drive(this.currentLocation, new Location(texas));} }Good: function travelToTexas(vehicle) {vehicle.move(this.currentLocation, new Location(texas)); }避免依赖于类型检测 如果你需要操作像字符串、数值、列表这样的基础数据类型你就无法依赖于多态性来实现类型检测。那么建议是使用TypeScript它为普通的JavaScript添加了静态类型支持。 Bad: function combine(val1, val2) {if (typeof val1 number typeof val2 number ||typeof val1 string typeof val2 string) {return val1 val2;} else {throw new Error(Must be of type String or Number);} }Good: function combine(val1, val2) {return val1 val2; }避免过度优化 现代浏览器已经在运行时做了很多的优化因此很多时候如果我们要遵循那些流传已久的优化策略不过是浪费时间。可以参考这个来获取建议的优化要点。 Bad: // On old browsers, each iteration would be costly because len would be // recomputed. In modern browsers, this is optimized. for (var i 0, len list.length; i len; i) {// ... }Good: for (var i 0; i list.length; i) {// ... }移除弃用的代码 弃用的代码就和重复的代码一样我们没有任何理由保留他们。不过为防万一建议不要彻底从Git的历史记录中删除它们。 Bad: function oldRequestModule(url) {// ... }function newRequestModule(url) {// ... }var req newRequestModule; inventoryTracker(apples, req, www.inventory-awesome.io);Good: function newRequestModule(url) {// ... }var req newRequestModule; inventoryTracker(apples, req, www.inventory-awesome.io);对象与数据结构 使用getters与setters 在JavaScript的对象属性读写中建议使用getter或者setter而不是直接读取或者赋值。不过JavaScript并没有类似于public或者private这样的关键字因此很难通过接口方式进行强限制。不过鉴于以下优势我们还是强烈建议使用getter或者setter: 1.如果你打算不仅仅是直接获取原始值使用getter能够避免去修改每个取值的地方。 2.使用set能够方便地添加校验。 封装内部表述。 便于添加日志与错误处理。 通过继承能够复写默认功能。 支持属性懒加载。 Bad: class BankAccount {constructor() {this.balance 1000;} }let bankAccount new BankAccount();// Buy shoes... bankAccount.balance bankAccount.balance - 100;Good: class BankAccount {constructor() {this.balance 1000;}// It doesnt have to be prefixed with get or set to be a getter/setterwithdraw(amount) {if (verifyAmountCanBeDeducted(amount)) {this.balance - amount;}} }let bankAccount new BankAccount();// Buy shoes... bankAccount.withdraw(100);为对象添加私有属性 可以通过闭包方式添加私有属性 Bad: var Employee function(name) {this.name name; }Employee.prototype.getName function() {return this.name; }var employee new Employee(John Doe); console.log(Employee name: employee.getName()); // Employee name: John Doe delete employee.name; console.log(Employee name: employee.getName()); // Employee name: undefined Good: var Employee (function() {function Employee(name) {this.getName function() {return name;};}return Employee; }());var employee new Employee(John Doe); console.log(Employee name: employee.getName()); // Employee name: John Doe delete employee.name; console.log(Employee name: employee.getName()); // Employee name: John Doe 类 单一职责原则 便如Clean Code中所述不应该为了多个理由去更改某个类的代码这样会把某个类塞入过多的功能。最小化你需要去改变某个类的次数对于保证代码的稳定性至关重要过多的改变代码会影响代码库中依赖于该类的其他模块。 Bad: class UserSettings {constructor(user) {this.user user;}changeSettings(settings) {if (this.verifyCredentials(user)) {// ...}}verifyCredentials(user) {// ...} }Good: class UserAuth {constructor(user) {this.user user;}verifyCredentials() {// ...} }class UserSettings {constructor(user) {this.user user;this.auth new UserAuth(user)}changeSettings(settings) {if (this.auth.verifyCredentials()) {// ...}} }开放封闭原则 正如Bertrand Meyer所述譬如类、模块、函数这样的实体应该面向扩展开放而拒绝修改。换言之我们推荐去继承扩展某个函数或模块而不是每次都去修改源代码。 Bad: class AjaxRequester {constructor() {// What if we wanted another HTTP Method, like DELETE? We would have to // open this file up and modify this and put it in manually. this.HTTP_METHODS [POST, PUT, GET];}get(url) {// ...}}Good: class AjaxRequester {constructor() {this.HTTP_METHODS [POST, PUT, GET];}get(url) {// ...}addHTTPMethod(method) {this.HTTP_METHODS.push(method);} }里氏替换原则 这个原则听起来有点拗口不过概念却很好理解。其形式化描述为如果S为T的子类型那么类型T的实例可以被类型S的实例替换而不需要修改任何的代码。形象而言我们创建的父类与其子类应当可交换地使用而不会引起异常譬如下文的Square-Rectangle这个例子。Square也是Rectangle Bad: class Rectangle {constructor() {this.width 0;this.height 0;}setColor(color) {// ...}render(area) {// ...}setWidth(width) {this.width width;}setHeight(height) {this.height height;}getArea() {return this.width * this.height;} }class Square extends Rectangle {constructor() {super();}setWidth(width) {this.width width;this.height width;}setHeight(height) {this.width height;this.height height;} }function renderLargeRectangles(rectangles) {rectangles.forEach((rectangle) {rectangle.setWidth(4);rectangle.setHeight(5);let area rectangle.getArea(); // BAD: Will return 25 for Square. Should be 20.rectangle.render(area);}) }let rectangles [new Rectangle(), new Rectangle(), new Square()]; renderLargeRectangles(rectangles);Good: class Shape {constructor() {}setColor(color) {// ...}render(area) {// ...} }class Rectangle extends Shape {constructor() {super();this.width 0;this.height 0;}setWidth(width) {this.width width;}setHeight(height) {this.height height;}getArea() {return this.width * this.height;} }class Square extends Shape {constructor() {super();this.length 0;}setLength(length) {this.length length;}getArea() {return this.length * this.length;} }function renderLargeShapes(shapes) {shapes.forEach((shape) {switch (shape.constructor.name) {case Square:shape.setLength(5);case Rectangle:shape.setWidth(4);shape.setHeight(5);}let area shape.getArea();shape.render(area);}) }let shapes [new Rectangle(), new Rectangle(), new Square()]; renderLargeShapes(shapes);接口隔离原则 JavaScript本身并不包含对于接口语法的支持因此也无法像其他语言那样达到严格限制的程度。不过鉴于JavaScript本身类型系统的缺失遵循接口隔离原则还是蛮重要的。ISP的表述为不应该强制客户端去依赖于他们不需要的接口这一点在JavaScript中较为典型的例子就是那些需要大量配置信息的对象。其实使用者并不需要去关心每一个配置项允许他们动态的设置能够节省大量的时间代码的可读性也会更好。 Bad: class DOMTraverser {constructor(settings) {this.settings settings;this.setup();}setup() {this.rootNode this.settings.rootNode;this.animationModule.setup();}traverse() {// ...} }let $ new DOMTraverser({rootNode: document.getElementsByTagName(body),animationModule: function() {} // Most of the time, we wont need to animate when traversing. // ... });Good: class DOMTraverser {constructor(settings) {this.settings settings;this.options settings.options;this.setup();}setup() {this.rootNode this.settings.rootNode;this.setupOptions();}setupOptions() {if (this.options.animationModule) {// ...}}traverse() {// ...} }let $ new DOMTraverser({rootNode: document.getElementsByTagName(body),options: { animationModule: function() {}} });依赖反转原则 This principle states two essential things: High-level modules should not depend on low-level modules. Both should on abstractions. Abstractions should not depend upon details. Details should depend onabstractions. This can be hard to understand at first, but if youve worked with Angular.js, youve seen an implementation of this principle in the form of Dependency Injection (DI). While they are not identical concepts, DIP keeps high-level modules from knowing the details of its low-level modules and setting them up. It can accomplish this through DI. A huge benefit of this is that it reduces the coupling between modules. Coupling is a very bad development pattern because it makes your code hard to refactor. As stated previously, JavaScript doesnt have interfaces so the abstractions that are depended upon are implicit contracts. That is to say, the methods and properties that an object/class exposes to another object/class. In the example below, the implicit contract is that any Request module for an InventoryTracker will have a requestItems method. Bad: class InventoryTracker {constructor(items) {this.items items;// BAD: We have created a dependency on a specific request implementation. // We should just have requestItems depend on a request method: request this.requester new InventoryRequester();}requestItems() {this.items.forEach((item) {this.requester.requestItem(item);});} }class InventoryRequester {constructor() {this.REQ_METHODS [HTTP];}requestItem(item) {// ...} }let inventoryTracker new InventoryTracker([apples, bananas]); inventoryTracker.requestItems();Good: class InventoryTracker {constructor(items, requester) {this.items items;this.requester requester;}requestItems() {this.items.forEach((item) {this.requester.requestItem(item);});} }class InventoryRequesterV1 {constructor() {this.REQ_METHODS [HTTP];}requestItem(item) {// ...} }class InventoryRequesterV2 {constructor() {this.REQ_METHODS [WS];}requestItem(item) {// ...} }// By constructing our dependencies externally and injecting them, we can easily // substitute our request module for a fancy new one that uses WebSockets. let inventoryTracker new InventoryTracker([apples, bananas], new InventoryRequesterV2()); inventoryTracker.requestItems();优先选择ES6类而不是ES5的基本函数定义 传统ES5的类实现语法对于类的继承、构建以及方法定义的可读性都不是很好。如果你考虑在类中实现继承那么建议优先考虑ES6的类语法糖。如果你只是需要构建简单的对象那么可以考虑使用ES5的基本函数定义来构造类对象。 Bad: var Animal function(age) {if (!(this instanceof Animal)) {throw new Error(Instantiate Animal with new);}this.age age; };Animal.prototype.move function() {};var Mammal function(age, furColor) {if (!(this instanceof Mammal)) {throw new Error(Instantiate Mammal with new);}Animal.call(this, age);this.furColor furColor; };Mammal.prototype Object.create(Animal.prototype); Mammal.prototype.constructor Mammal; Mammal.prototype.liveBirth function() {};var Human function(age, furColor, languageSpoken) {if (!(this instanceof Human)) {throw new Error(Instantiate Human with new);}Mammal.call(this, age, furColor);this.languageSpoken languageSpoken; };Human.prototype Object.create(Mammal.prototype); Human.prototype.constructor Human; Human.prototype.speak function() {};Good: class Animal {constructor(age) {this.age age;}move() {} }class Mammal extends Animal {constructor(age, furColor) {super(age);this.furColor furColor;}liveBirth() {} }class Human extends Mammal {constructor(age, furColor, languageSpoken) {super(age, furColor);this.languageSpoken languageSpoken;}speak() {} }Use method chaining Against the advice of Clean Code, this is one place where we will have to differ. It has been argued that method chaining is unclean and violates the Law of Demeter. Maybe its true, but this pattern is very useful in JavaScript and you see it in many libraries such as jQuery and Lodash. It allows your code to be expressive, and less verbose. For that reason, I say, use method chaining and take a look at how clean your code will be. In your class functions, simply return this at the end of every function, and you can chain further class methods onto it. Bad: class Car {constructor() {this.make Honda;this.model Accord;this.color white;}setMake(make) {this.name name;}setModel(model) {this.model model;}setColor(color) {this.color color;}save() {console.log(this.make, this.model, this.color);} }let car new Car(); car.setColor(pink); car.setMake(Ford); car.setModel(F-150) car.save();Good: class Car {constructor() {this.make Honda;this.model Accord;this.color white;}setMake(make) {this.name name;// NOTE: Returning this for chaining return this;}setModel(model) {this.model model;// NOTE: Returning this for chaining return this;}setColor(color) {this.color color;// NOTE: Returning this for chaining return this;}save() {console.log(this.make, this.model, this.color);} }let car new Car().setColor(pink).setMake(Ford).setModel(F-150).save();Prefer composition over inheritance As stated famously in the Gang of Four, you should prefer composition over inheritance where you can. There are lots of good reasons to use inheritance and lots of good reasons to use composition. The main point for this maxim is that if your mind instinctively goes for inheritance, try to think if composition could model your problem better. In some cases it can. You might be wondering then, when should I use inheritance? It depends on your problem at hand, but this is a decent list of when inheritance makes more sense than composition: Your inheritance represents an is-a relationship and not a has-a (Animal-Human vs. User-UserDetails). You can reuse code from the base classes (Humans can move like all animals). You want to make global changes to derived classes by changing a base class.(Change the caloric expenditure of all animals when they move). Bad: class Employee {constructor(name, email) {this.name name;this.email email;}// ... }// Bad because Employees have tax data. EmployeeTaxData is not a type of Employee class EmployeeTaxData extends Employee {constructor(ssn, salary) {super();this.ssn ssn;this.salary salary;}// ... }Good: class Employee {constructor(name, email) {this.name name;this.email email;}setTaxData(ssn, salary) {this.taxData new EmployeeTaxData(ssn, salary);}// ... }class EmployeeTaxData {constructor(ssn, salary) {this.ssn ssn;this.salary salary;}// ... }测试 测试是代码部署前不可避免的重要步骤如果你没有添加任何的测试那么你在每次部署之前你压根不敢确定是否会产生什么意外情况。不同的团队对于测试覆盖率的需求不太一致不过保持100%的覆盖率能够让你的团队对于代码保持较好的掌控与信赖。我们可以使用很多优秀的测试工具与测试覆盖率检测工具建议是对于每个新的特征或者模块都添加测试用例。如果更倾向于使用测试驱动开发一定要注意在你打算添加新的特性或者重构当前代码之前保证测试覆盖率已经达到了预期。 每个测试用例单一目标 Bad: const assert require(assert);describe(MakeMomentJSGreatAgain, function() {it(handles date boundaries, function() {let date;date new MakeMomentJSGreatAgain(1/1/2015);date.addDays(30);date.shouldEqual(1/31/2015);date new MakeMomentJSGreatAgain(2/1/2016);date.addDays(28);assert.equal(02/29/2016, date);date new MakeMomentJSGreatAgain(2/1/2015);date.addDays(28);assert.equal(03/01/2015, date);}); });Good: const assert require(assert);describe(MakeMomentJSGreatAgain, function() {it(handles 30-day months, function() {let date new MakeMomentJSGreatAgain(1/1/2015);date.addDays(30);date.shouldEqual(1/31/2015);});it(handles leap year, function() {let date new MakeMomentJSGreatAgain(2/1/2016);date.addDays(28);assert.equal(02/29/2016, date);});it(handles non-leap year, function() {let date new MakeMomentJSGreatAgain(2/1/2015);date.addDays(28);assert.equal(03/01/2015, date);}); });并发 使用Promise替代回调 回调含义不清晰还会导致过深的代码嵌套就是所谓的回调地狱。在ES6中Promises已经是内置的全局类型。 Bad: require(request).get(https://en.wikipedia.org/wiki/Robert_Cecil_Martin, function(err, response) {if (err) {console.error(err);}else {require(fs).writeFile(article.html, response.body, function(err) {if (err) {console.error(err);} else {console.log(File written);}})} })Good: require(request-promise).get(https://en.wikipedia.org/wiki/Robert_Cecil_Martin).then(function(response) {return require(fs-promise).writeFile(article.html, response);}).then(function() {console.log(File written);}).catch(function(err) {console.log(err);})Async/Await 更为清晰 Promises本身已经是对于回调的不错的替代而ES7中的async与await则是更为清晰的解决方案可以避免你编写大量的then调用链。 Bad: require(request-promise).get(https://en.wikipedia.org/wiki/Robert_Cecil_Martin).then(function(response) {return require(fs-promise).writeFile(article.html, response);}).then(function() {console.log(File written);}).catch(function(err) {console.log(err);})Good: async function getCleanCodeArticle() {try {var request await require(request-promise)var response await request.get(https://en.wikipedia.org/wiki/Robert_Cecil_Martin);var fileHandle await require(fs-promise);await fileHandle.writeFile(article.html, response);console.log(File written);} catch(err) {console.log(err);}}格式化 就像本文的很多建议一样格式化本身是非常主观的原则。建议是使用工具 来自动完成格式化操作而不是争论具体的格式化的细节。 相似含义变量的大写一致性 JavaScript本身是无类型的因此变量名大写也能传递很多有用的信息。这个规则算是比较主观的建议团队可以根据自己的内部规范将相同含义变量的大小写保持一致性。 Bad: var DAYS_IN_WEEK 7; var daysInMonth 30;var songs [Back In Black, Stairway to Heaven, Hey Jude]; var Artists [ACDC, Led Zeppelin, The Beatles];function eraseDatabase() {} function restore_database() {}class animal {} class Alpaca {}Good: var DAYS_IN_WEEK 7; var DAYS_IN_MONTH 30;var songs [Back In Black, Stairway to Heaven, Hey Jude]; var artists [ACDC, Led Zeppelin, The Beatles];function eraseDatabase() {} function restoreDatabase() {}class Animal {} class Alpaca {}函数的定义与调用位置尽量靠近 尽量将两个有相互调用关系的函数在源文件的竖直上较为接近的位置并且将调用者放置于被调用者上方。我们习惯从上至下的阅读代码这样的布局会提高整个代码的可读性。 Bad: class PerformanceReview {constructor(employee) {this.employee employee;}lookupPeers() {return db.lookup(this.employee, peers);}lookupMananger() {return db.lookup(this.employee, manager);}getPeerReviews() {let peers this.lookupPeers();// ...}perfReview() {getPeerReviews();getManagerReview();getSelfReview();}getManagerReview() {let manager this.lookupManager();}getSelfReview() {// ...} }let review new PerformanceReview(user); review.perfReview();Good: class PerformanceReview {constructor(employee) {this.employee employee;}perfReview() {getPeerReviews();getManagerReview();getSelfReview();}getPeerReviews() {let peers this.lookupPeers();// ...}lookupPeers() {return db.lookup(this.employee, peers);}getManagerReview() {let manager this.lookupManager();}lookupMananger() {return db.lookup(this.employee, manager);}getSelfReview() {// ...} }let review new PerformanceReview(employee); review.perfReview();注释 避免保留被注释的代码 Bad: doStuff(); // doOtherStuff(); // doSomeMoreStuff(); // doSoMuchStuff(); Good: doStuff();不要使用日记形式的注释 千万记住要使用版本控制工具而不是在你的代码前面添加日记形式的注释使用git log查看历史记录。 Bad: /*** 2016-12-20: Removed monads, didnt understand them (RM)* 2016-10-01: Improved using special monads (JP)* 2016-02-03: Removed type-checking (LI)* 2015-03-14: Added combine with type-checking (JR)*/ function combine(a, b) {return a b; }Good: function combine(a, b) {return a b; }避免额外的代码标记注释 建议是让函数与变量名来表述其功能避免添加过多额外的注释。 Bad: // Scope Model Instantiationlet $scope.model {menu: foo,nav: bar };// Action setuplet actions function() {// ... }Good: let $scope.model {menu: foo,nav: bar };let actions function() {// ... }原文发布时间2017-01-07 原文作者kimyeongnam 本文来源掘金如需转载请紧急联系作者
http://www.pierceye.com/news/507964/

相关文章:

  • 如何提高网站的点击率域名空间网站推广
  • 上海松江做网站建设wordpress 拒绝连接
  • 有免费的个人网站吗富德生命人寿保险公司官方网站保单服务
  • 网站备案 子域名网页视频制作软件
  • 空间 网站网站建设哪个好
  • 公司网站域名价格云南免费网站建设
  • 网站跳转域名不变常见网站架构
  • 山东省建设厅电工证查询网站网站标题的选择
  • 网站建设是属于软件吗电话销售哪里找客户电话
  • 用vue做网站的实例网站制作郑州
  • 五个网站想自己在家做外贸网站
  • 收费的电影网站怎么做网页设计图片的应用
  • 班级网站建设步骤橘子皮主题wordpress
  • 网站模板源文件网站制作需求文档
  • 青岛注册公司网站建网站需要那些步骤
  • 深圳做网上商城网站小蘑菇网站建设软件
  • 广州住建网站网站空间购买价格
  • 金华永康网站建设公司做网站的优点
  • 有免费的微网站制作吗瑞安哪里有培训做网站的
  • 苏州住房和城乡建设局网站wordpress中文书
  • 盐城市滨海县建设局网站wordpress 4.8.1 漏洞
  • 荆州市城市建设投资开发有限公司网站百度人工服务24小时
  • 永久域名购买昆明网站建设优化企业
  • 自适应网站模板下载网页设计培训哪好
  • 做门窗网站便宜的vps租用网站
  • 龙岗附近公司做网站建设多少钱公司行业类型有哪些
  • 188旅游网站管理系统源码做外贸有那些网站平台
  • 江苏网站建设要多少钱近三个月以来的国际新闻
  • 旬阳做网站免费漫画软件
  • asp相册网站源码企业网站建设的上市公司