软件工程原理,来自罗伯特·C·马丁代码的书,由JavaScript进行了空气。这不是一种样式的方法。它是可读程序,可重复使用和重新制造的Java脚本的生产指南。
并非必须准确地遵循这里的每个原则,甚至比全球同意的原则要少。这些是准则,不再是指南,但是它们是通过清洁代码_多年的集体经验的准则。
软件工程的寿命超过50年,我们仍然学到很多东西。 “当软件工程旧时,工程本身就是本身,”也许我们将有更多困难的规则。现在,让这些准则作为测试,以评估您和您的团队生产的JavaScript代码的质量。
另一件事:了解这些原则不会使您立即成为有史以来最好的程序员,并且与他们合作多年并不意味着您不会犯错误。代码的每个部分都是从初稿开始的,例如在湿的粘土上工作,该粘土不会从一见钟觉上获得最终形状,因为我们总是在何时消除缺陷。我们与同行一起审查。因此,由于初稿需要改进,不要按自己。改用代码!
坏的:
const yyyymmdstr = moment ( ) . format ( "YYYY/MM/DD" )好的:
const currentDate = moment ( ) . format ( "YYYY/MM/DD" )⬆回到顶部
坏的:
getUserInfo ( )
getClientData ( )
getCustomerRecord ( )好的:
getUser ( )⬆回到顶部
我们将读取的代码超出我们的编写。重要的是,我们编写的代码是可读和研究的。不要命名最终了解我们程序的变量,这使读者很难。搜索您的名字。 Buddy.js和Eslint等工具可以帮助确定未命名的常数。
坏的:
// What the heck is 86400000 for?
setTimeout ( blastOff , 86400000 )好的:
// Declare them as capitalized named constants.
const MILLISECONDS_PER_DAY = 60 * 60 * 24 * 1000 //86400000;
setTimeout ( blastOff , MILLISECONDS_PER_DAY )⬆回到顶部
坏的:
const address = "One Infinite Loop, Cupertino 95014"
const cityZipCodeRegex = / ^[^,\]+[,\s]+(.+?)s*(d{5})?$ /
saveCityZipCode (
address . match ( cityZipCodeRegex ) [ 1 ] ,
address . match ( cityZipCodeRegex ) [ 2 ]
)好的:
const address = "One Infinite Loop, Cupertino 95014"
const cityZipCodeRegex = / ^[^,\]+[,\s]+(.+?)s*(d{5})?$ /
const [ _ , city , zipCode ] = address . match ( cityZipCodeRegex ) || [ ]
saveCityZipCode ( city , zipCode )⬆回到顶部
总是比隐式更好。
坏的:
const locations = [ "Austin" , "New York" , "San Francisco" ]
locations . forEach ( ( l ) => {
doStuff ( )
doSomeOtherStuff ( )
// ...
// ...
// ...
// Wait, what is `l` for again?
dispatch ( l )
} )好的:
const locations = [ "Austin" , "New York" , "San Francisco" ]
locations . forEach ( ( location ) => {
doStuff ( )
doSomeOtherStuff ( )
// ...
// ...
// ...
dispatch ( location )
} )⬆回到顶部
如果名称类/对象告诉您一些东西,请不要在变量名称中重复此操作。
坏的:
const Car = {
carMake : "Honda" ,
carModel : "Accord" ,
carColor : "Blue" ,
}
function paintCar ( car , color ) {
car . carColor = color
}好的:
const Car = {
make : "Honda" ,
model : "Accord" ,
color : "Blue" ,
}
function paintCar ( car , color ) {
car . color = color
}⬆回到顶部
默认论点是离线的。 bey,如果您是我们,您的功能只会为undefined参数提供默认值。其他“虚假的”值su '' , "" false , null , 0和NaN不会被默认值所掩盖。
坏的:
function createMicrobrewery ( name ) {
const breweryName = name || "Hipster Brew Co."
// ...
}好的:
function createMicrobrewery ( name = "Hipster Brew Co." ) {
// ...
}⬆回到顶部
获得阅读类的继承,建立和经典的ES5类定义非常困难。如果您需要遗传(并且要知道您可能不需要它),那么您将更喜欢ES2015/ES6类。但是,请尝试在课堂上保持小功能,以便您发现自己需要更大,更复杂的功能。
坏的:
const Animal = function ( age ) {
if ( ! ( this instanceof Animal ) ) {
throw new Error ( "Instantiate Animal with `new`" )
}
this . age = age
}
Animal . prototype . move = function move ( ) { }
const 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 liveBirth ( ) { }
const 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 speak ( ) { }好的:
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 ( ) {
/* ... */
}
}⬆回到顶部
这种样式在Java脚本中非常有用,并且在Jquey和Lodash等许多库中都可以看到它。它允许表示您的代码,而八卦最少。由于这个原因,我建议使用序列方法,并查看您的代码的清洁程度。在类功能中,您只需要在每个功能的末尾返回此功能,就可以连接其他类方法。
坏的:
class Car {
constructor ( make , model , color ) {
this . make = make
this . model = model
this . color = color
}
setMake ( make ) {
this . make = make
}
setModel ( model ) {
this . model = model
}
setColor ( color ) {
this . color = color
}
save ( ) {
console . log ( this . make , this . model , this . color )
}
}
const car = new Car ( "Ford" , "F-150" , "red" )
car . setColor ( "pink" )
car . save ( )好的:
class Car {
constructor ( make , model , color ) {
this . make = make
this . model = model
this . color = color
}
setMake ( make ) {
this . make = make
// 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 )
// NOTE: Returning this for chaining
return this
}
}
const car = new Car ( "Ford" , "F-150" , "red" ) . setColor ( "pink" ) . save ( )⬆回到顶部
如[设计模式](https://en.wikipedia.org/wiki/design_patterns)中所述,四大的团伙,您应该在可以的情况下而不是继承。脸部使用遗传和使用构图的许多面孔的原因很多。该原则的重点是,如果您的思想安装了继承,请尝试考虑是否可以更好地解决您的问题。在某些情况下可以。
在此之后,您可能会想知道“我什么时候应该使用继承?”这取决于您要解决的问题,但是当继承比组成更合乎逻辑时,这是一个不错的列表:
您的继承是一种关系“而不是”有“有”关系(人类 - > Animal对面的用户 - >用户详细信息)。
您可以从基本类中重复使用代码(人类可以像所有动物一样移动)。
您想通过更改基本类对派生类进行一般更改。 (移动时所有动物的卡路里)。
坏的:
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
}
// ...
}好的:
class EmployeeTaxData {
constructor ( ssn , salary ) {
this . ssn = ssn
this . salary = salary
}
// ...
}
class Employee {
constructor ( name , email ) {
this . name = name
this . email = email
}
setTaxData ( ssn , salary ) {
this . taxData = new EmployeeTaxData ( ssn , salary )
}
// ...
}⬆回到顶部