Principes d'ingénierie logicielle, du livre Robert C Martin Code , conditionné à l'air avec JavaScript. Ce n'est pas une méthode de style. Il s'agit d'un guide de production pour un programme lisible, réutilisable et de fabrication de référence dans le script Java.
Tous les principes ne doivent pas être suivis avec précision, et encore moins que cela sera convenu à l'échelle mondiale. Ce sont des lignes directrices, pas plus, mais ce sont des lignes directrices pour de nombreuses années d'expérience collective par Clean Code _.
La durée de vie de l'ingénierie logicielle est plus de 50 ans, et nous apprenons encore beaucoup de choses. "Lorsque l'ingénierie logicielle est ancienne, l'ingénierie est en soi", peut-être que nous aurons des règles plus difficiles à suivre. Maintenant, laissez ces directives servir de test pour évaluer la qualité du code JavaScript que vous et votre équipe produisez.
Une autre chose: connaître ces principes ne fera pas de vous immédiatement le meilleur programmeur de tous les temps, et travailler avec eux pendant de nombreuses années ne signifie pas que vous ne ferez pas d'erreurs. Chaque partie du code commence comme une première ébauche, comme travailler sur une argile humide qui n'obtiendra pas la forme finale de la première vue, car nous supprimons toujours les défauts quand. Nous le passons en revue avec nos pairs. Alors, ne vous appuyez pas sur les premières ébauches qui nécessitent une amélioration. Surmonter le code à la place!
mauvais:
const yyyymmdstr = moment ( ) . format ( "YYYY/MM/DD" )bien:
const currentDate = moment ( ) . format ( "YYYY/MM/DD" )⬆ Retour au sommet
mauvais:
getUserInfo ( )
getClientData ( )
getCustomerRecord ( )bien:
getUser ( )⬆ Retour au sommet
Nous allons lire plus de code que nous n'écrire. Il est important que le code que nous écrivons soit lisible et la recherche. Ne pas nommer les variables qui finissent par être significatives pour comprendre notre programme, ce qui rend la tâche difficile pour les lecteurs. Faites la recherche de vos noms. Des outils comme Buddy.js et Eslint peuvent aider à déterminer les constantes sans nom.
mauvais:
// 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 )⬆ Retour au sommet
mauvais:
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 )⬆ Retour au sommet
Il est toujours clair que implicite.
mauvais:
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 )
} )⬆ Retour au sommet
Si la classe / objet de nom vous indique quelque chose, ne le répétez pas dans votre nom de variable.
mauvais:
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
}⬆ Retour au sommet
Les arguments par défaut sont hors ligne. Bey que si vous nous usons les eux, votre fonction ne fournira que des valeurs par défaut pour les arguments undefined . D'autres valeurs "Falsy" Su '' , "" false , null , 0 et NaN , ne raconteront pas une valeur par défaut.
mauvais:
function createMicrobrewery ( name ) {
const breweryName = name || "Hipster Brew Co."
// ...
}bien:
function createMicrobrewery ( name = "Hipster Brew Co." ) {
// ...
}⬆ Retour au sommet
Il est très difficile d'obtenir un héritage de classes de lecture, de construire et des définitions classiques des classes ES5. Si vous avez besoin d'hérédité (et sachez que vous n'en aurez peut-être pas besoin), vous préférerez les classes ES2015 / ES6. Cependant, essayez de rester les petites fonctions sur les cours, afin que vous vous trouviez besoin de plus grand et plus compliqué.
mauvais:
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 ( ) {
/* ... */
}
}⬆ Retour au sommet
Ce style est très utile dans le script Java et le voit dans de nombreuses bibliothèques comme JQuey et Lodash. Il permet d'exprimer votre code et le moins de ragots. Pour cette raison, je suggère, utilisez la méthode de séquence et jetez un œil à la propreté de votre code. Dans vos fonctions de classe, vous n'avez qu'à retourner cela à la fin de chaque fonction, et vous pouvez connecter les méthodes de classe supplémentaires.
mauvais:
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 ( )⬆ Retour au sommet
Comme indiqué dans [ Design Matchs ] (https://en.wikipedia.org/wiki/design_patterns) par Gang of Four, vous devez préférer la composition à l'héritage lorsque vous le pouvez. Il existe de nombreuses causes de visage pour utiliser l'héritage et bon nombre des visages de l'utilisation de la composition. Le point principal de ce principe est que si votre esprit est installé pour l'héritage, essayez de penser si la composition peut mieux résoudre votre problème. Dans certains cas, cela peut.
Vous vous demandez peut-être après cela: "Quand dois-je utiliser l'héritage?" Cela dépend de votre problème que vous souhaitez résoudre, mais c'est une liste décente lorsque l'héritage est plus logique que la composition:
Votre héritage est une relation "et non" a "une relation (humain-> Animal opposé utilisateur-> Détails de l'utilisateur).
Vous pouvez réutiliser le code à partir des classes de base (les humains peuvent se déplacer comme tous les animaux).
Vous souhaitez apporter des modifications générales sur les classes dérivées en modifiant la classe de base. (Changez des calories pour tous les animaux lorsqu'ils bougent).
mauvais:
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 )
}
// ...
}⬆ Retour au sommet