JavaScript from if else to switch case to abstract _javascript tips

Source: Internet
Author: User
Tags switch case
My answer is, more than two else if, or switch for more than two case. But is it normal to use a lot of if else and switch case in your code? Wrong! Most of the more than two of the if else and switch case should not appear as hard coded (hard-coded).
where complex branches come from
The first question we have to discuss is why there are so many complex branches in the legacy code. These complex branches often do not exist in the first version of the code, assuming that the person doing the design has a bit of experience, he should anticipate where it might need to be expanded in the future, and reserve the abstract interface.

However, after several iterations of the code, especially after several adjustments to the requirements details, the complex branches appear. The need for detail adjustment, often not reflected in UML, but will be directly reflected in the code. For example, the original message is divided into two types of chat messages and system messages, design will naturally be designed as a message class of two subclasses. But then one day the need for detail adjustment, the system message is part of the important, their title to be shown in red, when the programmer will often do the following modifications:
Add a important attribute to the system message class
Add a branch of the important property to the corresponding Render method to control the caption color
Why would programmers make such a change? Maybe it's because he didn't realize that he should be abstract. Because demand says "part of the system message is important", for programmers who are trained more in the imperative programming language, the first thing he might think of is the sign bit--a sign bit that distinguishes between important and unimportant. He didn't think the demand could be interpreted in another way, "system messages are divided into two categories, important and unimportant." In this way, he knew that the system message should be abstracted.
It is possible, of course, that the programmer knows it can be abstracted, but for some reason he chooses not to. One of the most common situations is that someone is forcing a programmer at the expense of code quality in exchange for the speed of the project--adding a property and a branch, much simpler than the abstract refactoring, if you want to do 10 of this form of modification, is to do 10 branches fast or 10 abstract fast? The difference is obvious.
Of course, if more, there are wise people come out and say, "Let's switch case". " In some cases, this can actually improve the readability of the code, assuming that each branch is mutually exclusive. But when the number of switch case is also more, the code will become unreadable.
What's the downside of complex branching ?
What's the downside of complex branching? Let me from the Baidu Hi Web version of the old code to intercept a paragraph out to do an example.
Copy Code code as follows:

Switch (json.result) {
Case "OK":
Switch (Json.command) {
Case "message":
Case "SystemMessage":
if (Json.content.from = = ""
&& Json.content.content = = "kicked") {
* Disconnect * *
else if (Json.command = "SystemMessage")
|| Json.content.type = = "Sysmsg") {
/* Render System Message * *
} else {
/* Render Chat message * *
}
Break
}
Break

This code is easy to read, so I'm going to ask you a simple question about which branch this JSON hits:
Copy Code code as follows:

{
"Result": "OK",
"Command": "Message",
"Content": {
"From": "Catchen",
"Content": "Hello!"
}
}

It's easy for you to get the correct answer: this JSON hit/* Render chat message/(show chat messages) This branch. So I want to know, how did you make this judgment? First, you want to see if it hits the case "OK": the branch, the result is a hit; then you want to see if it hits the case "message": The branch, the result is also hit, so the case "SystemMessage": no need to see; Next, it does not hit the condition inside the IF; Also, it does not hit the condition in else if, so it hits the else this branch.
Can you see the problem? Why can't you just look at this else and say this JSON hit this branch? Because else itself does not contain any conditions, it only implies conditions! The condition of each else is the result of the first negation and operation of every if and else if before it. That is, judging a hit on this else is equivalent to judging a set of complex conditions for a hit:
Copy Code code as follows:

! (Json.content.from = = "" && json.content.content = = "kicked") &&! (Json.command = = "SystemMessage" | | | json.content.type = "SYSMSG")

Then set up the outer two switch case, the condition of this branch is this:
Copy Code code as follows:

Json.result = = "OK" && (Json.command = = "message" | | json.command = = "SystemMessage") &&! (Json.content.from = = "" && json.content.content = = "kicked") &&! (Json.command = = "SystemMessage" | | | json.content.type = "SYSMSG")

There is a repetition logic in this, which is omitted as follows:
Copy Code code as follows:

Json.result = = "OK" && Json.command = = "Message" &&! (Json.content.from = = "" && json.content.content = = "kicked") &&! (Json.content.type = = "Sysmsg")

How much effort did we take to derive such a long string of logical expressions from the simple else four letters? Moreover, does not look closely also really does not understand this expression to say is what.
This is where complex branches are difficult to read and manage. Imagine you face a switch case set an if else, there are a total of 3 case, each case has 3 else, which is enough for you to study--each branch, the condition implies that all of its predecessor branches and all ancestor branches of the predecessor branch first and then the results.
How to avoid complex branches
First, complex logic operations cannot be avoided. The results of refactoring should be equivalent logic, and all we can do is make the code easier to read and manage. Therefore, our focus should be on how to make complex logic operations easier to read and manage.
Abstract as a class or factory
For those accustomed to doing object-oriented design, this may mean breaking and distributing complex logic operations into different classes:
Copy Code code as follows:

Switch (json.result) {
Case "OK":
var factory = commandfactories.getfactory (Json.command);
var command = Factory.buildcommand (JSON);
Command.Execute ();
Break
}

This looks good, at least the branches are getting shorter, and the code becomes easier to read. This switch case just the status Code branch, for "OK" This status code specific how to deal with, that is the other kind of things. GetFactory may have a set of branches that focus on the choice of which factory should be chosen to create this instruction. At the same time Buildcommand may have other trivial branches that decide how to build this instruction.
The advantage of this is that nested relationships between branches are lifted, and each branch is as good as it is in its own context. For example, GetFactory is now a named function, so the branch within this function can only implement the contract implied by the name GetFactory, without paying attention to the context in which getfactory is actually invoked.
Abstract for pattern matching
Another approach is to relay this complex logic operation to pattern matching:
Copy Code code as follows:

Network.listen ({
"Result": "OK",
"Command": "Message",
"Content": {"from": "", "content": "Kicked"}
}, function (JSON) {/* disconnect */});
Network.listen ([{
"Result": "OK",
"Command": "Message",
' content ': {' type ': ' Sysmsg '}
}, {
"Result": "OK",
"Command": "SystemMessage"
], function (JSON) {/* Render system Message */});
Network.listen ({
"Result": "OK",
"Command": "Message",
"Content": {"From$ne": "", "Type$ne": "Sysmsg"}
}, func tion (JSON) {/* Render chat message */});

Is this so much clearer now? In the first case, it is kicked off the line and must match the specified from and content values. The second scenario is to display system messages, because system messages are slightly different in two versions of the protocol, so we're going to capture two different JSON matches, whichever is hit. The third scenario is to display chat messages, because the system message and the boot line instruction in the old version agreement belong to the special chat message, in order to be compatible with the old version protocol, these two cases should be excluded from the display chat message, so the suffix of "$ne" (representing not equal) is used to match.
Since the Listen method is context-independent, each listen declares itself to match what JSON is, so there is no implied logic. For example, to capture chat messages, you must explicitly declare exclude from = = "" and type = = "Sysmsg", which do not need to be inferred from the context if else.
Using pattern matching can greatly improve the readability and maintainability of your code. Since we're capturing JSON, we use JSON to describe what each branch is capturing, which is much clearer than a long logical expression. At the same time, every modification on this JSON is independent, and modifying one condition does not affect other conditions.
Finally, how to write a pattern matching module, which is beyond the scope of this article.
Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.