キーポイント
この記事は、マット・バーネット、サイモン・コドリントン、ニルソン・ジャックによってレビューされました。 SitePointコンテンツを最高の状態にしてくれたすべてのSitePointピアレビュアーに感謝します! もう一度コードを見ることなく、一度に1回の実行でプロジェクトを完了したことがありますか?どちらの私もいない。古いプロジェクトに取り組んでいるときは、コードの仕組みを理解して、ほとんどまたはまったく時間を費やさないようにすることができます。読みやすいコードは、製品を維持し、あなたとあなたの同僚や協力者を満足させるために不可欠です。
読みにくいコードの誇張された例は、1024文字以下で最高のJavaScriptアプリケーションを書くことを目標に、JSF*CK(ちなみにNSFW)を書くことを目標に、JS1Kコンペティションで誇張されています。 JavaScriptコードを作成するために6つの異なる文字のみを使用して、深遠なプログラミングスタイル。これらのサイトでコードをチェックすると、何が起こっているのか不思議に思うようになります。このようなコードを書いて、数ヶ月後にエラーを修正しようとすることを想像してください。定期的にインターネットを閲覧したり、インターフェイスを構築したりすると、シンプルで小さなフォームを終了するよりも、大きくてかさばる形を出る方が簡単であることがわかるかもしれません。コードにも同じことが言えます。読みやすく使用しやすいと見なされると、人々はそれを使用することを好むかもしれません。少なくとも、それはあなたがあなたのコンピューターがイライラするのを捨てるのを妨げます。
この記事では、コードを読みやすくするためのヒントとトリック、および回避する落とし穴を調べます。
コードセグメンテーション
形式の類推に持続すると、フォームが部品に分割されることがあり、難しくなりません。コードは同じことができます。それをセクションに分割することにより、読者はジャングルを閲覧するのに苦労するのではなく、それらに関連するセクションにジャンプできます。
長年にわたり、ネットワークのあらゆる種類のものを最適化してきました。 JavaScriptファイルも例外ではありません。 MINIFINGとPRE-HTTP/2について考えて、スクリプトを1つに組み合わせることでHTTP要求を保存します。今日、私たちは希望どおりに作業し、GulpやGruntなどのタスクランナーを使用してファイルを処理できます。私たちが好きな方法をプログラムし、ツールに最適化(接続など)を残すことができると言っても安全です。
// 从 API 加载用户数据 var getUsersRequest = new XMLHttpRequest(); getUsersRequest.open('GET', '/api/users', true); getUsersRequest.addEventListener('load', function() { // 对用户执行某些操作 }); getUsersRequest.send(); //--------------------------------------------------- // 不同的功能从这里开始。也许 // 这是一个分成文件的时机。 //--------------------------------------------------- // 从 API 加载帖子数据 var getPostsRequest = new XMLHttpRequest(); getPostsRequest.open('GET', '/api/posts', true); getPostsRequest.addEventListener('load', function() { // 对帖子执行某些操作 }); getPostsRequest.send();
関数を使用すると、再利用可能なコードブロックを作成できます。一般に、関数の内容はインデントされているため、関数の開始位置と終了位置を簡単に確認できます。良い習慣は、関数を小さく保つことです-10列以下です。また、関数が正しく命名されたときに関数が呼び出されたときに何が起こるかを理解するのも簡単です。後で命名規則を紹介します。
// 从 API 加载用户数据 function getUsers(callback) { var getUsersRequest = new XMLHttpRequest(); getUsersRequest.open('GET', '/api/users', true); getUsersRequest.addEventListener('load', function() { callback(JSON.parse(getUsersRequest.responseText)); }); getUsersRequest.send(); } // 从 API 加载帖子数据 function getPosts(callback) { var getPostsRequest = new XMLHttpRequest(); getPostsRequest.open('GET', '/api/posts', true); getPostsRequest.addEventListener('load', function() { callback(JSON.parse(getPostsRequest.responseText)); }); getPostsRequest.send(); } // 由于命名正确,因此无需阅读实际函数即可轻松理解此代码 // getUsers(function(users) { // // 对用户执行某些操作 // }); // getPosts(function(posts) { // // 对帖子执行某些操作 // });
上記のコードを簡素化できます。これらの2つの関数はほとんど同じであることに注意してください。 「自分自身を繰り返さないでください」(ドライ)原則を適用できます。これは混乱を防ぎます。
function fetchJson(url, callback) { var request = new XMLHttpRequest(); request.open('GET', url, true); request.addEventListener('load', function() { callback(JSON.parse(request.responseText)); }); request.send(); } // 下面的代码仍然很容易理解 // 无需阅读上面的函数 fetchJson('/api/users', function(users) { // 对用户执行某些操作 }); fetchJson('/api/posts', function(posts) { // 对帖子执行某些操作 });
POSTリクエストを通じて新しいユーザーを作成したい場合はどうなりますか?この時点で、1つのオプションは、関数にオプションのパラメーターを追加して、関数に新しいロジックを導入し、関数になるには複雑すぎるようにすることです。別のオプションは、コードの複製を引き起こすために、投稿リクエスト専用に特別に新しい関数を作成することです。
オブジェクト指向のプログラミングを通じて両方の利点を取得でき、保守性を維持しながら構成可能な単一使用オブジェクトを作成できます。
注:オブジェクト指向のJavaScriptの初心者が必要な場合は、このビデオをお勧めします。オブジェクト指向のJavaScriptの権威あるガイド< オブジェクト指向のプログラミング
httpRequest.js
function HttpRequest(url) { this.request = new XMLHttpRequest(); this.body = undefined; this.method = HttpRequest.METHOD_GET; this.url = url; this.responseParser = undefined; } HttpRequest.METHOD_GET = 'GET'; HttpRequest.METHOD_POST = 'POST'; HttpRequest.prototype.setMethod = function(method) { this.method = method; return this; }; HttpRequest.prototype.setBody = function(body) { if (typeof body === 'object') { body = JSON.stringify(body); } this.body = body; return this; }; HttpRequest.prototype.setResponseParser = function(responseParser) { if (typeof responseParser !== 'function') return; this.responseParser = responseParser; return this; }; HttpRequest.prototype.send = function(callback) { this.request.addEventListener('load', function() { if (this.responseParser) { callback(this.responseParser(this.request.responseText)); } else { callback(this.request.responseText); } }, false); this.request.open(this.method, this.url, true); this.request.send(this.body); return this; };
new HttpRequest('/users') .setResponseParser(JSON.parse) .send(function(users) { // 对用户执行某些操作 }); new HttpRequest('/posts') .setResponseParser(JSON.parse) .send(function(posts) { // 对帖子执行某些操作 }); // 创建一个新用户 new HttpRequest('/user') .setMethod(HttpRequest.METHOD_POST) .setBody({ name: 'Tim', email: 'info@example.com' }) .setResponseParser(JSON.parse) .send(function(user) { // 对新用户执行某些操作 });
設計パターンは、OOPを使用する場合に最適です。彼らはそれ自体で読みやすさを向上させることはありませんが、一貫性はあります!
人工文法
。コードを読みやすくすることは、より細心の芸術です。わずかな詳細は大きな影響を与える可能性があります。たとえば、ラインの長さを80文字に制限することは簡単なソリューションであり、通常は垂直線を介して編集者によって強制されます。しかし、もっとあります! name 適切な命名は、値が何であるか、または関数の役割を見つけることなく、即座に認識される可能性があります。
// 从 API 加载用户数据 var getUsersRequest = new XMLHttpRequest(); getUsersRequest.open('GET', '/api/users', true); getUsersRequest.addEventListener('load', function() { // 对用户执行某些操作 }); getUsersRequest.send(); //--------------------------------------------------- // 不同的功能从这里开始。也许 // 这是一个分成文件的时机。 //--------------------------------------------------- // 从 API 加载帖子数据 var getPostsRequest = new XMLHttpRequest(); getPostsRequest.open('GET', '/api/posts', true); getPostsRequest.addEventListener('load', function() { // 对帖子执行某些操作 }); getPostsRequest.send();
変数名の場合は、逆ピラミッド法を適用してみてください。トピックは前に配置され、属性は後ろに配置されます。
// 从 API 加载用户数据 function getUsers(callback) { var getUsersRequest = new XMLHttpRequest(); getUsersRequest.open('GET', '/api/users', true); getUsersRequest.addEventListener('load', function() { callback(JSON.parse(getUsersRequest.responseText)); }); getUsersRequest.send(); } // 从 API 加载帖子数据 function getPosts(callback) { var getPostsRequest = new XMLHttpRequest(); getPostsRequest.open('GET', '/api/posts', true); getPostsRequest.addEventListener('load', function() { callback(JSON.parse(getPostsRequest.responseText)); }); getPostsRequest.send(); } // 由于命名正确,因此无需阅读实际函数即可轻松理解此代码 // getUsers(function(users) { // // 对用户执行某些操作 // }); // getPosts(function(posts) { // // 对帖子执行某些操作 // });
通常の変数と特別な変数を区別できることも重要です。たとえば、定数の名前は通常、大文字で記述され、下線が引かれます。
function fetchJson(url, callback) { var request = new XMLHttpRequest(); request.open('GET', url, true); request.addEventListener('load', function() { callback(JSON.parse(request.responseText)); }); request.send(); } // 下面的代码仍然很容易理解 // 无需阅读上面的函数 fetchJson('/api/users', function(users) { // 对用户执行某些操作 }); fetchJson('/api/posts', function(posts) { // 对帖子执行某些操作 });
クラスは通常、大文字から始まるラクダの命名法を使用します。
function HttpRequest(url) { this.request = new XMLHttpRequest(); this.body = undefined; this.method = HttpRequest.METHOD_GET; this.url = url; this.responseParser = undefined; } HttpRequest.METHOD_GET = 'GET'; HttpRequest.METHOD_POST = 'POST'; HttpRequest.prototype.setMethod = function(method) { this.method = method; return this; }; HttpRequest.prototype.setBody = function(body) { if (typeof body === 'object') { body = JSON.stringify(body); } this.body = body; return this; }; HttpRequest.prototype.setResponseParser = function(responseParser) { if (typeof responseParser !== 'function') return; this.responseParser = responseParser; return this; }; HttpRequest.prototype.send = function(callback) { this.request.addEventListener('load', function() { if (this.responseParser) { callback(this.responseParser(this.request.responseText)); } else { callback(this.request.responseText); } }, false); this.request.open(this.method, this.url, true); this.request.send(this.body); return this; };
小さな詳細は略語です。略語を大文字にすることを選択する人もいれば、ラクダの命名法に固執することを選択する人もいます。前者を使用すると、その後の略語を特定することがより困難になる場合があります。
多くのコードベースでは、文字の数を減らすか、アルゴリズムのパフォーマンスを改善するための「特別な」コードが遭遇する可能性があります。
シングルラインコードは、簡潔なコードの例です。残念ながら、彼らは通常、トリックや不明瞭な構文に依存しています。以下に示すネストされた三元演算子は一般的な例です。簡潔ですが、通常のIFステートメントと比較してその効果を理解するのに1〜2秒かかる場合があります。構文のショートカットには注意してください。
new HttpRequest('/users') .setResponseParser(JSON.parse) .send(function(users) { // 对用户执行某些操作 }); new HttpRequest('/posts') .setResponseParser(JSON.parse) .send(function(posts) { // 对帖子执行某些操作 }); // 创建一个新用户 new HttpRequest('/user') .setMethod(HttpRequest.METHOD_POST) .setBody({ name: 'Tim', email: 'info@example.com' }) .setResponseParser(JSON.parse) .send(function(user) { // 对新用户执行某些操作 });
マイクロ最適化はパフォーマンスの最適化であり、通常はほとんど影響を与えません。ほとんどの場合、それらはより低いパフォーマンスの等価物ほど読みやすいものではありません。
function getApiUrl() { /* ... */ } function setRequestMethod() { /* ... */ } function findItemsById(n) { /* ... */ } function hideSearchForm() { /* ... */ }
JavaScriptコンパイラは、私たちのコードの最適化に非常に優れており、常に改善しています。最適化されていないコードと最適化されたコードの違いが明らかでない限り(通常、数千または数百万の操作の後)、読みやすいコードを選択することをお勧めします。
これは皮肉ですが、コードを読みやすくするためのより良い方法は、実行されない構文を追加することです。それを非コードと呼びましょう。
すべての開発者が他の開発者にそれを提供しているか、特定のWebサイトの圧縮コードをチェックしていると確信しています - ほとんどのスペースが削除されているコードです。初めてこれに遭遇するのは非常に驚くべきことかもしれません。デザインやタイポグラフィなどの視覚芸術のさまざまな分野では、空白が充填と同じくらい重要です。 2つの間に微妙なバランスを見つける必要があります。このバランスの認識は、企業、チーム、開発者によって異なります。幸いなことに、一般的にによって認識されるいくつかのルールがあります。
1行につき1つの式、コメント
var element = document.getElementById('body'), elementChildren = element.children, elementChildrenCount = elementChildren.length; // 定义一组颜色时,我在变量前加“color”前缀 var colorBackground = 0xFAFAFA, colorPrimary = 0x663399; // 定义一组背景属性时,我使用 background 作为基准 var backgroundColor = 0xFAFAFA, backgroundImages = ['foo.png', 'bar.png']; // 上下文可以改变一切 var headerBackgroundColor = 0xFAFAFA, headerTextColor = 0x663399;
非自明なコードの解釈と議論、
var URI_ROOT = window.location.href;
// 从 API 加载用户数据 var getUsersRequest = new XMLHttpRequest(); getUsersRequest.open('GET', '/api/users', true); getUsersRequest.addEventListener('load', function() { // 对用户执行某些操作 }); getUsersRequest.send(); //--------------------------------------------------- // 不同的功能从这里开始。也许 // 这是一个分成文件的时机。 //--------------------------------------------------- // 从 API 加载帖子数据 var getPostsRequest = new XMLHttpRequest(); getPostsRequest.open('GET', '/api/posts', true); getPostsRequest.addEventListener('load', function() { // 对帖子执行某些操作 }); getPostsRequest.send();
オブジェクト指向ソフトウェアを作成する場合、通常のコメントのようなインラインドキュメントは、コードに呼吸スペースを提供できます。また、属性または方法の目的と詳細を明確にするのにも役立ちます。多くのIDはプロンプトにそれらを使用し、生成されたドキュメントツールもそれらを使用します!理由が何であれ、ドキュメントを書くことは優れた習慣です。
// 从 API 加载用户数据 function getUsers(callback) { var getUsersRequest = new XMLHttpRequest(); getUsersRequest.open('GET', '/api/users', true); getUsersRequest.addEventListener('load', function() { callback(JSON.parse(getUsersRequest.responseText)); }); getUsersRequest.send(); } // 从 API 加载帖子数据 function getPosts(callback) { var getPostsRequest = new XMLHttpRequest(); getPostsRequest.open('GET', '/api/posts', true); getPostsRequest.addEventListener('load', function() { callback(JSON.parse(getPostsRequest.responseText)); }); getPostsRequest.send(); } // 由于命名正确,因此无需阅读实际函数即可轻松理解此代码 // getUsers(function(users) { // // 对用户执行某些操作 // }); // getPosts(function(posts) { // // 对帖子执行某些操作 // });
イベントと非同期呼び出しはJavaScriptの強力な機能ですが、通常、コードの読み取りが難しくなります。
非同期コールは通常、コールバックを使用して提供されます。時々、それらを順番に実行するか、すべての非同期呼び出しが準備ができているのを待ちます。
function fetchJson(url, callback) { var request = new XMLHttpRequest(); request.open('GET', url, true); request.addEventListener('load', function() { callback(JSON.parse(request.responseText)); }); request.send(); } // 下面的代码仍然很容易理解 // 无需阅读上面的函数 fetchJson('/api/users', function(users) { // 对用户执行某些操作 }); fetchJson('/api/posts', function(posts) { // 对帖子执行某些操作 });
Promiseオブジェクトは、ES2015(ES6とも呼ばれます)で導入され、両方の問題を解決しました。ネストされた非同期リクエストを平らにすることができます。
function HttpRequest(url) { this.request = new XMLHttpRequest(); this.body = undefined; this.method = HttpRequest.METHOD_GET; this.url = url; this.responseParser = undefined; } HttpRequest.METHOD_GET = 'GET'; HttpRequest.METHOD_POST = 'POST'; HttpRequest.prototype.setMethod = function(method) { this.method = method; return this; }; HttpRequest.prototype.setBody = function(body) { if (typeof body === 'object') { body = JSON.stringify(body); } this.body = body; return this; }; HttpRequest.prototype.setResponseParser = function(responseParser) { if (typeof responseParser !== 'function') return; this.responseParser = responseParser; return this; }; HttpRequest.prototype.send = function(callback) { this.request.addEventListener('load', function() { if (this.responseParser) { callback(this.responseParser(this.request.responseText)); } else { callback(this.request.responseText); } }, false); this.request.open(this.method, this.url, true); this.request.send(this.body); return this; };
他のコードを導入しましたが、これは正しく説明しやすいです。 Promiseの詳細はこちらをご覧ください:JavaScriptは非同期(そして素晴らしい)になります
new HttpRequest('/users') .setResponseParser(JSON.parse) .send(function(users) { // 对用户执行某些操作 }); new HttpRequest('/posts') .setResponseParser(JSON.parse) .send(function(posts) { // 对帖子执行某些操作 }); // 创建一个新用户 new HttpRequest('/user') .setMethod(HttpRequest.METHOD_POST) .setBody({ name: 'Tim', email: 'info@example.com' }) .setResponseParser(JSON.parse) .send(function(user) { // 对新用户执行某些操作 });
function getApiUrl() { /* ... */ } function setRequestMethod() { /* ... */ } function findItemsById(n) { /* ... */ } function hideSearchForm() { /* ... */ }
結論
読みやすく保守可能なコードを書くことについてどう思いますか?以下のコメントであなたの考えを聞きたいです。
読み取り可能なコードに関するFAQ
プログラミング言語を読みやすくするのはなぜですか?
関数はコードの量をどのように減らしますか?
マシンコードと高レベルの言語の違いは何ですか?
通訳者とコンパイラはどのように機能しますか?
アセンブリ言語とは何ですか?
コードの読みやすさを改善する方法はいくつかあります。これらの方法には、意味のある変数と関数名の使用、コードの一貫したインデント、コードのさまざまな部分のスペースを分離し、コードの役割を説明するコメントが含まれます。また、使用しているプログラミング言語の慣習とベストプラクティスに従うことも重要です。
コメントは、コードを読み取り可能にする上で重要な役割を果たします。それらは、コードの機能、特定の決定が下される理由、および複雑なコードパーツがどのように機能するかについての説明を提供します。これは、コードを理解して使用する必要がある他の開発者にとって非常に役立ちます。ただし、コメントを簡潔に関連し、コードが変更されたときに更新することが重要です。
非常に読みやすいコードは、コラボレーションを大幅に促進します。コードが読みやすい場合、他の開発者が貢献を理解し、関与する方が簡単です。これは、複数の開発者がコードベースのさまざまな部分で作業している大規模プロジェクトで特に重要です。また、読み取り可能なコードにより、新しいチームメンバーがグループに登場しやすくなり、コードが何をし、どのように機能するかを迅速に理解できるためです。
非常に読みやすいコードは、ソフトウェアの品質を大幅に向上させることができます。コードが読みやすい場合、エラーを見つけて修正し、コードがすべきことを実行していることを確認するのが簡単です。また、コードの各部分の役割を明確に示しているため、時間の経過とともにソフトウェアを維持および強化しやすくなります。これにより、より信頼性が高く、効率的で、より強力なソフトウェアにつながる可能性があります。
以上が人間が読むことができるコードを書くことの重要性の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。