どのように腐ったコードを書くことを避けます
16446 ワード
名前を付ける
ルール:5行未満の関数でない限り、単語を使用して変数を命名しないでください.
説明:意味がはっきりせず、「望文生義」ができない
BadCode
GoodCode
ルール:名詞に数字を付けない命名方法
説明:意味がはっきりせず、「望文生義」ができない
BadCode
GoodCode
ルール:メソッドと関数のみが動詞で始まるべきです.
ここで動詞には時態変数名が含まれていないのは名詞または名詞フレーズであるべきである.
例外:コールバック関数 ライフサイクル関数 フレームレベル関数 getter/setter
説明:関数の命名には、内部作業 を体現する必要がある.値変数動詞の命名は匿名関数 と誤解されやすい.
BadCode
GoodCode
ルール:ピンインまたは略語で名前を付けないでください.
例外:専有名詞:weixin/POI 従来の規則:i/j/kは循環インデックス を表す.
説明:意味がはっきりせず、「望文生義」ができない
BadCode
GoodCode
ルール:名前の長さは、その役割ドメインのサイズに対応します.
例外:alertの説明のような独自のAPI:上位の役割ドメインの下のコードは、より多くの関数で使用されます.検索できるように、その名前はできるだけ長いか汎用的でなければなりません.
BadCode
GoodCode
変数/関数の末尾に記号、数値を付けない
説明:変数に記号を付けるのは、優先度や役割ドメインを約束するためです.シンボルは変数名の前にあるはずです.
BadCode
GoodCode
ルール:インスタンス名をクラス名に関連付ける
説明:クラスはインスタンスの所属として、その名前の表現の意味は脈々と受け継がなければならない.
BadCode
GoodCode
ルール:ストレートな中国語と英語の翻訳を避ける
乱暴な翻訳は、誤解を招きやすいので、ピンインを書くほうがいいです.
BadCode
GoodCode
ルール:概念の命名は一貫して行わなければならない
説明:1つの概念が異なるコードで複数の異なる単語で記述されることを避ける.
BadCode
GoodCode
ルール:双関語を使うな
例外:専有語の説明:双関語は曖昧さを引き起こしやすい
BadCode
GoodCode
ルール:ネーミングの必要性と実装の一貫性
説明:ネーミングは実装の隠喩であり、違いがあると読者にコードが読めなくなります.
BadCode
GoodCode
ルール:ブール値のネーミングには、「真」をデフォルトにする必要があります.
説明:ブール変数の名前に「not」などの否定語を付けると、論理的な判断をしたことに相当します.
BadCode
GoodCode
関数#カンスウ#
ルール:20行以上の長さは使用できません
説明:コードが長すぎると、やることがユニークではなく、読むことが難しくなります.
ルール:Don't repeat yourself
説明:同じ機能のコードを3回繰り返さないでください
ルール:各関数は1つのことをして、それをします.
説明:コードの論理分岐はできるだけ少なく、一つのことだけをし、境界と異常状況を処理しなければならない.
ルール:opitons、configなどのパラメータを含む関数のパラメータをできるだけ減らす
説明:関数の入力が多ければ多いほど、機能が複雑になることが多い.
ルール:プロジェクト/ビジネスのピットを注釈する
説明:比較的奇妙なビジネスロジック、あるいはシステム、インタフェースの原因で書かれた比較的奇妙なロジック.注釈で表示するには
BadCode
GoodCode
ルール:関数はできるだけ「純」で副作用がないようにする
説明:純粋な関数は比較的にテストしやすくて、論理も比較的にはっきりしていて、安心して導入して削除することができます.
BadCode
GoodCode
ルール:関数はパラメータ内のデータを変更しないほうがいいです.
説明:パラメータを変更すると、関数の役割が予測不可能になります.
BadCode
GoodCode
ルール:classのメソッドでない限り、thisにアクセスしないでください.
説明:thisの指向は常に固定されていないため、コードが理解しにくい場合があります.呼び出し元が慣れていないと、バグが起こりやすい.
BadCode
GoodCode
ルール:処理エラー
説明:エラーも論理分岐であり、処理しないとコードが丈夫ではありません.フロントエンドコードがエラーを処理する方法は、一般的にユーザに異常が発生したことを示すものである.エラーがビジネス・プロセスに影響しない場合は、ログに書き込み、レポートします.
BadCode
GoodCode
データ#データ#
ルール:Magic Numberは使用しない
説明:magic numberとは、コードに直接ハードコーディングされた数字を指し、ビジネス上の意味を持つことが多い.
これにより、数字の意味がわかりにくい 数値を変更する場合は、 の多くの場所を変更します.
BadCode
GoodCode
ルール:react stateでもvue dataでも格納されているビジネスデータには原子性が必要です.
説明:原子性は独立を意味し、分割できない.他の属性は原子トラフィック属性によって導出され、計算され、状態の一致を保証することができる.
BadCode
GoodCode
ルール:react stateとvue dataでは、ビジネスステータスとUIステータスを区別する必要があります.
説明:状態はUIとともに格納され、バックエンドに伝達されるデータに不要なUI状態が混在する場合がある. トラフィックコードはUIコードと結合されており、トラフィックコードは多重化されていない.
BadCode
GoodCode
ルール:reactアプリケーションでrender時にステータスを変更しない
説明:reactのrenderは純粋な関数であるべきで、renderでsetStateを実行するとレンダリングが重複したり、デッドサイクルになったりします.
BadCode
GoodCode
≪ルール|Rules|emdw≫:双方向バインド・アプリケーションでは、データ・サイクル依存性を回避します.
説明:ループ依存が軽いとページが遅くなり、重いと汚れたデータが表示されます. 循環依存を回避する前提は、ビジネスロジックを整理し、データ間の依存関係を明らかにすることです. サイクル依存も双方向バインド技術の非難の一つである.
BadCode
ルール:データにアクセスする際、境界状況とJS弱タイプの特性を考慮する必要があります.
二等号で判断する
BadCode
GoodCode
ルール:配列を巡回しながら配列データを変更しない
説明:これによりデータの異常が発生します.この操作が必要な場合は、配列関数を使用するか、データのコピーを操作することが望ましい.
BadCode
GoodCode
API
ルール:settimeout呼び出しの場合、渡される時間パラメータに意味がある必要があります.
説明:ほとんどのシーンでは、settimeoutの後に時間を渡すのは、右の例のコードのように、後続のAコードを実行してから、コード閉パッケージのBコードを実行するためです.
しかし,業務反復に伴ってAが非同期に変更されたり,実行時間が長い場合.先に行った遅延実行の防御措置は時効になり、逆にBがAより先に実行されるかもしれない.
BadCode
GoodCode
ルール:古いAPIは使用しない
説明:古いAPIには、セキュリティ、パフォーマンス、読みにくいなど、多くの問題があります.
BadCode
GoodCode
ルール:99.9%のシーンではReact refを使用する必要はありません
説明:React Refは、canvasなどのオリジナルDOMとインタラクティブなシーンを処理するために一般的に使用されます.
ほとんどのReact refの使用は誤りであり,サブ要素を制御するために用いられることが多い.このシーンでは、データストリーム(redux,mobx)やステータスアップグレードをお勧めします.
React公式には「ステータスアップ」の記述がhttps://react.docschina.org/d...あります
BadCode
GoodCode
ルール:urlを文字列でつなぎ合わせない
説明:文字列接合urlがencodeまたはdecodeを処理する必要がある場合、また?との判断が間違っていると、脆弱性やバグが発生しやすくなります.
現在、ブラウザとノードは標準的なURL解析方法を提供しています.
https://developer.mozilla.org...
BadCode
GoodCode
ろんり
ルール:真を判定しても偽を判定しない
説明:if条件内は「偽」の値ではなく「真」の値であることを期待すべきである.
2つ目のケースでは、コードが理解しにくくなります.
解決策はブールロジックを参照
BadCode
GoodCode
ルール:if条件では、3つ以上の論理オペレータは容易に現れません.
例外:if条件では「かつ」(&&)論理を複数のサブ条件に分割できる説明:複雑な条件判断はコードを理解しにくくし,論理的に脆弱性があるとBugを引き起こしやすい.解決策:中間変数の宣言
BadCode
GoodCode
ルール:ネストされた三元式は使用しない
説明:ネストされた3元式を読むと、文法の優先度が混同されやすく、コードの意味が間違って理解されます.
この場合はif elseに変更することをお勧めします.
react renderであれば、独立して関数にすることをお勧めします.
BadCode
GoodCode
ルール:if条件論理ネストは3層を超えないでください
説明:ネストが深すぎると理解が困難になります.解決策:判断条件をマージするか、独立して関数にします.
BadCode
GoodCode
ルール:5行未満の関数でない限り、単語を使用して変数を命名しないでください.
説明:意味がはっきりせず、「望文生義」ができない
BadCode
var l = data.length;
GoodCode
// ,
data.map(d => d.length)
ルール:名詞に数字を付けない命名方法
説明:意味がはっきりせず、「望文生義」ができない
BadCode
var obj = {};
var obj2 = {...obj, key: 1};
GoodCode
var obj = {};
var objWithKey = {...obj, key: 1};
ルール:メソッドと関数のみが動詞で始まるべきです.
ここで動詞には時態変数名が含まれていないのは名詞または名詞フレーズであるべきである.
例外:
説明:
BadCode
// ,
function option() {}
//
function updatedTime() {}
GoodCode
function selectOption() {}
function updateTime() {}
ルール:ピンインまたは略語で名前を付けないでください.
例外:
説明:意味がはっきりせず、「望文生義」ができない
BadCode
var uo = function updateOrder(){}
var as = [].slice;
var ex = Object.extends;
var nu = number
GoodCode
// weixin/wx
var weixinUser = {};
var wx = weixin;
// POI
var poi = {};
ルール:名前の長さは、その役割ドメインのサイズに対応します.
例外:alertの説明のような独自のAPI:上位の役割ドメインの下のコードは、より多くの関数で使用されます.検索できるように、その名前はできるだけ長いか汎用的でなければなりません.
BadCode
// item , 。
window.item = {}
GoodCode
window.primaryProductItem = {};
変数/関数の末尾に記号、数値を付けない
説明:変数に記号を付けるのは、優先度や役割ドメインを約束するためです.シンボルは変数名の前にあるはずです.
BadCode
function getDot_(){}
function privateFn$$ (){}
GoodCode
function _getDot() {}
function $$privateFn() {}
ルール:インスタンス名をクラス名に関連付ける
説明:クラスはインスタンスの所属として、その名前の表現の意味は脈々と受け継がなければならない.
BadCode
class Person() {}
var dog = new Person(); // dog is a Person ?
GoodCode
class Person() {}
var jack = new Person();
ルール:ストレートな中国語と英語の翻訳を避ける
乱暴な翻訳は、誤解を招きやすいので、ピンインを書くほうがいいです.
BadCode
// 「 」
// 「 」?
function renderHeadExecutantPeople(){}
GoodCode
function renderHeader() {}
ルール:概念の命名は一貫して行わなければならない
説明:1つの概念が異なるコードで複数の異なる単語で記述されることを避ける.
BadCode
// , get/fetch/query
//
function getUserInfo() {}
function fetchProductInfo() {}
function queryPayment() {}
GoodCode
// get
//
function getUserInfo() {}
function getProductInfo() {}
function getPayment() {}
ルール:双関語を使うな
例外:専有語の説明:双関語は曖昧さを引き起こしやすい
BadCode
// , ?
var orderType
GoodCode
var sortType
ルール:ネーミングの必要性と実装の一貫性
説明:ネーミングは実装の隠喩であり、違いがあると読者にコードが読めなくなります.
BadCode
// empty
// ( )
function getProduct(id) {
axios.delete('/product', {id});
}
GoodCode
function deleteProduct(id) {
axios.delete('/product', {id});
}
ルール:ブール値のネーミングには、「真」をデフォルトにする必要があります.
説明:ブール変数の名前に「not」などの否定語を付けると、論理的な判断をしたことに相当します.
BadCode
const notEmpty = !!array.length;
GoodCode
const empty = !array.length;
関数#カンスウ#
ルール:20行以上の長さは使用できません
説明:コードが長すぎると、やることがユニークではなく、読むことが難しくなります.
ルール:Don't repeat yourself
説明:同じ機能のコードを3回繰り返さないでください
ルール:各関数は1つのことをして、それをします.
説明:コードの論理分岐はできるだけ少なく、一つのことだけをし、境界と異常状況を処理しなければならない.
ルール:opitons、configなどのパラメータを含む関数のパラメータをできるだけ減らす
説明:関数の入力が多ければ多いほど、機能が複雑になることが多い.
ルール:プロジェクト/ビジネスのピットを注釈する
説明:比較的奇妙なビジネスロジック、あるいはシステム、インタフェースの原因で書かれた比較的奇妙なロジック.注釈で表示するには
BadCode
framework.doSomeThing();
framework.reset(); // OS: reset?
framework.continueSomeThing();
GoodCode
framework.doSomeThing();
// framework bug, rest : http://github.com/issuse/***
framework.reset();
framework.continueSomeThing();
ルール:関数はできるだけ「純」で副作用がないようにする
説明:純粋な関数は比較的にテストしやすくて、論理も比較的にはっきりしていて、安心して導入して削除することができます.
BadCode
let status;
function method() {
if (status) { ... }
}
GoodCode
function method(status) {
if (status) { ... }
}
ルール:関数はパラメータ内のデータを変更しないほうがいいです.
説明:パラメータを変更すると、関数の役割が予測不可能になります.
BadCode
function updateObj(obj, value) {
obj.key = value;
return obj;
}
GoodCode
function updateObj(obj, value) {
return {...obj, key: value};
}
ルール:classのメソッドでない限り、thisにアクセスしないでください.
説明:thisの指向は常に固定されていないため、コードが理解しにくい場合があります.呼び出し元が慣れていないと、バグが起こりやすい.
BadCode
function method() {
console.log(this.value);
}
method() //
var obj = { method, value: 1}
obj.method() // 1
GoodCode
function method(value) {
console.log(value);
}
ルール:処理エラー
説明:エラーも論理分岐であり、処理しないとコードが丈夫ではありません.フロントエンドコードがエラーを処理する方法は、一般的にユーザに異常が発生したことを示すものである.エラーがビジネス・プロセスに影響しない場合は、ログに書き込み、レポートします.
BadCode
function method(data) {
try { return JSON.parse(data) }
catch (e) {}
}
GoodCode
function method(data) {
try { return JSON.parse(data) }
catch (e) {
alert(' ')
}
}
データ#データ#
ルール:Magic Numberは使用しない
説明:magic numberとは、コードに直接ハードコーディングされた数字を指し、ビジネス上の意味を持つことが多い.
これにより、
BadCode
if (status === 1) {
...
} else if (type === 4) {
...
}
GoodCode
enum Status {
Closed
}
enum Type {
Array
}
if (status === Status.Closed) {
...
} else if (type === Type.Array) {
...
}
ルール:react stateでもvue dataでも格納されているビジネスデータには原子性が必要です.
説明:原子性は独立を意味し、分割できない.他の属性は原子トラフィック属性によって導出され、計算され、状態の一致を保証することができる.
BadCode
// status open
//
{
data() {
return {
showAlert: false,
status: 'closed',
}
},
onStatusChange() {
if (status === 'open') {
this.showAlert = true;
} else {
this.showAlert = false;
}
}
}
GoodCode
// showAlert
// status
{
data() {
return {
status: 'closed',
}
},
computed: {
showAlert() {
return this.status === 'open';
}
}
}
ルール:react stateとvue dataでは、ビジネスステータスとUIステータスを区別する必要があります.
説明:
BadCode
// ,
//
class extends React.Component {
async componentDidMount() {
const listData = getData();
this.setState({ listData })
}
check = (item) => {
const listData = this.state.listData.map(i => {
if (i === item) {
return {...item, checked: true}
}
return i;
});
this.setState({ listData });
}
delete() {
// , checked
deleteItems(this.state.listData.filter(i => i.checked));
}
render() {
const list = this.state.listData.map(item => {
const className = ['item'];
if (item.checked) className.push('active');
return ;
});
return <>
{list}
>
}
}
GoodCode
// ,
//
class extends React.Component {
async componentDidMount() {
const listData = getData();
// selected UI
this.setState({ listData, selected: [] })
}
check = (item) => {
let { selected } = this.state;
selected = selected.findOrInsert(s => s.id, item);
this.setState({ selected });
}
delete() {
const { selected, listData } = this.state;
deleteItems(listData.filter(i => selected.includes(i.id))));
}
render() {
const { selected, listData } = this.state;
const list = listData.map(item => {
const className = ['item'];
if (selected.includes(item.id)) className.push('active');
return ;
});
return <>
{list}
>
}
}
ルール:reactアプリケーションでrender時にステータスを変更しない
説明:reactのrenderは純粋な関数であるべきで、renderでsetStateを実行するとレンダリングが重複したり、デッドサイクルになったりします.
BadCode
// type http , https
class extends React.Component {
render() {
const { type } = this.state;
if (type === 'http') {
this.setState({ type: 'https'})
}
return ;
}
}
GoodCode
// type http , https
class extends React.Component {
get type() {
const { type } = this.state;
if (type === 'http') return 'https';
return type;
}
render() {
const type = this.type;
return ;
}
}
≪ルール|Rules|emdw≫:双方向バインド・アプリケーションでは、データ・サイクル依存性を回避します.
説明:
BadCode
// foo bar ,
{
data() {
return {
foo: 1,
};
},
computed: {
bar() {
return this.foo + 1;
}
},
watch() {
bar() {
this.foo = this.bar + 1;
},
}
}
ルール:データにアクセスする際、境界状況とJS弱タイプの特性を考慮する必要があります.
二等号で判断する
BadCode
const foo = '0';
const bar = 0
//
foo == bar // true
foo ? 1 : 2 // 1
bar ? 1 : 2 // 2
// length
if(obj.length) {
obj.forEach(...)
}
GoodCode
const foo = '0';
const bar = 0
foo === bar // false
if (Array.isArray(obj)) {
obj.forEach(...)
}
ルール:配列を巡回しながら配列データを変更しない
説明:これによりデータの異常が発生します.この操作が必要な場合は、配列関数を使用するか、データのコピーを操作することが望ましい.
BadCode
const array = [1,2,3,4,5,6,7,8,9,10];
//
for (var i = 0; i < array.length; i++) {
if (array[i] % 2 == 0) array.splice(i);
}
// array [1]
GoodCode
const array = [1,2,3,4,5,6,7,8,9,10];
array.filter(a => !(a % 2))
API
ルール:settimeout呼び出しの場合、渡される時間パラメータに意味がある必要があります.
説明:ほとんどのシーンでは、settimeoutの後に時間を渡すのは、右の例のコードのように、後続のAコードを実行してから、コード閉パッケージのBコードを実行するためです.
しかし,業務反復に伴ってAが非同期に変更されたり,実行時間が長い場合.先に行った遅延実行の防御措置は時効になり、逆にBがAより先に実行されるかもしれない.
BadCode
// B
setTimeout(() => {
B();
}, 1000);
A();
// render
// ,
setTimeout(() => {
render()
}, 16);
GoodCode
// A Promise
await A();
b();
// API
requestAnimationFrame(() => {
render();
});
ルール:古いAPIは使用しない
説明:古いAPIには、セキュリティ、パフォーマンス、読みにくいなど、多くの問題があります.
BadCode
//
Object.prototype.toString.call(array) === "[object Array]"
//
for (var i = 0; i < array.length; i++) {
if (array[i] % 2 === 0) return array[i];
}
// key
for (var key in obj) {
console.log(key);
}
// /
'some text'.indexOf('some') >= 0
//
' some text '.replace(/(^\s+|\s+$)/g, '')
// /
const array = new Array();
const obj = new Object();
GoodCode
Array.isArray(array)
array.find(a => a % 2 === 0);
Object.keys(obj).forEach(console.log)
'some text'.includes('some')
' some text '.trim()
const array = [];
const obj = {};
ルール:99.9%のシーンではReact refを使用する必要はありません
説明:React Refは、canvasなどのオリジナルDOMとインタラクティブなシーンを処理するために一般的に使用されます.
ほとんどのReact refの使用は誤りであり,サブ要素を制御するために用いられることが多い.このシーンでは、データストリーム(redux,mobx)やステータスアップグレードをお勧めします.
React公式には「ステータスアップ」の記述がhttps://react.docschina.org/d...あります
BadCode
class List extends React.Component {
async refresh() {
this.setState({
items: getItems(),
});
}
render() {
return this.state.items.map(i => );
}
}
class extends React.Component {
onRefresh = () => {
// ref
this.list.refresh();
}
render() {
return <>
this.list = l}>
GoodCode
class List extends React.Component {
render() {
return this.props.items.map(i => );
}
}
class extends React.Component {
//
refresh = async () => {
this.setState({
items: getItems(),
});
}
render() {
return <>
ルール:urlを文字列でつなぎ合わせない
説明:文字列接合urlがencodeまたはdecodeを処理する必要がある場合、また?との判断が間違っていると、脆弱性やバグが発生しやすくなります.
現在、ブラウザとノードは標準的なURL解析方法を提供しています.
https://developer.mozilla.org...
BadCode
// key、value encode
// url #
const url = location.href;
if (url.indexOf('?') >= 0) {
return url + key + '=' + value;
} else {
return url + '?' + key + '=' + value;
}
GoodCode
// URL ,
const url = new URL(urlStr);
url.searchParams.set(key, value);
return url.toString();
ろんり
ルール:真を判定しても偽を判定しない
説明:if条件内は「偽」の値ではなく「真」の値であることを期待すべきである.
2つ目のケースでは、コードが理解しにくくなります.
解決策はブールロジックを参照
BadCode
// if 「 」
if (!(status !== Closed) { ... }
if (!(status !== Closed || type !== Array)) { ...}
GoodCode
if (status === Closed) { ... }
if (status === Closed && type === Array) { ... }
ルール:if条件では、3つ以上の論理オペレータは容易に現れません.
例外:if条件では「かつ」(&&)論理を複数のサブ条件に分割できる説明:複雑な条件判断はコードを理解しにくくし,論理的に脆弱性があるとBugを引き起こしやすい.解決策:中間変数の宣言
BadCode
if (srcElem != dropElem && (srcElem.nextSibling || srcElem.nextElementSibling) != dropElem) {...}
if (selectedItem || (selectedEmployee && selectedEmployee.empId && selectedEmployee) || employee) { ... }
GoodCode
const nextSibling = srcElem.nextSibling || srcElem.nextElementSibling
if (srcElem != dropElem && nextSibling != dropElem ) {
...
}
// &&
if (
!Array.isArray(cur)
&& cur != null
&& typeof src[key] === 'object'
&& typeof cur === 'object'
) { ... }
ルール:ネストされた三元式は使用しない
説明:ネストされた3元式を読むと、文法の優先度が混同されやすく、コードの意味が間違って理解されます.
この場合はif elseに変更することをお勧めします.
react renderであれば、独立して関数にすることをお勧めします.
BadCode
function render(props) {
const value = props.value;
return <>
{value < 10 ? value > 0 ? value : 200 - value : 100 - value}
>;
}
GoodCode
function getValue(value) {
if (value < 10) {
if (value > 0) return value;
return 200 - value;
}
return 100 - value;
}
function render(props) {
const value = props.value;
return <>
{getValue(value)}
>;
}
ルール:if条件論理ネストは3層を超えないでください
説明:ネストが深すぎると理解が困難になります.解決策:判断条件をマージするか、独立して関数にします.
BadCode
if (status = Opened) {
if (type = 'array') {
if (code = Success) {
doSomething();
}
}
}
GoodCode
if (status = Opened && type = 'array' &&code = Success) {
doSomething();
}