Temporary Field

Description (What)

A field in a class that is given its value and then subsequently used by particular methods and are undefined in the rest of the cases.

How to Locate It (Where)

Look for fields that aren't explicit assigned a value in the constructor or are assigned default or garbage values in the constructor and fields that are used only in one method in the class and are assigned their proper values in that method.

Also look for fields that get their value based on type code/if-else/switch statements where they get their value based on satisfying a condition but remain unassigned in other conditions.

How it Manifests (Why)

Temporary fields might arise from the need of variables for complex algorithms or functions in a class that need them and are required to be defined in the fields of the class.

How to Fix It (Possible Treatments)

In Example 1, we use Extract Class. This treatment moves the fields and the methods that require them into their own class such that in the new class, the field is always assigned a proper value. This way the field is always populated with a correct value on object instantation.

In Example 2, Introduce Null Object is used. This treatment introduces a Null Object to prevent Null-Pointer error.

Other treatments are also possible based on the specific scenario, they can be found here

Examples

Example 1

Before:

Variables a and b are always used but c is used only when Quadratic/Cubic equations need to be solved and d only when Cubic equations need to be solved.

Observed Code Smells:
- Temporary Field (lines 4-5)

After:

Applied Extract Class to extract all the methods into their own Classes 'LinearSolver', 'QuadraticSolver' and 'CubicSolver' and deleted the original 'PolynomialSolver' class

Refactoring Applied:
- Temporary Field
    - Extract Class (LinearSolver, QuadraticSolver, CubicSolver)
Observed Code Smells After Refactoring:
- None

Example 2

Before:

The line 50 is checking if a customer is null, considering this case of nullable customer is reasonable

in such a scenario, some object should be created to capture this situation and prevents program crashes

from NullPointer issues.

Observed Code Smells:
-  Temporary field (line 40, 47, 54)

After:

Apply Introduce Null Object by creating a new subclass of Customer called NullCustomer,

mostly just an informative temp variable for checking for null.

Refactoring Applied:
- Temporary Field:
    - Introduce Null Object (line 22, line 40-48, line 56, line 65, line 74)
Observed Code Smells After Refactoring:
- None

When to Ignore

None

More

More about Temporary Field

001  class PolynomialSolver {
002   private int a;
003   private int b;
004   private int c;
005   private int d;
006  
007   public PolynomialSolver(int a, int b) {
008   this.a = a;
009   this.b = b;
010   }
011  
012   public PolynomialSolver(int a, int b, int c) {
013   this.a = a;
014   this.b = b;
015   this.c = c;
016   }
017  
018   public PolynomialSolver(int a, int b, int c, int d) {
019   this.a = a;
020   this.b = b;
021   this.c = c;
022   this.d = d;
023   }
024  
025   public void solveLinear() {
026   if (this.a == 0) {
027   if (this.b == 0) {
028   System.out.println("Infinite Solutions");
029   } else {
030   System.out.println("No solution");
031   }
032   } else {
033   System.out.println(-this.b / this.a);
034   }
035   }
036  
037   public void solveQuadratic() {
038   // check if c exists
039  
040   if (this.a == 0) {
041   solveLinear();
042   }
043  
044   double discriminant = Math.pow(this.b, 2) - 4 * this.a * this.c;
045  
046   if (discriminant > 0) {
047   double x1 = (-this.b + Math.sqrt(discriminant) / (2 * this.a));
048   double x2 = (-this.b - Math.sqrt(discriminant) / (2 * this.a));
049   System.out.println("Solutions: " + x1 + ", " + x2);
050   } else if (discriminant == 0) {
051   double x = (-this.b) / (2 * this.a);
052   System.out.println("One real solution: " + x);
053   } else {
054   double real = -this.b / (2 * this.a);
055   double imaginary = Math.sqrt(Math.abs(discriminant)) / (2 * this.a);
056   System.out.println("Complex solution: " + real + ", " + imaginary);
057   }
058   }
059  
060   public void solveCubic() {
061   //check if c, d exists
062  
063   if (this.a == 0) {
064   System.out.println("Coefficient 'a' is zero, solving as a quadratic equation:");
065   solveQuadratic();
066   return;
067   }
068   double B = this.b / this.a;
069   double C = this.c / this.a;
070   double D = this.d / this.a;
071   double p = C - B * B / 3;
072   double q = D - (B * C) / 3 + 2 * (B * B * B) / 27;
073   double delta = (q / 2) * (q / 2) + (p / 3) * (p / 3) * (p / 3);
074   if (delta >= 0) {
075   double u = Math.cbrt(-q / 2 + Math.sqrt(delta));
076   double v = Math.cbrt(-q / 2 - Math.sqrt(delta));
077   double y1 = u + v;
078   System.out.println("One real solution for cubic equation (from Cardano's method): x = " + (y1 - B / 3));
079   System.out.println(
080   "Note: Finding the other two roots involves complex numbers or more intricate calculations.");
081   } else {
082   double phi = Math.acos((-q / 2) / Math.sqrt(-((p / 3) * (p / 3) * (p / 3))));
083   double y1 = 2 * Math.sqrt(-p / 3) * Math.cos(phi / 3);
084   double y2 = 2 * Math.sqrt(-p / 3) * Math.cos((phi + 2 * Math.PI) / 3);
085   double y3 = 2 * Math.sqrt(-p / 3) * Math.cos((phi + 4 * Math.PI) / 3);
086   System.out.println("Three real solutions for cubic equation (trigonometric method):");
087   System.out.println("x1 = " + (y1 - B / 3));
088   System.out.println("x2 = " + (y2 - B / 3));
089   System.out.println("x3 = " + (y3 - B / 3));
090   }
091   }
092  }
093  
094  public class TFBE1 {
095   public static void main(String[] args) {
096   PolynomialSolver ps = new PolynomialSolver(10, 12);
097   ps.solveLinear();
098   PolynomialSolver ps2 = new PolynomialSolver(10, 12, 14);
099   ps2.solveQuadratic();
100   PolynomialSolver ps3 = new PolynomialSolver(10, 11, 12, 13);
101   ps3.solveCubic();
102   }
103  }
104