JavaScriptコードと問題のいくつかを解決する方法 - プログラミングの原則

プログラミングについては、私のお気に入りは、この問題を解決することです。私は、誰もが問題を解決するための生得的な能力を持っているとは思いません。繰り返し運動を通じて確立し、維持する能力です。任意の運動と同様に、のような、あなたがより効果的に問題を解決するための能力を向上させることができますガイドラインのセット。私は私の問題解決プロセスを導いたことを最も重要な5つのソフトウェアの設計原理を導入し、かつ実用的な問題を解決するために、これらの原則を適用する方法を紹介します。

1.はそれをシンプルに保ちます

あなたはこの記事から取得する必要があります任意の情報を持っている場合、それは原則「それシンプルに保つ」、です。この原理は、一般的にKISSとして知られ、それは「愚かな、それシンプルにしてください」を表します。

非常に複雑であるだけで、我々は問題を解決する必要があるため、それが当社のソリューションは非常に複雑にしていることを意味するものではありません。

一般的に、我々はこれらの問題を容易に解決することができるように複雑な問題にシンプルなソリューションを開発するために、サブ問題でシンプルに複雑な問題を打破します。

簡単な例を見てください:

あなたは、対称ブレースやブラケット中間文字列をチェックする機能を書きたいとしよう。例えば、一つだけ「(falseを返します、「()」trueを返します「(」のみ、falseを返します)」の場合、文字列「fooが」trueを返します。

だから、私たちはどのように行うのですか?

要約を書くためのアルゴリズムのために、KISSの原則を適用するための最初のステップ。

一部の文字で、文字列に与えます。

  1. 左から開始した文字は、各文字の後ろに見えます。
  2. (のすべての発生を記録します。
  3. 録音は、()を終了する前に発生しました。
  4. これらの文字は無視(または)されていません。
  5. 一つだけ)とない場合(リターンの偽。
  6. 真残っシングル(または)リターンが存在しない場合、我々は、最後の文字の観測が完了したら。

関心事の分離2.(SoC)の

当社のアルゴリズムは、3つの論理ドメインを有します。
かどうかは、文字を観察し続ける、または真または偽の論理を停止して返すために - ?続行または停止。
括弧タリー - 論理的な統計(と)の文字が表示されます。
で、次を見てすることは何? - どのような次の論理的な観察を決定します。
のは、3つの論理ドメインへの6つのステップの上にマッピングしてみましょう:
続行または中止? 括弧タリー 次は何を見て
一つだけ)とない場合(リターンの偽。 (のすべての発生を記録します。 左から開始した文字は、各文字の後ろに見えます。
真残っシングル(または)リターンが存在しない場合、我々は、最後の文字の観測が完了したら。 記録が表示される前に)(終了します
これらの文字は無視(または)のされていません

私達はちょうど私達のアルゴリズムは3つの論理ドメイン、特定の問題に対処するために、各ドメインに分割されました。それぞれの特定の問題領域は、独立したソフトウェアコンポーネントによって対処することができます。これらの3つのソフトウェア・コンポーネントは、特定のタスクを達成するために設計されており、他のコンポーネントが何をしているかを気にしないでください。これは懸念の分離、またはいわゆるSoCの原則ことを示しています。

SoC開発には多くの変化の複雑なアプリケーションやシステムソフトウェア部分を持つための鍵です。Webアプリケーションは、それぞれの表現(Webページの外観)、ビジネスロジック(Webコンテンツ)とコンテンツ配信(JSON APIを介してアクセスリソースに、データベースクエリなど)との関係を紹介します。

不十分なSoCの実行

ソフトウェアは、異なるドメインに分割されるが、私は、設計が不十分なソフトウェアを見てきましたが、関心事の分離はありません。次の例を考えてみます。

数字の配列内のすべての番号をインクリメントし、その後倍増関数fooを書きます。

1 
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22


//ヘルパー関数
関数arrIn { arrOut = [] のためには、 iは= 0 ; I <arrIn.length; iが++){ arrOut [I] = arrIn [I] * 2 } 戻り arrOut } 関数インクリメントarrInを { arrOut = [] のために iは= 0 ; I <arrIn.lengthを、iは++){ arrOut [I] = arrIn [I] + 1 } 戻り arrOutを}














// FOOの
関数 FOOarrIn { 戻りインクリメント(二重(arrIn))}


これはなぜなSoCの場合は失敗したのですか?

まあ、ダブル方法インクリメント方法は、各要素を変更するために、配列を横断含まれます。ことを注意ダブル方法増分法は、異なる配列の要素を除いてほぼ同じルックスをどのように機能するか以外が変更されました。これはとして知られている定型

長いあなたのコードのように定型文書、あなたは懸念の分離点で改善のためのより良い部屋を持つことができることを知っています。これは、1つの原則が含まれます。

3.自分(DRY)を繰り返してはいけません

ユアセルフ(DRY)の原則とのSoC共存を繰り返してはいけません。DRY原則狙いする抽象形成重複やソフトウェア減らすために定型を、私は抽象的に別の記事を書くが、ここではどのように適用するかである可能性が抽象的にキーポイントを繰り返さない書き込みコードに:

  • 関数の一般的なソフトウェアモデルを作成します。私たちは、高階関数と呼ばれます。
  • あなたのコードを置き換えることができます高度な方法を使用し、定型を

高階関数のいくつかの例は次のとおりです。

  • map - 指定された規則に従って、配列の各要素を変更します。
  • filter - 与えられた条件の配列のサブセットを取得します。
  • reduce - すべての指定されたルールアレイの合計含有量

私たちはDRY原則を適用しようと書き換えfooに使用するmapエキスに高階関数を定型

1 
2
3
4
5
6
7
8
//まあ懸念やDRYコードの分離を実行します

constのダブル= elemは => elemは* 2
のconst INCREMENT = < 大列  プログラミングの原則- javascriptのコードで問題のいくつか解決する方法スパンクラス= "機能"> elemは => elemは+ 1を

関数 FOOarrIn {リターン arrIn.map( ELEM =>インクリメント(二重(ELEM)))}


まあ、これは長い回り道です。私たちは、hasBalancedParenの問題に戻ることができますか?

!私たちは、およそ最終的な解決に到達することですが、我々が必要とする原則があります:

4.分割統治(分割統治アルゴリズム)

あなたは、アルゴリズム設計の文脈での「分割統治」を聞くと、再帰をご検討ください。用語 - 再帰 - 数学的基礎は通常無限のシーケンスを作成するために自分自身を更新するための規則を繰り返し適用を必要とするが、物事の次のシーケンスは、シーケンス内の一つのことに依存しています。例えば、フラクタル、フィボナッチ数とパスカルの三角形を再帰的に構築されます。

代わりにシーケンスを構築するのは、我々は問題空間を解体したい、最終的に、最終的な解を返し、ルールを繰り返し適用されるに分割統治アルゴリズムについては、我々は興味を持っています。次のコードは、基本的な構造を有する再帰関数アルゴリズム分割統治で:

1 
2
3
4
5
6
関数 recursiveFun入力、出力 {場合、我々は、ベースヒット場合、更新された出力として必要と戻り、最終的な出力を


そうでない場合は、入力を簡素化します。出力は、更新戻り recursiveFun(simplerInput、updatedOutput)を}


焦点は、問題は、我々はすぐに関数の先頭に結果を返すことができます解決するために非常に簡単になるまで入力(パラメータ)を簡素化することです。これは、いわゆる基本ケースである。(個人が最低レベルの条件の理解だけでなく、少なくとも、条件が満たされています)。私たちは、再帰関数の意志の基本ケースを追加する方法を忘れてしまった場合は?非常に単純なメモリ爆発。

私たちは分割統治アルゴリズムを実装するために再帰関数を使用する必要はありません。私たちは、ループと可変データ構造を使用することができます。それは時々、より効率的であるが、私は、変数のデータ構造のファンではありません。

変数のパーティションを達成するために再帰関数やデータ構造を使用しての簡単な例で見てみましょう:

オプション1:再帰関数
1 
2
3
4
5
6
7
8
9
10
11
12
関数の ARR {

機能の 追加ARR、合計 { //基本ケースの場合(arr.length === 0リターン合計



//再帰的ステップの戻りアド(arr.slice(1)、和+ ARR [ 0 ]) }



リターンアドオン(ARR、0// < -初期値
}
Option 2: Mutable Data Structure
1
2
3
4
5
6
7
8
9
10
11
12
function sum(arr) {

// Initial Values
let result = 0
let elems = arr // <-- mutable data structure

while(elems.length > 0) { // <-- Base Case
result += elems.pop() // <-- Recursive step
}

return result
}

函数式编程和单行程序的爱好者将使用更高阶的函数reduce执行如下,JavaScript为您提供Array原型的开箱即用功能:

const sum = (arr) => arr.reduce((res, elem) => res + elem, 0)

使用分治,我们有了解决最后一个重要问题的原则,来解决 hasBalancedParen 问题:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// Parentheses Tally
const newOpenCnt = (c, openCnt) => {
if(c === '(') return openCnt + 1
if(c === ')') return openCnt - 1
return openCnt
}

function isBalanced(str, openCnt) {
// Continue or Stop?
if (typeof str !== 'string') return false
if (openCnt < 0) return false
if (str.length === 0) return openCnt === 0

// What to Look At Next?
const fst = str[0]
const rst = str.slice(1)
return isBalanced(rst, newOpenCnt(fst, openCnt))
}

関数 hasBalancedParenSTR {リターン isBalanced(STR、 0}


おすすめ

転載: www.cnblogs.com/lijianming180/p/12032650.html
おすすめ