Robert C Martin Code 책의 소프트웨어 엔지니어링 원칙은 JavaScript로 공기 조정되었습니다. 이것은 스타일의 방법이 아닙니다. Java 스크립트로 재사용 가능한 재사용 및 재 제조를위한 읽기 가능한 프로그램을위한 제작 가이드입니다.
여기의 모든 원칙을 정확하게 따라야하는 것은 아니며, 그보다는 전 세계적으로 합의 될 것입니다. 이들은 더 이상 지침이지만, Clean Code _의 수년간의 집단 경험에 대한 지침입니다.
소프트웨어 엔지니어링의 수명은 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
}⬆ 위로 돌아갑니다
기본 인수는 오프라인입니다. 당신이 우리에게 그들을한다면, 당신의 기능은 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 ( )⬆ 위로 돌아갑니다
갱 4 명에 의해 [ 디자인 패턴 ] (https://en.wikipedia.org/wiki/design_patterns)에 언급 된 바와 같이, 가능하면 상속을보다 선호해야합니다. 상속 재산과 구성 사용의 많은면을 사용하기위한 많은 원인이 있습니다. 이 원칙의 주요 요점은 당신의 마음이 상속을 위해 설치되면 구성이 문제를 더 잘 해결할 수 있는지 생각해보십시오. 어떤 경우에는 가능합니다.
"상속을 언제 사용해야합니까?" 이것은 당신이 해결하려는 당신의 문제에 따라 다르지만, 상속이 구성보다 더 논리적 일 때 괜찮은 목록입니다.
당신의 상속은 "관계"가 아니라 "관계 (인간-> 동물 반대 사용자-> 사용자 세부 사항)입니다.
기본 클래스에서 코드를 재사용 할 수 있습니다 (인간은 모든 동물처럼 움직일 수 있습니다).
기본 클래스를 변경하여 파생 클래스에서 일반적인 변경을 원합니다. (모든 동물이 움직일 때 칼로리를 바꾸십시오).
나쁜:
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 )
}
// ...
}⬆ 위로 돌아갑니다