Principles of Programming - how to solve some of the problems with the javascript code

About programming, my favorite is to solve the problem. I do not believe anyone has the innate ability to solve problems. It is the ability to establish and maintain through repeated exercise. Like any exercise, like, a set of guidelines that can help you more effectively improve the ability to solve problems. I will introduce five most important software design principles that guided my problem-solving process, and show you how to apply these principles to solve practical problems.

1. Keep It Simple

If you have any information you need to get from this article, that is, "keep it simple" principle. This principle is commonly known as KISS, it represents "Keep it simple, stupid".

Just because we have to solve the problem is very complex, it does not mean that our solutions have to be very complicated.

In general, we break down complex problems into simple by sub-problems to develop simple solutions to complex problems so that we can easily solve these problems.

Look at a simple example:

Suppose you want to write a function to check the symmetrical brace or bracket an intermediate string. For example, only one '(' will return false, only a ') (' will return false, '()' will return true, then the string 'foo' will return true.

So, how do we do?

The first step to apply the KISS principle, for the algorithm to write a summary.

Give to a string, by some characters.

  1. A character Starting with the left, then look at each character back.
  2. Record every occurrence of (.
  3. Record occurred before to terminate) (.
  4. Those characters are not ignored (or) a.
  5. If only one) and not (returns false.
  6. Once we have completed the observation of the last character, if there are no remaining single (or) returns true.

2. Separation of Concerns (SoC)

Our algorithm has three logical domains:
Continue or Stop -? Whether to continue observing character, or stop and return true or false logic.
Parentheses Tally - logical statistics (and) characters appear.
What to Look At Next -? To decide what the next logical observation.
Let's map the above six steps to three logical domains:
Continue or Stop? Parentheses Tally What to Look At Next
If only one) and not (returns false. Record every occurrence of (. A character Starting with the left, then look at each character back.
Once we have completed the observation of the last character, if there are no remaining single (or) returns true. Before recording appears) to terminate the (
Those characters are not ignored (or) of

We just did our algorithm is divided into three logical domains, each domain to deal with specific issues. Each specific problem areas can be addressed by independent software components. These three software components are designed to accomplish a specific task, and do not care about what other components are doing. This indicates that the principle of separation of concerns, or the so-called SoC.

SoC development is the key to having a complex application or system software part of many changes. Web applications will introduce each representation (the appearance of web pages), business logic (Web content) and content delivery (to access resources through the JSON API, database queries, etc.) relationship between.

Poorly executed SoC

I have seen poorly designed software, although the software is divided into different domains, but there is no separation of concerns. Consider the following example:

Write a function foo that doubles then increments every number in an array of numbers.

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


// Helper Functions
function (arrIn) {
let arrOut = []
for (let i = 0; i < arrIn.length; i++) {
arrOut[i] = arrIn[i] * 2
}
return arrOut
}
function increment(arrIn) {
let arrOut = []
for (let i = 0; i < arrIn.length; i++) {
arrOut[i] = arrIn[i] + 1
}
return arrOut
}

// foo
function foo(arrIn) {
return increment(double(arrIn))
}

Why is this a case of SoC failed?

Well, Double methods and increment method involves traversing the array to modify each element. Note that double methods and increment methods other than how they function looks almost identical except different array element is changed. This is known as boilerplate .

As long as your code boilerplate documents, you know that you can have a better room for improvement at the point of separation of concerns. This involves the principle of one:

3. Don’t Repeat Yourself (DRY)

Do not Repeat Yourself (DRY) principle and SoC co-exist. DRY principle aims to form abstract to reduce duplication and software boilerplate , I could write a separate article on the abstract, but here is how to apply the abstract to write code that does not repeat the key points:

  • Create a function common software model. We called higher-order functions.
  • Use advanced methods that can replace your code boilerplate

Some examples of higher-order functions include:

  • map - modify each element of the array according to a given rule.
  • filter - Get a subset of the given conditions array
  • reduce - The combined content of all given rules array

Let us apply DRY principle and rewritten footo use maphigher-order functions to extract boilerplate :

1
2
3
4
5
6
7
8
// Well executed separation of concerns and DRY code

const Double = elem => elem * 2
const INCREMENT = < large column  programming principles - how to solve some of the problems with the javascript code span class = "function"> elem => elem + 1

function foo(arrIn) {
return arrIn.map(elem => increment(double(elem)))
}

Well, this is a lengthy detour. We can go back to hasBalancedParen problem?

! We are about to reach a final solution, but there is a principle that we need:

4. Divide and Conquer (divide and conquer algorithm)

When you hear the "Divide and Conquer" in the context of algorithm design, please consider recursion. The term - recursion - mathematical foundation usually requires repeated application of rules to update themselves to create an infinite sequence, the next sequence of things is dependent on one thing in the sequence. For example, fractal, Fibonacci number and the Pascal triangle are constructed recursively.

For divide and conquer algorithm, we are interested in is the repeated application of rules, instead of building a sequence, we want to deconstruct the problem space and eventually returns the final solution. In the following code, the divide and conquer algorithm a recursive function having a basic structure:

1
2
3
4
5
6
function recursiveFun(input, output) {
if we hit a base case, updated output as necessary and return the final output

otherwise, simplify the input. update the output then
return recursiveFun(simplerInput, updatedOutput)
}

The focus is to simplify input (parameters) until the problem becomes very simple to solve then we can immediately return a result in the beginning of the function. This is the so-called base case. (Personal understanding of the conditions for the lowest level, but also at least the conditions are met). If we forget how to add a recursive function will base case? Very simple memory explosion.

Note that we do not need to use a recursive function to implement divide and conquer algorithm. We can use a loop and a variable data structure. I'm not fan of variable data structures, although it is sometimes more efficient.

Let's look at a simple example of using recursive functions and data structures to achieve a variable partition:

Option 1: Recursive Function
1
2
3
4
5
6
7
8
9
10
11
12
function sum(arr) {

function add(arr, sum) {
// Base Case
if (arr.length === 0) return sum

// Recursive Step
return add(arr.slice(1), sum + arr[0])
}

return add(arr, 0) // <-- Initial Values
}
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))
}

function hasBalancedParen(str) {
return isBalanced(str, 0)
}

Guess you like

Origin www.cnblogs.com/lijianming180/p/12032650.html