軟件工程原理,來自羅伯特·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 )
}
// ...
}⬆回到頂部