Go back to Richel Bilderbeek's homepage.
Go back to Richel Bilderbeek's C++ page.
This is the answer of exercise #6: refactoring quadratic solver.
Below the original code is shown:
#include <cmath> |
There are many ways to Rome to improve this class, but I'll start at looking at the member functions 'coeff' and 'solve': why is it necessary to temporarily store three doubles when you want to solve a quadratic equation using these three doubles? Or: why does the user first needs to set these three values, before solving them? In my humble opinion, the place to start improving this class is to remove the member functions 'coeff' and directly pass these three doubles to 'solve'.
#include <cmath> |
In the resulting piece of code, the variables 'a','b' and 'c' are needed only locally to 'solve' (instead of class scope). This removes the need to internally store these three doubles in the private section:
#include <cmath> |
Can we refactor the piece of code above? Sure we can! As you could have read, the number of solutions of a quadratic equation can be zero, one or two. In the code above we face the following design problems:
The solution to these problems is to let the method 'solve' return a std::vector containg all solutions (returning an empty std::vector for zero solution):
#include <cmath> |
In the resulting piece of code, the variables 'x1' and 'x2' are needed only locally to 'solve' (instead of class scope) and the methods 'root1' and 'root2' are no longer needed. This results in the following code:
#include <cmath> |
Now, we have ended up with a stateless class with only one member function! Therefore, nothing stops you from making it a function:
#include <cmath> |
Now, what is left to do? Well, the first part of the first 'if' statement ('if ( a == 0' ) is nonsense: if 'a' equals zero and 'b' equals non-zero, the solution of the equation is x = c/b. If 'a' equals zero and 'b' equals zero, the solution is x = 0.
#include <cmath> |
The function above works fine. The only thing left to do is doing some cleaning:
|
Now we're done.
Personally, the only thing I would do, is add some personal tastes to the function. The code above is fine, the code below is just as good, but I personally like it better:
#include <cmath> |
Of course, I already had the function SolveQuadratic on my website :-D.
About the literature I took the example from [1]: it was written in 2001 and therefore written before the most important C++ books about class design. The author admitted in the example that the class indeed could have been written as a function. Also, the class example was given before the student knew about std::vector.
But in my humble opinion, it still is an example of bad class design. I would suggest the following class:
#include <cmath> |
Go back to Richel Bilderbeek's C++ page.
Go back to Richel Bilderbeek's homepage.