JavaScriptコードのクリーンな道
9025 ワード
きれいなコードは快適に見えるだけではなく、いくつかの仕様に従って、コードを維持しやすくし、バグの確率を下げることができます.
1.配列の下付きを名前付きの変数で置換します.
多くのパラメータがあるならば、objectを使って伝達し、解を使います.
3.一つの関数は一つのことしかしない.
メリットはcompose、test、and reason aboutです.
4.自分で原型を広げない
原型を拡張したいなら、まず引き継いでから方法を加えて汚染を防ぐことができます.
7.Prefer compsition over inherityance
なるべくグループで相続の代わりに、どのような場合に継承が使われますか?
Your inhearitance represents an“is-a”relatinship and not a“has-a”relatitionnship(Human->Animal vs.User->UserDetails).You can reuse code from the base clases(Humans can can mon momove clcleagggggggggggggggggclclclclclinininininininininininininininingggggggggclclclclclclclclclass.mamamamamamamamagggggggggggclclclclclass)))))))You ure of all animls when they move)
8.SOLID
Single Resonsibility Principle単一職責原則
The e e shoud never be more than one reason for a class to changeは、一つの種類が変更された原因の数はできるだけ低くするべきです.一つのクラスの中で、機能が多すぎると、その中の一点を修正すると、このクラスのモジュールを引用して受けた影響は計り知れません.
Open/Closed Principle開放閉鎖原則
ユーザーは、内部実装を修正せずに機能を自己拡張することができる.例えばHttpモジュールがありますが、内部は環境によってどのアドホットを使うかを判断します.ユーザーがアドホップを追加するなら、Httpモジュールを修正しなければなりません.
親類と子類は交換されて使っても大丈夫です.
Clients shound not be forced to depend up on interfaces that they do use.例えば、機能モジュールは、必須のパラメータおよびオプションのパラメータを設計する必要があり、オプションのパラメータをユーザに強制的に使用させるべきではない.
Dependency Inversion Principle依存注入原則
9.コメント
Comments are an applogy,not a requirement.Good code mostly documents itself.良いコードは自己解釈です.
あなたはよくバグや他の問題に会います.落ち込んでしまうかもしれませんが、できるだけ冷静に、系統的に考えてください.実践を覚えることは問題を解決する一番いい方法です.
私たちが採集したのは石ですが、いつも未来の大聖堂を展望しなければなりません.
「ITPUBブログ」から、リンク:http://blog.itpub.net/69901074/viewspace-2639805/転載する場合は、出典を明記してください.そうしないと法律責任を追及します.
転載先:http://blog.itpub.net/69901074/viewspace-2639805/
1.配列の下付きを名前付きの変数で置換します.
// bad
const address = "One Infinite Loop, Cupertino 95014";
const cityZipCodeRegex = /^[^,\\]+[,\\\s]+(.+?)\s*(\d{5})?$/;
saveCityZipCode(
// 1,2
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);
2.関数のパラメータが一番いいです.多くのパラメータがあるならば、objectを使って伝達し、解を使います.
3.一つの関数は一つのことしかしない.
メリットはcompose、test、and reason aboutです.
4.自分で原型を広げない
原型を拡張したいなら、まず引き継いでから方法を加えて汚染を防ぐことができます.
// bad
Array.prototype.diff = function diff(comparisonArray) {
const hash = new Set(comparisonArray);
return this.filter(elem => !hash.has(elem));
};
// good
class SuperArray extends Array {
diff(comparisonArray) {
const hash = new Set(comparisonArray);
return this.filter(elem => !hash.has(elem));
}
}
5.条件文の代わりに多形を使う// bad
if (type === 'text') {
// do something
} else if (type === 'select') {
// do something else
}
個人がこのコードを書くのによく使われるのは、const control = {
text: {
mapper() {},
restore(){},
name: 'this is a text field',
},
select: {
mapper() {},
restore(){},
name: 'this is a select field',
}
}
control[type].mapper();
実際には多状態です.classを使う方法も考えられます.class Field {
...
}
class TextField extends Field {
mapper(){}
restore(){}
name = 'this is a text field';
}
class SelectField extends Field {
mapper(){}
restore(){}
name = 'this i```s a select field';
}
getterとsetter関数を使用します.// bad
function makeBankAccount() {
// ...
return {
balance: 0
// ...
};
}
const account = makeBankAccount();
account.balance = 100;
// good
function makeBankAccount() {
// this one is private
let balance = 0;
// a "getter", made public via the returned object below
function getBalance() {
return balance;
}
// a "setter", made public via the returned object below
function setBalance(amount) {
// ... validate before updating the balance
balance = amount;
}
return {
// ...
getBalance,
setBalance
};
}
const account = makeBankAccount();
account.setBalance(100);
getterとsetterの中で多くのことをすることができます.一つ一つのbalanceを修正する必要はありません.7.Prefer compsition over inherityance
なるべくグループで相続の代わりに、どのような場合に継承が使われますか?
Your inhearitance represents an“is-a”relatinship and not a“has-a”relatitionnship(Human->Animal vs.User->UserDetails).You can reuse code from the base clases(Humans can can mon momove clcleagggggggggggggggggclclclclclinininininininininininininininingggggggggclclclclclclclclclass.mamamamamamamamagggggggggggclclclclclass)))))))You ure of all animls when they move)
8.SOLID
Single Resonsibility Principle単一職責原則
The e e shoud never be more than one reason for a class to changeは、一つの種類が変更された原因の数はできるだけ低くするべきです.一つのクラスの中で、機能が多すぎると、その中の一点を修正すると、このクラスのモジュールを引用して受けた影響は計り知れません.
Open/Closed Principle開放閉鎖原則
ユーザーは、内部実装を修正せずに機能を自己拡張することができる.例えばHttpモジュールがありますが、内部は環境によってどのアドホットを使うかを判断します.ユーザーがアドホップを追加するなら、Httpモジュールを修正しなければなりません.
// bad
class AjaxAdapter extends Adapter {
constructor() {
super();
this.name = "ajaxAdapter";
}
}
class NodeAdapter extends Adapter {
constructor() {
super();
this.name = "nodeAdapter";
}
}
class HttpRequester {
constructor(adapter) {
this.adapter = adapter;
}
fetch(url) {
if (this.adapter.name === "ajaxAdapter") {
return makeAjaxCall(url).then(response => {
// transform response and return
});
} else if (this.adapter.name === "nodeAdapter") {
return makeHttpCall(url).then(response => {
// transform response and return
});
}
}
}
function makeAjaxCall(url) {
// request and return promise
}
function makeHttpCall(url) {
// request and return promise
}
// good
class AjaxAdapter extends Adapter {
constructor() {
super();
this.name = "ajaxAdapter";
}
request(url) {
// request and return promise
}
}
class NodeAdapter extends Adapter {
constructor() {
super();
this.name = "nodeAdapter";
}
request(url) {
// request and return promise
}
}
class HttpRequester {
constructor(adapter) {
this.adapter = adapter;
}
fetch(url) {
return this.adapter.request(url).then(response => {
// transform response and return
});
}
}
Liskov Substitution Principle内式置換原則親類と子類は交換されて使っても大丈夫です.
// bad
class Rectangle {
constructor() {
this.width = 0;
this.height = 0;
}
setColor(color) {
// ...
}
render(area) {
// ...
}
setWidth(width) {
this.width = width;
}
setHeight(height) {
this.height = height;
}
getArea() {
return this.width * this.height;
}
}
class Square extends Rectangle {
setWidth(width) {
this.width = width;
this.height = width;
}
setHeight(height) {
this.width = height;
this.height = height;
}
}
function renderLargeRectangles(rectangles) {
rectangles.forEach(rectangle => {
rectangle.setWidth(4);
rectangle.setHeight(5);
const area = rectangle.getArea(); // BAD: Returns 25 for Square. Should be 20.
rectangle.render(area);
});
}
const rectangles = [new Rectangle(), new Rectangle(), new Square()];
renderLargeRectangles(rectangles);
上記のRectangleはSquareを直接に置き換えることができません.計算面積が間違っているので、面積を計算する方法を抽象的に考えています.class Shape {
setColor(color) {
// ...
}
render(area) {
// ...
}
}
class Rectangle extends Shape {
constructor(width, height) {
super();
this.width = width;
this.height = height;
}
getArea() {
return this.width * this.height;
}
}
class Square extends Shape {
constructor(length) {
super();
this.length = length;
}
getArea() {
return this.length * this.length;
}
}
function renderLargeShapes(shapes) {
shapes.forEach(shape => {
const area = shape.getArea();
shape.render(area);
});
}
const shapes = [new Rectangle(4, 5), new Rectangle(4, 5), new Square(5)];
renderLargeShapes(shapes);
インターフェース分離原則Clients shound not be forced to depend up on interfaces that they do use.例えば、機能モジュールは、必須のパラメータおよびオプションのパラメータを設計する必要があり、オプションのパラメータをユーザに強制的に使用させるべきではない.
Dependency Inversion Principle依存注入原則
// bad
class InventoryRequester {
constructor() {
this.REQ_METHODS = ["HTTP"];
}
requestItem(item) {
// ...
}
}
class InventoryTracker {
constructor(items) {
this.items = items;
// BAD: We have created a dependency on a specific request implementation.
// We should just have requestItems depend on a request method: `request`
this.requester = new InventoryRequester();
}
requestItems() {
this.items.forEach(item => {
this.requester.requestItem(item);
});
}
}
const inventoryTracker = new InventoryTracker(["apples", "bananas"]);
inventoryTracker.requestItems();
上記の例は、InventryTracker内部でInventry Requesterを実装していること、すなわちhigh-levelのモジュールはlow-levelモジュールの詳細を知る必要があることを意味している(例えば、実用化されたInventryRequesterはその構造パラメータを知る必要があるなど、あるいはimportこのモジュールを必要とし、結合を作る).// good
class InventoryTracker {
constructor(items, requester) {
this.items = items;
this.requester = requester;
}
requestItems() {
this.items.forEach(item => {
this.requester.requestItem(item);
});
}
}
class InventoryRequesterV1 {
constructor() {
this.REQ_METHODS = ["HTTP"];
}
requestItem(item) {
// ...
}
}
class InventoryRequesterV2 {
constructor() {
this.REQ_METHODS = ["WS"];
}
requestItem(item) {
// ...
}
}
// By constructing our dependencies externally and injecting them, we can easily
// substitute our request module for a fancy new one that uses WebSockets.
const inventoryTracker = new InventoryTracker(
["apples", "bananas"],
new InventoryRequesterV2()
);
inventoryTracker.requestItems();
low-levelに直接入ってきた例は、どのように実用化されるかを考える必要はなく、high-levelは抽象的なインターフェースに依存するだけでサブモジュールへの呼び出しを完了することができます.9.コメント
Comments are an applogy,not a requirement.Good code mostly documents itself.良いコードは自己解釈です.
あなたはよくバグや他の問題に会います.落ち込んでしまうかもしれませんが、できるだけ冷静に、系統的に考えてください.実践を覚えることは問題を解決する一番いい方法です.
私たちが採集したのは石ですが、いつも未来の大聖堂を展望しなければなりません.
「ITPUBブログ」から、リンク:http://blog.itpub.net/69901074/viewspace-2639805/転載する場合は、出典を明記してください.そうしないと法律責任を追及します.
転載先:http://blog.itpub.net/69901074/viewspace-2639805/