Principios de ingeniería de software, del libro Robert C Martin Code , Air -acondicionado con JavaScript. Este no es un método de estilo. Es una guía de producción para un programa legible, reutilizable y reanicura en el script Java.
No todos los principios aquí deben seguirse con precisión, e incluso menos de lo que se acordará a nivel mundial. Estas son pautas, no más, pero son pautas para muchos años de experiencia colectiva por código limpio _.
La vida de la ingeniería de software es de más de 50 años, así como aún aprendemos muchas cosas. "Cuando la ingeniería de software es antigua, la ingeniería es en sí misma", tal vez tengamos reglas más difíciles de seguir. Ahora, deje que estas pautas sirvan como una prueba para evaluar la calidad del código JavaScript que producen usted y su equipo.
Otra cosa: saber estos principios no lo hará inmediatamente el mejor programador de la historia, y trabajar con ellos durante muchos años no significa que no cometa errores. Cada parte del código comienza como un primer borrador, como trabajar en una arcilla húmeda que no obtendrá la forma final desde la primera vista, ya que siempre eliminamos defectos cuando. Lo revisamos con nuestros compañeros. Así que no presione a sí mismo debido a los primeros borradores que necesitan mejoras. ¡Supere el código en su lugar!
malo:
const yyyymmdstr = moment ( ) . format ( "YYYY/MM/DD" )bien:
const currentDate = moment ( ) . format ( "YYYY/MM/DD" )⬆ Volver a la cima
malo:
getUserInfo ( )
getClientData ( )
getCustomerRecord ( )bien:
getUser ( )⬆ Volver a la cima
Leeremos más código del que escribiremos. Es importante que el código que escribimos sea legible e investigación. No nombrar las variables que terminan para ser significativas para comprender nuestro programa, lo que dificulta a los lectores. Haga que sus nombres busquen. Herramientas como Buddy.js y Eslint pueden ayudar a determinar las constantes no identificadas.
malo:
// What the heck is 86400000 for?
setTimeout ( blastOff , 86400000 )bien:
// Declare them as capitalized named constants.
const MILLISECONDS_PER_DAY = 60 * 60 * 24 * 1000 //86400000;
setTimeout ( blastOff , MILLISECONDS_PER_DAY )⬆ Volver a la cima
malo:
const address = "One Infinite Loop, Cupertino 95014"
const cityZipCodeRegex = / ^[^,\]+[,\s]+(.+?)s*(d{5})?$ /
saveCityZipCode (
address . match ( cityZipCodeRegex ) [ 1 ] ,
address . match ( cityZipCodeRegex ) [ 2 ]
)bien:
const address = "One Infinite Loop, Cupertino 95014"
const cityZipCodeRegex = / ^[^,\]+[,\s]+(.+?)s*(d{5})?$ /
const [ _ , city , zipCode ] = address . match ( cityZipCodeRegex ) || [ ]
saveCityZipCode ( city , zipCode )⬆ Volver a la cima
Siempre es claro mejor que implícito.
malo:
const locations = [ "Austin" , "New York" , "San Francisco" ]
locations . forEach ( ( l ) => {
doStuff ( )
doSomeOtherStuff ( )
// ...
// ...
// ...
// Wait, what is `l` for again?
dispatch ( l )
} )bien:
const locations = [ "Austin" , "New York" , "San Francisco" ]
locations . forEach ( ( location ) => {
doStuff ( )
doSomeOtherStuff ( )
// ...
// ...
// ...
dispatch ( location )
} )⬆ Volver a la cima
Si la clase/objeto de nombre le dice algo, no repita esto en su nombre de variable.
malo:
const Car = {
carMake : "Honda" ,
carModel : "Accord" ,
carColor : "Blue" ,
}
function paintCar ( car , color ) {
car . carColor = color
}bien:
const Car = {
make : "Honda" ,
model : "Accord" ,
color : "Blue" ,
}
function paintCar ( car , color ) {
car . color = color
}⬆ Volver a la cima
Los argumentos predeterminados son fuera de línea. Bey que si nosotros ellos, su función solo proporcionará valores predeterminados para argumentos undefined . Otros valores "falsos" su '' , "" false , null , 0 y NaN , no se pondrán por un valor predeterminado.
malo:
function createMicrobrewery ( name ) {
const breweryName = name || "Hipster Brew Co."
// ...
}bien:
function createMicrobrewery ( name = "Hipster Brew Co." ) {
// ...
}⬆ Volver a la cima
Es muy difícil obtener una herencia de clases de lectura, para construir y definiciones clásicas de las clases de ES5. Si necesita heredidad (y tenga en cuenta que es posible que no la necesite), preferirá las clases ES2015/ES6. Sin embargo, trate de seguir siendo las pequeñas funciones en las clases, para que se encuentre más grande y más complicado.
malo:
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 ( ) { }bien:
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 ( ) {
/* ... */
}
}⬆ Volver a la cima
Este estilo es muy útil en el guión de Java y lo ve en muchas bibliotecas como JQuey y Lodash. Permite que su código se exprese y el menor chismes. Por esta razón, sugiero, use el método de secuencia y eche un vistazo a cuán limpio está su código. En las funciones de su clase, solo necesita devolver esto al final de cada función, y puede conectar los métodos de clase adicionales.
malo:
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 ( )bien:
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 ( )⬆ Volver a la cima
Como se indica en [ Patrones de diseño ] (https://en.wikipedia.org/wiki/design_patterns) por Gang of Four, debe preferir la composición sobre la herencia cuando pueda. Hay muchas causas de la cara para usar la herencia y muchas de las caras del uso de la composición. El punto principal de este principio es que si su mente se instala para su herencia, trate de pensar si la composición puede resolver mejor su problema. En algunos casos puede.
Puede preguntarse después de esto, "¿Cuándo debo usar la herencia?" Esto depende de su problema que desee resolver, pero esta es una lista decente cuando la herencia es más lógica que la composición:
Su herencia es una relación "y no" tiene "relación" (humano-> animal opuesto a los detalles del usuario).
Puede reutilizar el código de las clases básicas (los humanos pueden moverse como todos los animales).
Desea hacer cambios generales en clases derivadas cambiando la clase básica. (Cambie calorías para todos los animales cuando se mueven).
malo:
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
}
// ...
}bien:
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 )
}
// ...
}⬆ Volver a la cima