Software Engineering Principles, from the book Robert C Martin Code , air -conditioned with JavaScript. This is not a method of style. It is a production guide for a readable program, reusable and re -manufacturing in Java Script.
Not every principle here must be followed accurately, and even less than that will be agreed upon globally. These are guidelines, no more, but they are guidelines for many years of collective experience by Clean Code _.
The lifetime of software engineering is more than 50 years, as well as we still learn a lot of things. "When software engineering is old, engineering is in itself," perhaps we will have more difficult rules to be followed. Now, let these guidelines serve as a test to evaluate the quality of the JavaScript code that you and your team produce.
Another thing: Knowing these principles will not make you immediately the best programmer ever, and working with them for many years does not mean that you will not make mistakes. Each part of the code begins as a first draft, such as working on a wet clay that will not get the final shape from the first sight, as we always remove defects when. We review it with our peers. So do not press yourself because of the first drafts that need improvement. Overcome the code instead!
bad:
const yyyymmdstr = moment ( ) . format ( "YYYY/MM/DD" )good:
const currentDate = moment ( ) . format ( "YYYY/MM/DD" )⬆ Back to the top
bad:
getUserInfo ( )
getClientData ( )
getCustomerRecord ( )good:
getUser ( )⬆ Back to the top
We will read more code than we will write. It is important that the code we write is readable and research. Not to name the variables that end up to be meaningful to understand our program, making it difficult for readers. Make your names search. Tools like Buddy.js and Eslint can help determine unnamed constants.
bad:
// What the heck is 86400000 for?
setTimeout ( blastOff , 86400000 )good:
// Declare them as capitalized named constants.
const MILLISECONDS_PER_DAY = 60 * 60 * 24 * 1000 //86400000;
setTimeout ( blastOff , MILLISECONDS_PER_DAY )⬆ Back to the top
bad:
const address = "One Infinite Loop, Cupertino 95014"
const cityZipCodeRegex = / ^[^,\]+[,\s]+(.+?)s*(d{5})?$ /
saveCityZipCode (
address . match ( cityZipCodeRegex ) [ 1 ] ,
address . match ( cityZipCodeRegex ) [ 2 ]
)good:
const address = "One Infinite Loop, Cupertino 95014"
const cityZipCodeRegex = / ^[^,\]+[,\s]+(.+?)s*(d{5})?$ /
const [ _ , city , zipCode ] = address . match ( cityZipCodeRegex ) || [ ]
saveCityZipCode ( city , zipCode )⬆ Back to the top
It is always clear better than implicit.
bad:
const locations = [ "Austin" , "New York" , "San Francisco" ]
locations . forEach ( ( l ) => {
doStuff ( )
doSomeOtherStuff ( )
// ...
// ...
// ...
// Wait, what is `l` for again?
dispatch ( l )
} )good:
const locations = [ "Austin" , "New York" , "San Francisco" ]
locations . forEach ( ( location ) => {
doStuff ( )
doSomeOtherStuff ( )
// ...
// ...
// ...
dispatch ( location )
} )⬆ Back to the top
If the name Class/Object tells you something, do not repeat this in your variable name.
bad:
const Car = {
carMake : "Honda" ,
carModel : "Accord" ,
carColor : "Blue" ,
}
function paintCar ( car , color ) {
car . carColor = color
}good:
const Car = {
make : "Honda" ,
model : "Accord" ,
color : "Blue" ,
}
function paintCar ( car , color ) {
car . color = color
}⬆ Back to the top
Default Arguments are of offline. Bey that if you us the they, your function will only Provide Default Values for undefined arguments. Other "FALSY" Values Su '' , "" false , null , 0 , and NaN , Will Not Beled by A Default Value.
bad:
function createMicrobrewery ( name ) {
const breweryName = name || "Hipster Brew Co."
// ...
}good:
function createMicrobrewery ( name = "Hipster Brew Co." ) {
// ...
}⬆ Back to the top
It is very difficult to obtain a reading Classes inheritance, to build and classic definitions of ES5 Classes. If you need heredity (and be aware that you may not need it), you will prefer ES2015/ES6 Classes. However, try to remain the small Functions on Classes, so that you find yourself needed larger and more complicated.
bad:
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 ( ) { }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 ( ) {
/* ... */
}
}⬆ Back to the top
This style is very useful in Java Script and sees it in many libraries like JQUEY and Lodash. It allows your code to be expressed, and the least gossip. For this reason, I suggest, use the sequence method and take a look at how clean your code is. In your Class Functions, you only need to return this at the end of each Function, and you can connect the additional Class Methods.
bad:
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 ( )good:
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 ( )⬆ Back to the top
As stated in [ Design Patterns ] (https://en.wikipedia.org/wiki/design_patterns) by Gang of Four, you should prefer composition over inheritance when you can. There are many causes of the face to use inheritance and many of the faces of the use of composition. The main point of this principle is that if your mind goes installed for inheritance, try to think if composition can solve your problem better. In some cases it can.
You may wonder after this, "When should I use inheritance?" This depends on your problem that you want to solve, but this is a decent list when Inheritance is more logical than composition:
Your inheritance is a relationship "and not" has "relationship (human-> animal opposite user-> User details).
You can reuse the code from the basic classes (humans can move like all animals).
You want to make general changes on Derived Classes by changing the basic Class. (Change calories for 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 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 )
}
// ...
}⬆ Back to the top