Review refactoring-improving the design of existing code

Source: Internet
Author: User

  • It re-organizes internal code without changing system behavior, improves comprehensibility and reduces modification costs.

  • A small modification involves multiple places, and these points are unknown.
  • Not easy to understand code (including reading your own code one month ago)
  • It takes a long time for a newbie to modify the code.
  • Slow response at the code layer when demand changes

  • Reconstruction anytime, anywhere, that is, small-scale reconstruction from the very beginning, so that it will not be smooth after a long time.
  • The above sentence is actually a methodology level. In reality, there is still no way to determine when to refactor, so it is changed to: refactoring is required when the Code has a bad taste.
  • What is bad taste:
    • When duplicate code exists
    • The function is too long.
    • Function parameters are too long
    • Unable to intuitively see the code Logic
    • The class is too large.
    • Multiple copies exist for a constant.
    • Many if/else/switch statements
    • Unfriendly class name, function name, and method name

  • Rebuild first, fine tune its times
  • Reconstruction can be well organized, and a good structure can make tuning easier.

  • Extract Method (extraction function)
    • When internal logic is too entangled, some code needs to be extracted into the sub-function.
  • Inline Method (Inline Function)
    • If a function has very few bodies and is not used by other functions, you can consider inserting this small function into the parent function.
  • Inline Temp (Inline temporary variable)
    • If a variable is used only once, and this variable represents little logic, you can consider copying the logic represented by this temporary variable directly to the parent function.
  • Replace Temp with Query (Replace temporary variables with queries)
    • If temporary variables are removed, this method is used to extract the logic represented by temporary variables into a single function.
    • Although it has an impact on the performance, we recommend that you change it to this mode if it is not a very serious impact on the performance after reconstruction, because reconstruction in the past will be more advantageous for subsequent reconstruction, making it easier for future reconstruction.
  • Introduce Explaining Variable (Introducing explanatory variables)
    • Assign logical fragments to well-named variable names, so that the code is more readable and understandable.
  • Split Temporary variable (break down Temporary variables)
    • A logic objective is only assigned to a temporary variable. Do not use temporary variables, for example:
    • Int temp = x + y;
    • // Some logic to process temp varialbe
    • Temp = getBase () + 100;
    • // Some logic to process the new temp varialbe
  • Remove Assignments to Parameters (Remove the value assigned to the parameter)
    • Do not assign values to input parameters. You must add temporary variables.
  • Replace Method with method Object (Replace functions with function objects)
    • For large functions, complicated logic, and many local variables
    • The idea is to separate this function into a class and process complicated logic in the class.
  • Substitute Algorithm (replacement Algorithm)
    • Replace the internal algorithms of the function, for example, for higher efficiency or better comprehensibility.
    • The intention is to improve efficiency or comprehensibility
  • In a general sense, the semantics is clearer.

  • Move Method)
    • If you find that a function is mainly dependent on data of other classes, it is necessary to move the function to that class.
  • Move Field)
    • Similar to the above, to which method is used for refactoring, you need to check the situation, such as the class name and responsibility definition.
  • Extract Class (extraction Class)
    • When a class contains a large number of functions and data, consider splitting the class.
  • Inline Class (associating classes)
    • When a class does not have sufficient responsibilities to become a class, consider merging this class into other classes.
    • For example, this situation weakens the role of a class after refactoring.
  • Hide Delegate (Hide "delegation relationship ")
    • Hides a class on the server, so that the client can perform logical operations only by knowing one class, without having to know multiple classes at the same time.
  • Remove Middle Man (Remove Man in the Middle)
    • Expose more classes for the client to call
    • It is difficult to determine whether to remove "man-in-the-middle". Generally, the module should be exposed as little as possible, depending on the situation inside the module.
  • Introduce Foreign Method (introduces an additional function)
    • When the provided function cannot be modified, you can add a function on the client to wrap the target function to complete insertion and conversion of additional logic.
    • There are not many additional functions.
    • It is not easy to use more, and eventually needs to be merged to the server where the target function is located
  • Introduce Local Extension (introducing Local extensions)
    • If the above conditions occur and there are many extensions, you can create a class on the client, import the original method or class through inheritance or Wrapper, and process additional methods, functions, and logic.

  • Self Encapsulate Field (Self-encapsulated Field)
    • C # uses attributes to resolve the issue. If fields are not referenced, attributes must be referenced so that the logic can be embedded when variable values need to be overwritten.
  • Replace Data Value with Object (Replace Data Value with Object)
    • When more common functions are available for a base metadata, You need to replace the base metadata with the object type, and then implement some common functions in this object to facilitate the caller's call.
  • Change Value to Reference (Change Value object to Reference object)
    • If the current value object is used in multiple places and you want to change one place, the reference in other places will also change. In this case, you need to convert this value object to a reference object.
    • Scenario: A value object is used at the beginning of the project, but later it is considered that the reference type is better, and the conversion is required.
  • Change Reference to Value (Change the referenced object to a Value object)
    • If a reference type exists and the reference type is small, and mutual modification between instances is not required, you can change the reference type to the value type, this ensures the immutability of this object.
  • Replace Array with Object (Replace Array with Object)
    • When an array is used to pass object attributes, classes can be used to replace this array.
  • Duplicate Observed Data (copy "monitored Data ")
    • Layer-to-layer winding call, caused by no layer division
    • Data transmission between layers through DTO
  • Change Unidirectional Association to Bidirectional (Change one-way Association to two-way Association)
    • Exercise caution and try to make one-way Association
    • Code for maintaining the other party must be added to the objects of both parties, such as Customer. AddOrder/Order. AddCustomer, which must appear in pairs.
  • Change Bidirectional Association to Unidirectional (Change Bidirectional Association to Unidirectional Association)
    • With the evolution of demand, two-way association is not required in a certain period of time.
  • Replace Magic Number with Symbolic Constant (Replace Magic Number with literal constants)
    • Replace the literal value with a const constant.
    • For example, some numeric values with special meanings in scientific computing must be referenced in a unified const.
  • Encapsulate Field (encapsulation Field)
    • After data and behavior are separated, since everyone can reference public data, it is not easy to manage and modify
    • If no data is exposed, you can only use the data in the current class.
  • Encapsulate Collection (encapsulation set)
    • The default List <T> Collection <T> ArrayList exposes too many internal logics, and the returned objects can be modified by the client, which is not conducive to isolation and encapsulation.
    • Write a collection class by yourself. Only a specific interface is exposed and a new copy of the object is returned, which can solve malicious and unintentional changes.
  • Replace Record with Data Class (Replace Record with Data Class)
    • Overwrite an object-oriented plane data type (such as an array or a passed attribute without a good name) into a class with only the private attribute.
    • The purpose is to prepare for further reconstruction.
  • Replace Type Code with Class (Replace Type Code with Class)
    • Type Code: enumeration, multiple string, int variables, such as: string Male = "Male" string Female = "Female"), and so on
    • Abstract The Type Code (which contains multiple fields but only distinguishes different types) into a Type Code class.
    • Make changes to references.
  • Replace Type Code with Subclasses (Replace Type Code with subclass)
    • It is identified by subclass, so that rewrite functions can be used to solve some behavior changes.
  • Replace Type Code with State/Strategy (Replace Type Code with State/Strategy)
    • Extract the changed part using the status and Policy Mode
  • Replace Subclass with Fields (Replace Subclass with field)
    • If the subclass simply returns some constants, You can abolish them, compress the inheritance level, and write the type judgment logic in the corresponding method of the parent class.

  • Decompose Conditional (decomposition condition expression)
    • The logic is often complicated, and there are many branches.
    • If a branch writes a lot of small pieces of code, it should also re-construct more semantic code.
    • Branches need to be reconstructed to be more semantic, which will improve readability.
  • Merge lidate Conditional Expression (merge condition Expression)
    • Generally, the parameter validity is checked at the function entry. if multiple if statements are written to determine that they are invalid and return false, the return false statements can be extracted to a separate function.
    • The semantics of the main function is clearer.
  • Merge lidate Duplicate Conditional Fragments (merge Duplicate condition Fragments)
    • If the same code is used at the beginning or end of each branch in the if/else branch, the code is extracted outside the if/else for unified calling.
  • Remove Control Flag)
    • In a loop, remove the control mark, such as the control mark bool found = false. when found, return obj/return directly;
  • Replace Nested Conditional with Guard Clauses (Replace Nested Conditional expressions with Guard statements)
    • Change if/else and nested if/else to a flat statement, for example:
    • If (xxx) return result + 1;
    • If (yyy) return result + 2;
    • If (zzz) return result + 3;
    • Return result + 4;
  • Replace Conditional with Polymorphism (Replace Conditional expressions with Polymorphism)
    • In the inheritance system with multiple subclasses, the parent class has a method for calculating: calculate different values based on different subclasses.
    • The template method is the same as the design mode.
  • Introduce Null Object (introducing Null Object)
    • Design Pattern for null objects
    • When null is allowed, the exception algorithm of the business logic can be implemented in NullObject, so that the judgment and forwarding of a bunch of if null are not required in the business logic class.
  • Introduce Assertion (introducing assertions)
    • Write Assert at the function entry to ensure that the corresponding preconditions are correct when the function is called.
    • If the assertions fail, the call stack information and custom information will appear in the log file.
    • System. Diagnostics. Trace. Assert: logs are recorded no matter whether Release or not.
    • System. Diagnostics. Trace. Debug: logs are generated only in Debug mode.

  • Rename Method (renamed function)
    • Modify the name of a function to be more semantic and improve readability.
    • Parameter order and parameter naming are also considered.
  • Add Parameter (Add Parameter)
    • Modified a function, but the function currently needs to use information that was not previously used
  • Remove Parameter (Remove Parameter)
    • The previous parameters are not required now.
  • Separate Query from Modifier (Separate the Query function from the modification function)
    • If a function modifies some values during the return value process, it will cause some troubles to the client caller and need to be split into two functions: Query and Modify.
  • Parameterize Method (parameters included in the function)
    • Extract common subfunctions within the function to flatten and make the code public.
  • Replace Parameter with Explicit Methods (Replace parameters with Explicit functions)
    • When the function behavior depends entirely on the parameter value, you need to split the function into multiple methods to avoid the internal logic of the function being too complex.
  • Reserve Whole Object (keep Object complete)
    • When the parameter of the called function is exactly a few of the attributes of an object, the object is passed in directly.
    • You must also consider whether the called function needs to be moved to this object.
  • Replace Parameter with Methods (Replace parameters with functions)
    • If the main function contains multiple subfunctions, and the returned values of these subfunctions are transmitted from the beginning and end to the end
    • In this case, except the last function, other subfunctions are called through the internal function rather than the main function.
  • Introduce Parameter Object (introducing Parameter objects)
    • When some parameters are always paired and stacked, consider this mode.
    • For example, DateTime from, DateTime end ==> DateRange
    • Int pageIndex, int pageSize ==> PagingInfo
    • And PagingResult <T> {TotalCount, List <T>}
  • Remove Setting Method (Remove the Setting function)
    • If the properties of a class do not need to be changed after construction, disable the corresponding set accessors.
  • Hide Method (hidden function)
    • If a function is not referenced by other classes, change it to private.
  • Replace Constructor with Factory Method (Replace constructors with Factory functions)
    • When a class has multiple subclasses and you want to generate a new object by using the type code, you can change the constructor to a factory method to facilitate client calls without knowing which subclass it is.
  • Encapsulate Downcast (encapsulation downward transformation)
    • It means that forced conversions of types must be implemented in specific functions rather than in client code.
    • Now. Net has a generic type, which reduces a lot of such troubles.
  • Replace Error Code with Exception (Replace the Error Code with an Exception)
    • In case of any exception in the code, throw new XXXXException ("xx") instead of the return errorCode method.
    • If the exception is controllable, it will be handled in catch (XXXException ex ).
    • If the exception is uncontrollable, you do not need to handle it.
    • Uncontrollable exceptions should be handled by a framework, such as an Error event in AOP or Global.
  • Replace Exception with Test (Replace Exception with Test)
    • Modify the logic of the catch exception misuse.
    • Use unit test + Assert + Boundary Value test to ensure that some exceptions are not triggered.

  • Pull Up Field (Field move Up)
    • When multiple child classes contain similar fields, you need to analyze whether to extract these similar fields to the parent class.
  • Pull Up Method (function move Up)
    • When there are similar functions in multiple subclasses, You need to analyze whether to extract these similar functions to the parent class.
    • If they are identical, they are extracted directly to the parent class.
    • If only one step fails, the public logic is upgraded to the parent class using the template method.
  • Pull Up Constructor Body (Constructor ontology moving Up)
    • The constructor In the subclass tries to assign values using the constructor of the parent class.
  • Pull Down Method (function Down)
    • When a function in the parent class is only related to a few sub-classes (not all), the function is placed in a specific sub-class to implement
  • Pull Down Field (move the Field Down)
    • When a field in the parent class is related to only a few subclasses (not all), the field is placed in a specific subclass.
  • Extract Subclass (Extract Subclass)
    • When Type Code exists or some instances of the class have different behaviors, the subclass needs to be extracted.
    • Some features of the class are only used by some instances.
  • Extract Superclass (Extract super class)
    • If multiple classes have similar features, you can add a new super class to extract the commonalities.
  • Extract Interface (Extract Interface)
    • Directly referencing a class exposes all methods
    • If you define interfaces according to your responsibilities and then let the class implement these interfaces, the encapsulation and concealment during the call will be much better.
  • Collapse Hierarchy (folding inheritance system)
    • When there is little difference between the parent class and the Child class, you can merge them to remove the hierarchical relationship.
  • Form Template Method (shaping Template functions)
    • It is actually an application of the template design model.
  • Replace Inheritance with Delegation (Replace Inheritance with Delegation)
    • When the subclass finds that integrated data and functions are not actually needed, or only a few parent classes of data and functions are used, the inheritance relationship can be removed, add a parent class reference to the current class and call the data and functions of the parent class through delegation.
  • Replace Delegation with Inheritance (Replace Delegation with Inheritance)
    • When many delegates are used between the two classes for calling, and the delegate coverage is a large range of the other party, consider changing the delegate to an inheritance relationship.

  • Tease Apart Inheritance (combing and decomposing the Inheritance system)
    • Split in bridging mode
  • Convert Procedural Design to Objects (converting Procedural Design into object Design)
    • OO object Creation
    • Separation of duties
  • Separate Domain from Presentation (separating Domain and Presentation/display)
    • MVC Mode
    • MVVM Mode
    • View and Domain Differentiation
  • Extract Hierarchy (Extract inheritance system)
    • Closed development principle
      • Open to expansion means that existing code can be expanded to adapt to new situations when there are new requirements or changes.
      • Closed modification means that once the class is designed, its work can be completed independently without any modification to the class.

 

 

 

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.