Drink Remodeling Series [4]--decomposition method

Source: Internet
Author: User

Overview

The idea of "decomposition method" is basically the same as the "extracting Method" and "extracting Method Object" mentioned earlier.
It is the continuous splitting of the methods of larger individuals, allowing each "method" to do a single thing, thus improving the readability and maintainability of each method.
The decomposition method can be regarded as the recursive version of "Extracting Method", which is a kind of reconstruction strategy for the method's iterative refinement.

Decomposition method

In this paper, the strategy of "extracting method" is adopted for the 1th and 2nd refining of this reconstruction strategy.

When is the decomposition method?

The "Decomposition method" can ultimately make the method more readable, and usually we can tell whether the method needs decomposition based on the following points:

1. Each method should only do one thing (the degree of understanding of the matter, determines the granularity of the matter)
2. Methods should be as short as possible, preferably not more than 20 lines (depending on the situation, as appropriate, consider the number of rows)
3. The indentation level of the method should not be too much, preferably not more than two levels
4. Method requires too many annotations to understand the example

In the enterprise annual budget scenario, users need to fill in the account, department, and month budget data according to the following Excel template, and then import the Excel file into the budget system.

To represent each line of budget data that the user fills out, the developer has designed two class:budgetitem (budget items) and Budgetitemdetail (budget item details) in the system.
The red box is labeled as a Budgetitem object, and each blue box corresponds to a Budgetitemdetail object.

BudgetItem.cs and BudgetItemDetail.cs
<summary>///Budget Item//</summary>public class budgetitem{public    string Dept {get; set;}    public string Account {get; set;}    Public ilist<budgetitemdetail> budgetitemdetails {get; set;}} <summary>///Budget Detail//</summary>public class budgetitemdetail{public    string Month {get; set;}    Public decimal Amount {get; set;}}
Before refactoring

When the developer represents this logic, a Budgetitemimport class is written that reads Excel and returns the Ilist<budgetitem> collection

Hide Code
public class budgetitemimport{Private regex _monthregex = new Regex (@ "\d{4}\\\d{2}"); Public ilist<budgetitem> Getbudgetitems (string path) {//Read Excel get datatable datatable table = Exce        Lutil.renderfromexcel (path);        Gets the column name that represents the month ilist<string> monthcolumns = new list<string> (); for (var i = 0; i < table. Columns.count; i++) {var columnName = table. Columns[i].            ColumnName;            if (_monthregex.ismatch (ColumnName)) {Monthcolumns.add (columnName);        }}//Traverse DataRow get budgetitems ilist<budgetitem> budgetitems = new list<budgetitem> (); for (var i = 1; i < table. Rows.Count; i++) {//Get DataRow datarow datarow = table.            Rows[i]; Create a Budgetitem object and set up department and account information Budgetitem Budgetitem = new Budgetitem {Dept = datarow[ 0]. ToString (), account = DataRow[1].            ToString ()};            Create Budgetitemdetail collection Ilist<budgetitemdetail> budgetitemdetails = new list<budgetitemdetail> ();                foreach (var column in monthcolumns) {//Create Budgetitemdetail object and set budget month and corresponding amount                    Budgetitemdetail detail = new Budgetitemdetail {Month = column,                Amount = Convert.todecimal (Datarow[column])};            Budgetitemdetails.add (detail);            } budgetitem.budgetitemdetails = Budgetitemdetails;        Budgetitems.add (Budgetitem);    } return budgetitems; } }

Without these comments, the Getbudgetitems () method is more difficult to read than the above code.
Next, we use the "decomposition method" strategy to reconstruct it.

First time refactoring

The Getbudgetitems () method did a total of 3 things, explaining its logic.


Adhering to the "one way only thing" principle, we split these 3 things out.

Hide Code
public class budgetitemimport{Private regex _monthregex = new Regex (@ "\d{4}\\\d{2}"); Public ilist<budgetitem> Getbudgetitems (string path) {//Read Excel get datatable datatable table = Exce        Lutil.renderfromexcel (path); Gets the column name that represents the month ilist<string> monthcolumns = getmonthcolumns (table.        Columns);    Read DataTable get Budgetitem Collection return getbudgetitemsfromdatatable (table, monthcolumns); }//Gets the column name that represents the month private ilist<string> getmonthcolumns (DataColumnCollection collection) {Ilist<str        ing> monthcolumns = new list<string> (); for (var i = 0; i < collection. Count; i++) {var columnName = Collection[i].            ColumnName;            if (_monthregex.ismatch (ColumnName)) {Monthcolumns.add (columnName);    }} return monthcolumns; }//Read DataTable get Budgetitem collection Private ilist<budgetitem> getbudgetitemsfromdatatable (DataTable table, Ilist<string> monthcolumns) {//traverse DataRow get budgetitems ilist<budgetitem> budgetitems = new        List<budgetitem> (); for (var i = 1; i < table. Rows.Count; i++) {DataRow datarow = table.            Rows[i]; Create a Budgetitem object and set up department and account information Budgetitem Budgetitem = new Budgetitem {Dept = datarow[ 0]. ToString (), account = Datarow[1].            ToString ()}; Create a Budgetitemdetail collection and set the month and amount of each Budgetitemdetail object ilist<budgetitemdetail> budgetitemdetails = MonthCo Lumns. Select (column = new Budgetitemdetail {Month = column, Amount = Convert.todec iMAL (Datarow[column])}).            ToList ();            Budgetitem.budgetitemdetails = budgetitemdetails;        Budgetitems.add (Budgetitem);    } return budgetitems; } }
Two-time refactoring

Although split into 3 methods, but the new addition of the Getbudgetitemsfromdatatable () method is still not good readability, this method we still need to use annotations to read.
We analyze the internal logic of this method in detail, and getbudgetitemsfromdatatable () This method also does 3 things, see:

Following this more detailed logical flow, we split the 3 things up again.

Hide Code
public class budgetitemimport{Private regex _monthregex = new Regex (@ "\d{4}\\\d{2}"); Public ilist<budgetitem> Getbudgetitems (string path) {//Read Excel get datatable datatable table = Exce        Lutil.renderfromexcel (path); Gets the column name that represents the month ilist<string> monthcolumns = getmonthcolumns (table.        Columns);    Read DataTable get Budgetitem Collection return getbudgetitemsfromdatatable (table, monthcolumns); }//Gets the column name that represents the month private ilist<string> getmonthcolumns (DataColumnCollection collection) {Ilist<str        ing> monthcolumns = new list<string> (); for (var i = 0; i < collection. Count; i++) {var columnName = Collection[i].            ColumnName;            if (_monthregex.ismatch (ColumnName)) {Monthcolumns.add (columnName);    }} return monthcolumns; }//Read DataTable get Budgetitem collection Private ilist<budgetitem> getbudgetitemsfromdatatable (DataTable table, Ilist<string> monthcolumns) {ilist<budgetitem> budgetitems = new list<budgetitem> (); foreach (DataRow datarow in table.            Rows) {Budgetitem Budgetitem = Getbudgetitemfromdatarow (DataRow, monthcolumns);        Budgetitems.add (Budgetitem);    } return budgetitems; }//Create a Budgetitem object and set up department and account information private Budgetitem Getbudgetitemfromdatarow (DataRow DataRow, Ilist<string> Mont Hcolumns) {Budgetitem Budgetitem = new Budgetitem {Dept = datarow[0]. ToString (), account = Datarow[1].        ToString (), budgetitemdetails = Getbudgetitemdetailsfromdatarow (DataRow, MonthColumns)};    return budgetitem; }//Create Budgetitemdetail collection and set the month and amount of each Budgetitemdetail object to private ilist<budgetitemdetail> GETBUDGETITEMDETAILSF Romdatarow (DataRow DataRow, ilist<string> monthc Olumns) {REturn monthcolumns.select (column = new Budgetitemdetail {Month = column, Amount = Conver T.todecimal (Datarow[column]).    ToList (); }}

After this refactoring, the readability of the Budgetitemimport class has been very good. Each method does only one thing, and each method is short, no more than 20 lines, and we don't even need to write comments for these methods.

Summary

After two refactoring, we've got a well-structured code. Reviewing the refactoring process for this example, we can use the following diagram to represent it.

Writing code is much like writing something else. When you write an article, write what you want to do first, and then polish it. The first draft may be ugly and disorderly, and you will carve a Zhang Yi sentence until you reach your mind.
We are not able to directly write a structured and readable approach, and at first our approach was complex and lengthy, with various loops, judgments, indents, and annotations.
Then we polished the code and solved each of these problems with a decomposition method.

Drink Remodeling Series [4]--decomposition method

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.