どのように腐ったコードを書くことを避けます

16446 ワード

名前を付ける
ルール: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};

ルール:メソッドと関数のみが動詞で始まるべきです.
ここで動詞には時態変数名が含まれていないのは名詞または名詞フレーズであるべきである.
例外:
  • コールバック関数
  • ライフサイクル関数
  • フレームレベル関数
  • getter/setter

  • 説明:
  • 関数の命名には、内部作業
  • を体現する必要がある.
  • 値変数動詞の命名は匿名関数
  • と誤解されやすい.
    BadCode
    //      ,           
    function option() {}
    
    //     
    function updatedTime() {}

    GoodCode
    function selectOption() {}
    function updateTime() {}

    ルール:ピンインまたは略語で名前を付けないでください.
    例外:
  • 専有名詞:weixin/POI
  • 従来の規則:i/j/kは循環インデックス
  • を表す.
    説明:意味がはっきりせず、「望文生義」ができない
    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ステータスを区別する必要があります.
    説明:
  • 状態はUIとともに格納され、バックエンドに伝達されるデータに不要なUI状態が混在する場合がある.
  • トラフィックコードは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();
    }