魅力的なコードの作成: 可読性、保守性、パフォーマンスを最適化する鍵

この記事は、業務開発でよく遭遇するビジネスロジックのエレガントな書き方をまとめたものであり、私が新人の頃ビジネスの始め方がわからなかったときに苦労した点をまとめたものです。書いた内容は標準化されていませんでした。

書き終えた後も気分は良く、また勉強になりました。

本文の始まり

なぜエレガントなコードを書くのでしょうか?

簡潔な構文と構造を採用し、一貫した命名規則に従い、適切なコード構成とコメントを備え、コードの意図とロジックを同時に表現します。

主に以下のようなメリットがあります。

  1. 可読性: 読みやすく、理解しやすい。明確な命名、簡潔​​な構文、適切なコード構造により、コードの意図がより明確になり、降低理解代码的难度コードの読みやすさが向上します。

  2. メンテナンス性: メンテナンスが容易です。コードのロジックが明確で構造が簡潔であれば、開発者は更快速地定位和修复bug機能を拡張または変更できます。同時に、可読性の高いコードは、その後のコードのリファクタリングや最適化にも役立ちます。

  3. スケーラビリティ: よりスケーラブルで柔軟です灵活性明確なコード構造と簡潔なコーディング スタイルにより、新しい機能の追加、既存の機能の変更、またはコードの拡張が容易になります。さらに、簡潔なコードは特定の実装の詳細への依存が少なくなる傾向があり、柔軟性と代替性が高まります。

  4. エラーの削減とデバッグ時間: 更容易写出正确的逻辑,减少了出错的概率同時に、コードに問題がある場合、エレガントで簡潔なコードの方がデバッグが容易で、エラーを特定するのが簡単です。

  5. パフォーマンスの最適化: 通常、簡潔なコードは効率が高く、不必要な計算とリソースの消費が削減されます。合理化されたコード構造とアルゴリズムにより、コード実行の効率とパフォーマンスが向上します。

基本スキル

1. アロー関数を使用して関数定義を簡素化する

// 传统函数定义
function add(a, b) {
 return a + b;
 }
  
 // 箭头函数简化
 const add = (a, b) => a + b;

2. 分割代入を使用して変数宣言を簡素化する

// 传统变量声明
const firstName = person.firstName;
const lastName = person.lastName;
// 解构赋值简化
const { firstName, lastName } = person;

3. テンプレートリテラルを使用した文字列連結

// 传统字符串拼接
const greeting = 'Hello, ' + name + '!';
// 模板字面量简化
const greeting = `Hello, ${name}!`;

4. 配列およびオブジェクトの演算にスプレッド演算子を使用する

// 合并数组
const combined = [...array1, ...array2];
// 复制对象
const clone = { ...original };

5. 配列の高次メソッドを使用してループとデータ操作を簡素化する

// 遍历数组并返回新数组
const doubled = numbers.map(num => num * 2);
// 过滤数组
const evens = numbers.filter(num => num % 2 === 0);

6. 条件演算子を使用して条件判断を簡素化する

// 传统条件判断
let message;
if (isSuccess) {
 message = 'Operation successful';
} else {
 message = 'Operation failed';
}
// 条件运算符简化
const message = isSuccess ? 'Operation successful' : 'Operation failed';

7. オブジェクトの構造化とデフォルト引数を使用して関数の引数を簡素化する

// 传统参数设置默认值
function greet(name) {
 const finalName = name || 'Guest';
 console.log(`Hello, ${finalName}!`);
 }
  
 // 对象解构和默认参数简化
 function greet({ name = 'Guest' }) {
 console.log(`Hello, ${name}!`);
 }

8. 純粋関数や関数合成などの関数型プログラミングの概念を使用する

// 纯函数
function add(a, b) {
 return a + b;
 }
  
 // 函数组合
 const multiplyByTwo = value => value * 2;
 const addFive = value => value + 5;
 const result = addFive(multiplyByTwo(3));

9. オブジェクト リテラルを使用してオブジェクトの作成と定義を簡素化する

// 传统对象创建
const person = {
 firstName: 'John',
 lastName: 'Doe',
 age: 30,
 };
  
 // 对象字面量简化
 const firstName = 'John';
 const lastName = 'Doe';
 const age = 30;
 const person = { firstName, lastName, age };

10. 適切な名前とコメントを使用して、コードの可読性を向上させます。

// 不好的
const x = 10; // 设置x的值为10
function a(b) {
 return b * 2; // 返回b的两倍
}
// 好的
const speed = 10; // 设置速度为10
function double(value) {
 return value * 2; // 返回输入值的两倍

続いて音楽を流してダンス(実戦)!

戦闘

1. 条件判定コードを美しく書く

単純な条件判定ロジックif else や三項演算子は一目で何のことを言っているのか分かるが、大量のif else三項演算子が重なり合うのは受信者の悪夢だ~~~

三項演算子の重ね合わせの例をあげておきますが、実際にプロジェクトで遭遇しましたが、CPUが直接爆発してしまいました~~~

<view>{
   
   {status===1?'成功': status===2 ? '失败' : status===3 ? '进行中' : '未开始' }}</view>

おそらくこのように、特定のプロジェクトのコードをここに置くのは簡単ではありません (理解している限り)。

複雑なロジックには、人間の脳のロジックに沿った、可読性が高く、快適に見えるオブジェクトマップの記述方法を使用することをお勧めします~~~

1.そうでなければ普通

let txt = '';
if (falg) {
 txt = 成功
} else {
 txt = 失败
}

2. 三項演算子

let txt = flag ? 成功 : 失败;

3. if else の複数

// param {status} status 活动状态:1:成功 2:失败 3:进行中 4:未开始
let txt = '';
if (status == 1) {
 txt = 成功;
} else if (status == 2) {
 txt = 失败;
} else if (status == 3) {
 txt = 进行中;
} else {
 txt = 未开始;
}

4、スイッチケース

let txt = '';
switch (status) {
 case 1:
 txt = 成功;
 break;
 case 2:
 txt = 成功;
 break;
 case 3:
 txt = 进行中;
 break;
 default:
 txt = 未开始;
}

5. オブジェクトの書き込み

const statusMap = {
 1: 成功,
 2: 失败,
 3: 进行中,
 4: 未开始
}
//调用直接 statusMapp[status]

6. 地図の書き方

const actions = new Map([
 [1, 成功],
 [2, 失败],
 [3, 进行中],
 [4, 未开始]
])
// 调用直接 actions.get(status)

2. 条件文をカプセル化する

同様に、if の条件が多ければ多いほど受信機のメンテナンスに不利になり、人間の脳の理解に役立たないため、一見論理の塊に見えます。複数の論理的なべきです化零为整

大脑:'别来碰我,让我静静'

// 不好的
if (fsm.state === 'fetching' && isEmpty(listNode)) {
 // ...
}
// 好的
shouldShowSpinner(fsm, listNode){
 return fsm.state === 'fetching' && isEmpty(listNode)
}
if(shouldShowSpinner(fsm, listNode)){
 //...doSomething
}

3. 関数は 1 つのことだけを実行する必要があります

関数型の記述方法は非常に尊重されており柯里化、1 つの関数と 1 つの関数を分割して組み立てることができます。

// 不好的
function createFile(name, temp) {
 if (temp) {
   fs.create(`./temp/${name}`);
 } else {
   fs.create(name);
 }
}
// 好的
function createFile(name) {
 fs.create(name);
}
function createTempFile(name) {
 createFile(`./temp/${name}`)
}

栗をもう一つ

この関数が行うことは次のとおりです。

  • クライアント配列を走査する

  • トラバーサル プロセス中に、ルックアップ関数を通じて新しいオブジェクトclientRecordが取得されます。

  • clientRecordオブジェクトのisActive関数がtrueを返すかどうかを確認します

    • isActive関数はtrueを返し電子メール関数を実行して、現在のメンバーを呼び出します。

// 不好的
function emailClients(clients) {
 clients.forEach((client) => {
   const clientRecord = database.lookup(client);
   if (clientRecord.isActive()) {
     email(client);
   }
 });
}
// 好的
function emailClients(clients) {
 clients
   .filter(isClientRecord)
   .forEach(email)
}
function isClientRecord(client) {
 const clientRecord = database.lookup(client);
 return clientRecord.isActive()
}

上の悪い栗は一見して、コードがたくさんあるように感じますか、しばらく見たくありません。

いい栗ですね、ロジックが明確で読みやすいですよね?

  • フィルター関数を上手に使って、条件処理用のフィルターのコールバック関数を開き、条件に合致したデータを返す

  • forEach を上手に使って、適格なデータに対してメール機能を実行する

4. Object.assign はデフォルト値をデフォルトオブジェクトに割り当てます。

// 不好的
const menuConfig = {
 title: null,
 body: 'Bar',
 buttonText: null,
 cancellable: true
};
function createMenu(config) {
 config.title = config.title || 'Foo';
 config.body = config.body || 'Bar';
 config.buttonText = config.buttonText || 'Baz';
 config.cancellable = config.cancellable === undefined ?
 config.cancellable : true;
}
createMenu(menuConfig);
// 好的
const menuConfig = {
 title: 'Order',
 buttonText: 'Send',
 cancellable: true
};
function createMenu(config) {
 Object.assign({
   title: 'Foo',
   body: 'Bar',
   buttonText: 'Baz',
   cancellable: true 
 }, config)
}
createMenu(menuConfig);

5. 関数パラメータは 2 つ未満にするのが最善です

千の言葉と一万の言葉を言うのは、優雅さと読みやすさのためです。

// 不好的
function createMenu(title, body, buttonText, cancellable) {
 // ...
}
// 好的
const menuConfig = {
 title: 'Foo',
 body: 'Bar',
 buttonText: 'Baz',
 cancellable: true
};
function createMenu(config){
 // ...
}
createMenu(menuConfig)

6. 説明変数を使用する

フローを保存し、読みやすくするために拡張演算子を使用します(saveCityZipCode(city, zipCode)読みやすさは非常に優れており、パラメーターの目的がわかります)

// 不好的
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})?$/;
cosnt [, city, zipCode] = address.match(cityZipCodeRegex) || [];
saveCityZipCode(city, zipCode)

クラス内の属性に対してさらにカスタムのアクセス/増加/変更操作を実行したい場合は、set/getを使用します。

この文言を初めて見たのですが、何を意味するのか分かりません、皆さん、vue2 の definePropertyだと思います。

Object.defineProperty(data1,'age',{
 set:function(newAge){
   console.log(this.name+'现在'+newAge+'岁')
 },
 get:function(){
   return 18;
 }
})

これは、値を割り当てるときに set がトリガーされ、値を取得するときに get がトリガーされることを意味します。

組み込みの属性を上手に使用してパフォーマンスを向上させます。

class BankAccount {
 constructor(balance = 1000) {
   this._balance = balance;
 }
 // It doesn't have to be prefixed with `get` or `set` to be a
 //getter/setter
 set balance(amount) {
   console.log('set')
   if (verifyIfAmountCanBeSetted(amount)) {
     this._balance = amount;
   }
 }
 get balance() {
   console.log('get')
   return this._balance;
 }
 verifyIfAmountCanBeSetted(val) {
   // ...
 }
}
const bankAccount = new BankAccount();
// Buy shoes...
bankAccount.balance -= 100;
// Get balance
let balance = bankAccount.balance;

7. オブジェクトにプライベートメンバーを持たせる - クロージャを使用する

クロージャは本質的に私有化される

// 不好的
const Employee = function(name) {
 this.name = name;
};
Employee.prototype.getName = function getName() {
 return this.name;
};
const employee = new Employee('John Doe');
console.log(`Employee name: ${employee.getName()}`); // Employee name: John Doe
delete employee.name;
console.log(`Employee name: ${employee.getName()}`); // Employee name: undefined
// 好的
const Employee = function(name){
 this.getName = function(){
   return name
 }
}
const employee = new Employee('John Doe');
console.log(`Employee name: ${employee.getName()}`); // Employee name: John Doe
delete employee.name;
console.log(`Employee name: ${employee.getName()}`); // Employee name: undefined

最初の例

アドバンテージ:

  • 原型链共享方法メモリスペースを節約することによって。インスタンス オブジェクト getName ごとに独立したメソッドを作成するのではなく、すべてのインスタンス オブジェクトが同じメソッドを共有します。

欠点:

  • コンストラクターでプライベート プロパティやメソッドを直接定義する方法はありません所有属性和方法都会被暴露在原型链上

2番目の例

アドバンテージ:

  • コンストラクター内に置くことができ定义私有属性和方法、オブジェクトのプロトタイプ チェーンで公開されないため、カプセル化が向上します。

欠点:

  • インスタンス オブジェクトが作成されるたびに、独立したメソッド (每个实例对象都有独自の getName メソッド) がより多くのメモリ領域を占有します。

8. メソッドチェーンの使用

链式写法コードの上品さもポイントです。

ps:これを考えたプログラマはバックエンド出身でしょうね、この手の書き方はPHPのCIフレームワークでも見られました。

// 不好的
class Car {
 constructor() {
   this.make = 'Honda';
   this.model = 'Accord';
   this.color = 'white';
 }
 setMake(make) {
   this.make = make;
 }
 save() {
   console.log(this.make, this.model, this.color);
 }
}
const car = new Car();
car.setMake('Ford');
car.save();
// 好的
class Car {
 constructor() {
   this.make = 'Honda';
   this.model = 'Accord';
   this.color = 'white';
 }
 setMake(make) {
   this.make = make;
   // NOTE: return this是为了用链式写法
   return this;
 }
 save() {
   console.log(this.make, this.model, this.color);
   // NOTE:return this是为了用链式写法
   return this;
 }
}
const car = new Car()
 .setMake('Ford')
 .save();

上記のたくさんの文章を読んだ後、私の友人の考えはより明確になりました。あなたのプロジェクトで実践してみましょう。

あなたが得るのは、同僚や受け手への感謝と、自分自身の心の安らぎです。

終わり

この記事では、私のメモとアイデアをここに記載するために最善を尽くしました。友人の役に立てば幸いです。

転載歓迎ですが、出典を明記してください。

最後に、友達が私に無料で「いいね!」をしてくれることを願っています。そして、あなたの願いがすべて叶い、平和と喜びが得られることを願っています。

おすすめ

転載: blog.csdn.net/qq_48652579/article/details/131364132