📜 ⬆️ ⬇️

Technique: Compilation of methods (refactoring M. Fowler)

Beginning Code with a nice smell (M. Fowler refactoring) .
In the sequel, the refactoring technique of the book Refactoring. Improvement of the existing Martin Fowler code .

The syntax will be in C #, but the main thing is to understand the idea, and it can be used in any other programming language.

Drawing up methods.


  1. Selecting a method ( convert a code snippet to a method whose name explains its meaning ).
    The long method is divided into logical sub-methods.
    From
    void PrintUserInfo(decimal amount) { PrintParentInfo(); Console.WriteLine(string.Format(": {0}", name); Console.WriteLine(string.Format(": {0}", age); Console.WriteLine(string.Format("-: {0}", amount); } 

    To
     void PrintUserInfo(decimal amount) { PrintParentInfo(); PrintUserDetails(decimal amount); } void PrintUserDetails(decimal amount) { Console.WriteLine(string.Format(": {0}", name); Console.WriteLine(string.Format(": {0}", age); Console.WriteLine(string.Format("-: {0}", amount); } 

  2. Embedding a method ( place the body of the method in the code that calls it and delete the method ).
    Excessive indirection (breakdown into methods) can complicate a class.
    From
     int GetPoints() { return HasMaxSum() ? decimal.One : decimal.Zero; } bool HasMaxSum() { return summ >= maxSumm; } 

    To
     int GetPoints() { return summ >= maxSumm ? decimal.One : decimal.Zero; } 

  3. Embedding a temporary variable ( replace this expression with all references to this variable ).
    Extra intermediate code.
    From
     decimal cost = order.GetCost(); return cost > 1000; 

    To
     return order.GetCost() > 1000; 

  4. Replacing a temporary variable with a method call ( convert an expression to a method ).
    The method can be called anywhere in the class, if there are many such places.
    From
     decimal MethodA() { decimal summ = amount * cost; if(summ > 1000) { //do something return summ * 10; } return 0; } decimal MethodB() { //do something decimal summ = amount * cost; return summ != 0 ? summ * 100 : 1; } 

    To
     decimal MethodA() { decimal summ = GetSumm(); if(summ > 1000) { //do something return summ * 10; } return 0; } decimal MethodB() { //do something return GetSumm() != 0 ? GetSumm() * 100 : 1; } decimal GetSumm() { return amount * cost; } 

  5. Introduce an explanatory variable ( place the result of the expression or its part in a temporary variable ).
    Simplified reading and understanding of the code.
    From
     if(VisualItems.ColumnCount == FocusedCell.X && (key == Keys.Alt | Keys.Shift) && WasInitialized() && (resize > 0)) { // do something } 

    To
     bool isLastFocusedColumn = VisualItems.ColumnCount == FocusedCell.X; bool altShiftPressed = (key == Keys.Alt | Keys.Shift); bool wasResized = resize > 0; if(isLastFocusedColumn && altShiftPressed && WasInitialized() && wasResized) { // do something } 

  6. Splitting the explanatory variable ( create a separate temporary variable for each assignment ).
    Simplified reading and understanding of the code.
    From
     decimal temp = 2 * (height + width); Console.WriteLine(temp); temp = height * width; Console.WriteLine(temp); 

    To
     decimal perimetr = 2 * (height + width); Console.WriteLine(perimetr); decimal area = height * width; Console.WriteLine(area); 

  7. Delete assignments to parameters ( it is better to use a temporary variable ).
    Methods should not change the values ​​of incoming parameters unless explicitly stated (for example, out, ref in C #).
    From
     int Discount(int amount, bool useDefaultDiscount, DateTime date) { if(amount == 0 && useDefaultDiscount) { amount = 10; } return amount; } 

    To
     int Discount(int amount, bool useDefaultDiscount, DateTime date) { int result = amount; if(amount == 0 && useDefaultDiscount) { result = 10; } return result; } 

  8. Replacing a method with a method object ( convert the method to a separate object ).
    Class decomposition for code flexibility.
    From
     class MessageSender { public Send(string title, string body) { // do something // long calculation of some condition if(condition) { // sending message } } } 

    To
     class MessageSender { public Send(string title, string body, decimal percent, int quantity) { // do something Condition condition = new Condition (percent, quantity, dateTime); if(condition.Calculate()) { // sending message } } } class Condition { public Condition(decimal percent, int quantity, DateTime dt) { } public bool Calculate() { // long calculation of some condition } } 

  9. Replacement of the algorithm ( replace the algorithm with a more understandable one ).
    Code optimization for better readability and / or performance.
    From
     string FoundPerson(List<string> people) { foreach(var person in people) { if(person == "Max") { return "Max"; } else if(person == "Bill") { return "Bill"; } else if(person == "John") { return "John"; } return ""; } } 

    To
     string FoundPerson(List<string> people) { var candidates = new List<string>{ "Max", "Bill", "John"}; foreach(var person in people) { if(candidates.Contains(person)) { return person; } } return ""; } 


A bit of reality and code review procedure.


Before refactoring or for checking the changes, code review procedure is used.
In this case, we are talking about the "comments" (criteria) of the reviewer.

The reality is that the line between these criteria may be different for each programmer, but it is tolerable - normal. It is worse when the reviewer has no third criterion, i.e. he is always right, and if he is wrong, then prove it to him (but not everything is conclusive, after all not a mathematician). Becoming a code committer, it is the other way around, it only applies the 3rd criterion.
And when two such people collide, it is a flame, screams (I saw it with a motherboard :)).
To resolve the conflict, we need 3 strength, as a rule another programmer (preferably with more experience) must express his opinion.

About conflicts of interest and their solutions will tell in the next article.

')

Source: https://habr.com/ru/post/173903/


All Articles