Big talk refactoring serial 16: Super function

Source: Internet
Author: User

Things are always like this: when we endure a legacy system, endure, endure, and endure ... Finally accumulate to one day, really unbearable, outraged, can not endure again, reconstruct!

That's how it happened.

At this point, however, you suddenly find that the refactoring work is so complicated that I don't know where to start. The mountains of the problem, the design of the desired changes.

Here is an idea, there is a train of thought, what all want to do, but what can not do, really brain mess.

At this time, there is no reasonable step. A clear plan, it is critical to be reckless, and it will bring an unexpected future to your refactoring.

Countless experiences tell me, no matter what the system is. What architecture to use, from the decomposition of large functions to start, certainly not wrong.

The big function is the super method that the business logic is very complicated, the program code is very much, and the one who mentions it is a headache. Super large function, very difficult to read, more difficult to maintain and change, is undoubtedly the hardest hit of software degradation. It may not be complex at first, it is logically clear and easy to read, but as business logic changes over time. Constantly add code to the inside, coupled with some unreasonable design, after forever, become more and more bloated, the super-large function is thus produced.

The generation of super-large function has its intrinsic objective reason. Why do you say that? We talked before. The objective law of software development is that business logic is more and more complex. As business logic becomes more complex, the right approach is to refactor and optimize our code in a timely manner. But it's very regrettable. Almost very few people recognize this.

The result is that as business logic becomes more complex, people always add new code to the original program structure. The original clear and simple procedure. As new code continues to be added, it becomes more complex and difficult to understand.

Because of this, the super function becomes a common problem in the legacy systems of most software companies. Let's use HelloWorld as an example to evolve its course.

As mentioned in chapter III above, the most initially HelloWorld procedure is this:

/** * The refactoring ' s hello-world program * @author Fangang */public class HelloWorld {/** * Say hello To everyone * @param now * @param user * @return The words-to say */pub  Lic String SayHello (Date now, Stringuser) {//get-hour of day calendar calendar                   =calendar.getinstance ();                   Calendar.settime (now);                                     int hour =calendar.get (calendar.hour_of_day);                   Get the right words to sayhello String words = null;                   if (hour>=6 &&hour<12) {words = "goodmorning!";                   }else if (hour>=12&& hour<19) {words = "goodafternoon!";                   }else{words = "goodnight!"; } words = "Hi," +user+ ".                   "+words; return words; }}

Dozens of lines of code, simple and straightforward. Then began to change, first of all, about the time the greetings became complex, and added some special holiday questions, such as New Year Greetings "Happy new year! ", Valentine's Day Greetings" Happyvalentine ' s day! ", 38 women's Day Greetings" Happy women ' sday! ”。 Wait a minute.

At the same time. The greetings of the day also become more refined.

For this kind of demand, the IT siege lion starts to rewrite with the keyboard:

/** * The refactoring ' s hello-world program * @author Fangang */public class HelloWorld {/** * Say hello To everyone * @param now * @param user * @return The words-to say */pub                   Lic String SayHello (date now, Stringuser) {//get current month, date Andhour.                   Calendar Calendar =calendar.getinstance ();                   Calendar.settime (now);                   int hour =calendar.get (calendar.hour_of_day);                   Int month =calendar.get (calendar.month);                                     int day = Calendar.get (calendar.day_of_month);                   Get the right words to sayhello String words = null;                   if (month==1 &&day==1) {words = "happynew year!";                   }else if (month==1 &&day==14) {words = "happyvalentine ' day!"; }else if (month==3 &AMP;&Amp;day==8) {words = "happywomen s day!";                                     }else if (month==5 &&day==1) {words = "Happylabor day!"; ...... }                   else if (hour>=6&& hour<12) {words = "goodmorning!";                   }else if (hour==12) {words = "goodnoon!";                   }else if (hour>=12&& hour<19) {words = "good afternoon!";                   }else{words = "goodnight!"; } words = "Hi," +user+ ".                   "+words;         return words; }}

The amount of code starts to double. Then, the customer requests that all user information should originate from the Database user table, the same time the greeting rules table design, all about the time of the greetings should be derived from the table query.

Then we continue to swell SayHello () This method:

/** * The refactoring ' s hello-world program * @author Fangang */public class HelloWorld {/** * Say hello To everyone * @param now * @param user * @return The words-to say */pub                   Lic String SayHello (Date now, Longuserid) {//get database connection.                   try {class.forname ("oracle.jdbc.driver.OracleDriver");                   } catch (ClassNotFoundException E1) {throw newruntimeexception ("No found JDBC driver");                   The String url = "Jdbc:oracle:thin: @localhost: 1521:helloworld";                   String username = "Test";                   String password = "Testpwd";                   Connection Connection;                   try {connection =drivermanager.getconnection (Url,username,password); } catch (SQLException E1) {throw NewruntimeexcEption ("Connect database failed!");                   }//get Current month, date Andhour.                   Calendar Calendar =calendar.getinstance ();                   Calendar.settime (now);                   int hour =calendar.get (calendar.hour_of_day);                   Int month =calendar.get (calendar.month);                                     int day =calendar.get (calendar.day_of_month);                   Get the right words to sayhello String words = null;                   String greetingrulesql = "Select Words,month, Day, Hourlower, hourupper from Greeting_rules"; try {preparedstatementstatement = Connec                            Tion.preparestatement (Greetingrulesql);                            ResultSet resultset= statement.executequery (); while (!resultset.islast ()) {IntmonthoFrule = Resultset.getint ("month");                                     Intdayofrule = Resultset.getint ("Day"); if (month==monthofrule&& day==dayofrule) {words= resultset.getstring (                                               "Words");                                     Break                                     } Inthourlower = Resultset.getint ("Hourlower");                                     Inthourupper = Resultset.getint ("Hourupper"); if (hour>=hourlower&& hour

This is a very simple demonstration example, but we can see that it has been expanded from just a dozen lines to more than 60 lines, inflating 4 times times more. In the last version number. SayHello () is responsible for connecting the database, querying the data, and getting the month, date, and hour of the current time. Also complete the inference of the corresponding business logic. Makes the program quite complex.

We can continue to imagine, assuming that new requirements continue to be proposed. For example, support for multiple languages, multi-database support, program quality will continue to decline. Until we can't stand it.

The most effective way to solve the problem of super-large function is decomposition, which is decomposed according to the function. Restore the optimal structure that it should have. The refactoring method we often use in this process is called "extraction method (ExtractMethod)". Refactoring is a process of exploration, as we are always at first not aware of the systems to be refactored, without designing documents (even if there are. Right or wrong?). People who are not familiar with the system (even if they are just asking when they are not clear). You, only to receive the task to start taking over the system, your knowledge of the system is a cat black. And then. The extraction method is where we begin to explore and understand the most effective tools of the system, which are often done like this:

When we are reading a large function, we are able to consciously and unconsciously fragment the code, writing a gaze for a functionally relatively independent code. Sometimes we may need to adjust the order of the code to put together some code that has many other associations. If you put the declaration of a variable together with the code that the variable actually uses. Or put together code that has obvious relationships.

This adjustment is a good start. Because it makes our code start to become orderly. Start to become readable.

Then we are able to use the "extraction method". It is a very important good habit to extract the code from the original function and put it in a separate function to give the function an understandable name. I often think about a very long time, even several times, to give a function a correct name. Don't think it's a waste of time. It is also an important part of optimizing code.

But at first our understanding of this code may not be so deep, so we often choose to name it with the result variable. As we understand this piece of code in depth. You can use the Rename method (Renamemethod) in refactoring to name it again based on its code intent (many development tools, such as Eclipse, support this refactoring method, which allows you to synchronously change all calls to the method at the same time you rename it). After this extraction of the code snippet, the original code becomes a call to the new function here.

Give me a sample. At this time a real legacy system, the original program is written like this:

         ......         INTICTBZ =-1;         Elecobjelecobj = null;         Get processing time         INTICZYF = integer.valueof (Stream[9]). Intvalue ();         Stringczmonth = string.valueof (iczyf%). ToString (). Trim ();         Stringczyear = string.valueof ((ICZYF-(iczyf%))/+ +).                      ToString ();         if (czmonth.length () = = 1) {           Czmonth = "0" + czmonth;         }         LONGLBLSJ = long.valueof (Czyear + czmonth). Longvalue ();         Stringdqyear = sysdate.tostring (). substring (0, 4);         ......
This code is not well written, there are a lot of places that need our optimization. But remembering the principle of "small steps" is not the time to solve other problems, now we first use the extraction method to optimize the program structure.

After extraction. The above bold section is changed to this:

         ......         INTICTBZ =-1;         Elecobjelecobj = null;         Get processing time         INTICZYF = integer.valueof (Stream[9]). Intvalue ();         LONGLBLSJ = GETBLSJ (ICZYF);         Stringdqyear = sysdate.tostring (). substring (0, 4);         ......

The bold part is the rewritten content, and at the same time the extracted content is put into a separate function:

/*** @param iczyf* @return Gets the processing time */private long GETBLSJ (int iczyf) {         String czmonth = string.valueof (iczyf%20). ToString (). Trim ();         String czyear = string.valueof ((iczyf-(iczyf%))/+ +).                   ToString ();         if (czmonth.length () = = 1) {             Czmonth = "0" + czmonth;         }         Return long.valueof (Czyear +czmonth). Longvalue (); /*** @param iczyf* @return Gets the processing time */private long GETBLSJ (int iczyf) {         String czmonth = string.valueof (iczyf%20). ToString (). Trim ();         String czyear = string.valueof ((iczyf-(iczyf%))/+ +).                   ToString ();         if (czmonth.length () = = 1) {             Czmonth = "0" + czmonth;         }         Return long.valueof (Czyear +czmonth). Longvalue ();

When naming this newly created function. Our understanding of this code is not profound. In the original function. The result of this code operation is to obtain the result variable LBLSJ, that is, the processing time. To do this, we first name the function getblsj the function name. But in the possible work, we gradually understand that it can not only get the processing time, but also can get a lot of time. It is essentially converting time from one representation to another, so we use the rename function of the development tool to name the function transformdate, and the other code that calls it changes.

The renamed function is no longer used only to get the processing time here. It is also applied in the processing of other business code.

The extraction method can be very small, you can take a hundreds of lines of code to take away, it may be just a few rows. However, the extracted code must be functionally cohesive, meaning that they run a function that is Chiang Dao and clearly understood.

At the same time, the code being taken away must be a clear function of running, not multiple. It can be large and small, large and perhaps also can be decomposed into several functions. But at least logically, these features are part of this big feature.

The extraction method is a process of exploration, the most important thing is where the red line is drawn, that is, the range of the code.

More than one line is also right. A small line is also right. The key is the function we extract, and how we define its function.

Public speaking public management. Po said that the reason, there is no conclusion. Therefore, the extraction of the method is often counter-duplicated. We started with a thought and thought it was incorrect, so we put back the original function. Another division, another extraction, repeated several times.

Once, when I was refactoring a servlet, the extracted function was running a large segment of business logic operations.

But after a series of business operations, the original program will convert the return value into binary code written to response. Returns the front end. At first, I pulled out the whole section. However, it is very uncomfortable that the transfer of response must be sent in, which makes the business logic and the Web application environment coupling, not conducive to future optimization. Write your own proactive test. I then restored this code, and once again I extracted it, leaving the part of the writing response in the original function. The red line is drawn after the business logic operation, before writing to response. The newly refactored function is decoupled from the Web application. Prepare for further optimization in the back.

The process of refactoring is the process of testing the developer's ability, which requires you to repeat the exercises and delve into it.

In addition, the extraction method is like nuclear fission, starting from a function fission into several functions. The decomposed function is divided into several other functions. Keep on going like this. At the same time, the extraction method always takes place in a class of fission. And when this kind of decomposition of the method to a certain extent, followed by a class of fission, from a class decomposed into multiple classes, decomposition of the class decomposition ... Decomposition of classes we are using a method-"Extract class", which we will describe later.

Refactoring is a series of isometric transformations. The extraction method is the most typical example of these isometric transformations.

Extract a piece of code from the original function, and the code is still the code. Only the program structure has been transformed.

Because of this, talent ensures that our refactoring process is safe and reliable.


Big talk Reconstruction serial home: http://blog.csdn.net/mooodo/article/details/32083021

Special NOTE: I hope that netizens in the reprint of this article, should indicate the author or source, to show respect for the author, thank you!


Big talk refactoring serial 16: Super function

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.