How to write an elegant program?

Source: Internet
Author: User

This article has been published by the author Wu Weiwei authorized NetEase Cloud community.

Welcome to NetEase Cloud Community, learn more about NetEase Technology product operation experience.


The necessary condition for writing an elegant program is a good design.


Writing a program is like walking a maze. At the beginning of the writing, there are several possible solutions that linger in our minds. We choose one that continues in depth and may reach the finish line-fulfilling functional requirements, but the greater possibility is to enter a cul-de-sac or a new fork that needs to be re-chosen, so repeated.


Think of myself a year ago, only with the instinct of Biology to write code: I follow the past experience, first wrote a paragraph. Then refresh the page to see if it's a step closer to fulfilling your needs. The illusion that the program works perfectly is what I see most is JavaScript errors and unexpected running results, something that QA calls bugs. So I made a change by instinct ... stupefied, I do not know how long after the program has finally run in a seemingly correct logical track. Well? Did you ask me if there was any bug in the program? I'm really not sure about that.


I need a map of the maze, avoiding all the dead ends and finding an optimal path to the exit, which is the design.


We design a program and PM to plan a product process is somewhat similar-first to collect and collate requirements, and then clear the need to implement the N-function, and then the implementation of the final sequence. The difference is that our users are ourselves, so we have a better advantage and easier to design an easy-to-use program.


The first step in the design process is to identify the functional points that need to be implemented in the program. Many function points are listed in front of them, are they implemented in a module, or a number of modules to achieve? If you divide multiple modules, what are the function points that each module implements? These problems of course can not be taken on the forehead decision, need to consider reusability and maintainability.


Imagine a login feature: We need to send the user information to the backend for verification, and if successful, refresh the page. The function is very simple, it is easy to write out the code:


Module Logic class Login {
Login () {this.verify (function () {window.location.reload ();
});
}
/**
* @description Verify user information.
* Callback function executed after @param callback {function} validation passed
*/
Verify (callback) {//do something
}
The}//module calls new login (). Login ();

Instant fix, so easy!


Not long after the completion of the new demand. Suppose just is page A, now to implement the landing logic in page B with a some difference: after the successful landing no longer page refresh, but directly update the page about the user information display.


How do we do it now? Re-implement a page B's Landing logic from scratch? First of all, to exclude this practice, after all, the logic of verifying user information has not changed, can be reused. Think about it and write down this code:


 

//Module Logic class Login {   /**
    *   @param state {number} 1 login After refreshing  2 login update user Data
    */
   login (state) {       this.verify (functio N () {           if (state = = = 1)                win Dow.location.reload ();            else if (state = = = 2)
               D Osomethingwithuserinfo ();
       });
   }    
   /**
    *   @description verify user information.
    *   @param callback {function} validation passed after the callback function
    */
   verify (callback) {       //do something
   }
}//module call//Login to refresh new login (). login (1);//update user data after login new Login (). Login (2);

Well, it's good to meet the demand. But this way of implementation is too stiff and not too flexible. Suppose there is a page C, page d, and its login logic in the successful execution of the operation is different. Once again, the implementation of the ' Login.prototype.login ' method needs to be modified, so the logic that used to run stably can be changed. A good program structure should be open to extensions and closed to modifications. That is, we do not need to modify the original code in anticipation, regardless of which operations are added to the successful login.

So, refactor the following:


Module Logic class Login {

Login () {this.verify (function () {this.doafterlogin ();
}.bind (this));
}
/**
* @description Verify user information.
* Callback function executed after @param callback {function} validation passed
*/
Verify (callback) {//do something
}
/**
* @abstract
*/
Doafterlogin () {//Subclass implementation specific logic
}
}class LoginA extends Login {
Doafterlogin () {window.location.reload ();
}
}class Loginb extends Login {
Doafterlogin () {
Dosomethingwithuserinfo ();
}
}//module Call//Login Refresh New LoginA (). Login ();//update user data after login new LOGINB (). Login ();


Extract some common logic into the parent class ' Login '. After the successful landing of the operation of each change, only need to inherit the ' Login ' class, in the new subclass to implement the specific logic. This does not have any effect on the existing functionality. Absolutely perfect!


In complacency, new demand has come. Let's say that we're going to implement page E, page F. The operation after landing on page E is to refresh the page, and the same as a. The operation after landing in page F is to update the user information display, the same as B. But they no longer validate user information through their backend, but through Urs and VRS (don't ask me what the VRS is ...). )。 The part that needs to be reused now is not just the ability to verify the user's information, but also the operations performed after the successful login. In the face of such a demand, only through inheritance is not able to maximize the functionality of the existing functions, you need to login verification and execution of the operation of these 2 function points into different modules. Thus, this can be achieved:


Module Logic class Verify {/**
* @abstract
* @description Verify user information.
* Callback function executed after @param callback {function} validation passed
*/
Verify (callback) {//Subclass implementation specific logic
}
}class Verifynormal extends Verify {
Verify (callback) {//Authenticate through your own background
}
}class Verifyurs extends Verify {
Verify (callback) {//verified via URS
}
}class Verifyvrs extends Verify {
Verify (callback) {//through VRS authentication
}
}class Login {
/**
* @param verify {Verify}
*/
Login (verify) {
Verify.verify (function () {this.doafterlogin ();
}.bind (this));
}
/**
* @abstract
*/
Doafterlogin () {//Subclass implementation specific logic
}
}class LoginA extends Login {
Doafterlogin () {window.location.reload ();
}
}class Loginb extends Login {
Doafterlogin () {
Dosomethingwithuserinfo ();
}
}
module invocation

Normal login, refresh the page after landing
New LoginA (). Login (New Verifynormal ());
Normal login, update user information display after login
New Loginb (). Login (New Verifynormal ());
URS Login, refresh page after login
New LoginA (). Login (New verifyurs ());
URS Login, update user information display after login
New Loginb (). Login (New verifyurs ());
VRS login, refresh page after login
New LoginA (). Login (New Verifyvrs ());
VRS login, update user information display after login
New Loginb (). Login (New Verifyvrs ());


To summarize: If a module has only one reason for the change (only after the login operation will change), it can be inherited to meet the open/close principle (opening to the extension, closing the modification). However, if a module has multiple reasons for changes (such as the post-login operation and the login verification process will change), we need to divide one of the reasons into another module. A module can only have one reason for change (single duty principle). The functional points are friendly to each module, then a good program of the embryonic shape is also molded out, the rest is to the inside of the hard fill.



NetEase Cloud Free Experience Pavilion, 0 cost experience 20+ Cloud products!

More NetEase technology, products, operating experience sharing please click.


Related articles:
"Recommended" a Code specification for ECMASCRIPT2015 (Part Two)
"Recommended" Understanding the nature of DDoS protection: an intelligent system based on resource contest and rule filtering

How to write an elegant program?

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.