Prinsip -prinsip rekayasa perangkat lunak, dari buku Robert C Martin Code , Air -Conditioned dengan JavaScript. Ini bukan metode gaya. Ini adalah panduan produksi untuk program yang dapat dibaca, dapat digunakan kembali dan memproduksi kembali dalam skrip Java.
Tidak setiap prinsip di sini harus diikuti secara akurat, dan bahkan kurang dari yang akan disepakati secara global. Ini adalah pedoman, tidak lebih, tetapi mereka adalah pedoman selama bertahun -tahun pengalaman kolektif dengan kode bersih _.
Seumur hidup rekayasa perangkat lunak lebih dari 50 tahun, dan kami masih belajar banyak hal. "Ketika rekayasa perangkat lunak sudah tua, rekayasa itu sendiri," mungkin kita akan memiliki aturan yang lebih sulit untuk diikuti. Sekarang, biarkan pedoman ini berfungsi sebagai tes untuk mengevaluasi kualitas kode JavaScript yang Anda dan tim Anda hasilkan.
Hal lain: mengetahui prinsip -prinsip ini tidak akan membuat Anda segera menjadi programmer terbaik yang pernah ada, dan bekerja dengan mereka selama bertahun -tahun tidak berarti bahwa Anda tidak akan membuat kesalahan. Setiap bagian dari kode dimulai sebagai draft pertama, seperti mengerjakan tanah liat basah yang tidak akan mendapatkan bentuk akhir dari pandangan pertama, karena kami selalu menghilangkan cacat kapan. Kami memeriksanya dengan rekan -rekan kami. Jadi jangan menekan diri sendiri karena draft pertama yang membutuhkan perbaikan. Mengatasi kode sebagai gantinya!
buruk:
const yyyymmdstr = moment ( ) . format ( "YYYY/MM/DD" )Bagus:
const currentDate = moment ( ) . format ( "YYYY/MM/DD" )⬆ Kembali ke atas
buruk:
getUserInfo ( )
getClientData ( )
getCustomerRecord ( )Bagus:
getUser ( )⬆ Kembali ke atas
Kami akan membaca lebih banyak kode daripada yang akan kami tulis. Penting bahwa kode yang kami tulis dapat dibaca dan penelitian. Bukan untuk menyebutkan variabel yang akhirnya bermakna untuk memahami program kami, membuatnya sulit bagi pembaca. Buat nama Anda mencari. Alat seperti Buddy.js dan Eslint dapat membantu menentukan konstanta yang tidak disebutkan namanya.
buruk:
// What the heck is 86400000 for?
setTimeout ( blastOff , 86400000 )Bagus:
// Declare them as capitalized named constants.
const MILLISECONDS_PER_DAY = 60 * 60 * 24 * 1000 //86400000;
setTimeout ( blastOff , MILLISECONDS_PER_DAY )⬆ Kembali ke atas
buruk:
const address = "One Infinite Loop, Cupertino 95014"
const cityZipCodeRegex = / ^[^,\]+[,\s]+(.+?)s*(d{5})?$ /
saveCityZipCode (
address . match ( cityZipCodeRegex ) [ 1 ] ,
address . match ( cityZipCodeRegex ) [ 2 ]
)Bagus:
const address = "One Infinite Loop, Cupertino 95014"
const cityZipCodeRegex = / ^[^,\]+[,\s]+(.+?)s*(d{5})?$ /
const [ _ , city , zipCode ] = address . match ( cityZipCodeRegex ) || [ ]
saveCityZipCode ( city , zipCode )⬆ Kembali ke atas
Itu selalu lebih jelas daripada implisit.
buruk:
const locations = [ "Austin" , "New York" , "San Francisco" ]
locations . forEach ( ( l ) => {
doStuff ( )
doSomeOtherStuff ( )
// ...
// ...
// ...
// Wait, what is `l` for again?
dispatch ( l )
} )Bagus:
const locations = [ "Austin" , "New York" , "San Francisco" ]
locations . forEach ( ( location ) => {
doStuff ( )
doSomeOtherStuff ( )
// ...
// ...
// ...
dispatch ( location )
} )⬆ Kembali ke atas
Jika kelas nama/objek memberi tahu Anda sesuatu, jangan ulangi ini di nama variabel Anda.
buruk:
const Car = {
carMake : "Honda" ,
carModel : "Accord" ,
carColor : "Blue" ,
}
function paintCar ( car , color ) {
car . carColor = color
}Bagus:
const Car = {
make : "Honda" ,
model : "Accord" ,
color : "Blue" ,
}
function paintCar ( car , color ) {
car . color = color
}⬆ Kembali ke atas
Argumen default adalah offline. BEY bahwa jika Anda adalah mereka, fungsi Anda hanya akan memberikan nilai default untuk argumen undefined . "Falsy" Nilai SU '' , "" false , null , 0 , dan NaN , Nan, tidak akan terikat dengan nilai default.
buruk:
function createMicrobrewery ( name ) {
const breweryName = name || "Hipster Brew Co."
// ...
}Bagus:
function createMicrobrewery ( name = "Hipster Brew Co." ) {
// ...
}⬆ Kembali ke atas
Sangat sulit untuk mendapatkan warisan kelas membaca, untuk membangun dan definisi klasik kelas ES5. Jika Anda membutuhkan keturunan (dan sadarilah bahwa Anda mungkin tidak membutuhkannya), Anda akan lebih suka kelas ES2015/ES6. Namun, cobalah untuk tetap menjadi fungsi kecil di kelas, sehingga Anda merasa lebih besar dan lebih rumit.
buruk:
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 ( ) { }Bagus:
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 ( ) {
/* ... */
}
}⬆ Kembali ke atas
Gaya ini sangat berguna dalam skrip Java dan melihatnya di banyak perpustakaan seperti Jquey dan Lodash. Ini memungkinkan kode Anda untuk diekspresikan, dan gosip paling sedikit. Untuk alasan ini, saya sarankan, gunakan metode urutan dan lihat seberapa bersih kode Anda. Dalam fungsi kelas Anda, Anda hanya perlu mengembalikan ini di akhir setiap fungsi, dan Anda dapat menghubungkan metode kelas tambahan.
buruk:
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 ( )Bagus:
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 ( )⬆ Kembali ke atas
Seperti yang dinyatakan dalam [ pola desain ] (https://en.wikipedia.org/wiki/design_patterns) oleh Gang of Four, Anda harus lebih suka komposisi daripada warisan saat Anda bisa. Ada banyak penyebab wajah untuk menggunakan warisan dan banyak wajah penggunaan komposisi. Poin utama dari prinsip ini adalah bahwa jika pikiran Anda dipasang untuk warisan, cobalah untuk berpikir jika komposisi dapat menyelesaikan masalah Anda dengan lebih baik. Dalam beberapa kasus itu bisa.
Anda mungkin bertanya -tanya setelah ini, "Kapan saya harus menggunakan warisan?" Ini tergantung pada masalah Anda yang ingin Anda selesaikan, tetapi ini adalah daftar yang layak saat warisan lebih logis daripada komposisi:
Warisan Anda adalah hubungan "dan bukan" memiliki "hubungan (human-> hewan berlawanan pengguna-> detail pengguna).
Anda dapat menggunakan kembali kode dari kelas dasar (manusia dapat bergerak seperti semua hewan).
Anda ingin membuat perubahan umum pada kelas yang diturunkan dengan mengubah kelas dasar. (Ubah kalori untuk semua hewan saat mereka bergerak).
buruk:
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
}
// ...
}Bagus:
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 )
}
// ...
}⬆ Kembali ke atas