RE: WhatWhat about Performance?
Dear reader, if you'reinspired by comments
One might be frowning upon the code demonstrated above, saying "it'll not perform well enough""it'll not perform well enough". If that's the case, then, dear reader, please pause for a moment and bear with me, because you completely missed the point of the answer.
"Make the change easy, then make the easy change" - a quote from "Tidy first" by Kent Beck, the father The goal of TDD and Extreme programmingthese changes is to improve the design to enable further changes.
The point is that introducing changes into a code that is far from being clean is costly. Is some cases, it makes sense to improve the design,father of TDD and then make an "easy change".Extreme programming Kent Beck in his book "Tidy first" expressed this idea in the following way:
Make the change easy, then make the easy change
Introducing changes into a code that is far from being clean is costly. Is some cases, it makes sense to improve the design, and then make an "easy change".
Design should evolve in small incremental changes. Trying to create from scratch an implementation which works correctly, which is clean, which is performant is counterproductive. TheHere's the proper (least painful / time-consuming) sequence would beof actions leading to performant code:
- make it work (i, i.e. the code should pass all test (no more, not less), without spreading your focus on anything else;
- make it clean;
- improveoptimize the performance.
It's akin to the metaphor of hats in TDD (you can wear only one hat at a time). YouWe need to be focusedfocus on achieving only one goal at a time, evolving the code in small incremental steps.
SoThe same holds true, when it comes to refactoring existing code the first change that enables a massivesame principle applies as well. Tiding the code should happen separately from making performance improvementoptimizations. It's called a preparatory refactoring. Otherwise, an attempt to optimize a ball of mud is already donelikely to produce a code which is still a mess and has a suboptimal performance -(in the worst case you end up with the broken code and rolling back the changes losing time for no avail).
So, what performance tweaks we can introduce with the current design changes?
Eliminating the hack with the static variable and making the method for finding palindromic product is a pure function. Which means it's by itself already gives a room for leveraging referentialy transparentreferential transparency,. Since the result of its execution doesn't change, hence it can be computed only once and cached reducing time complexity to constant. Functional languages like Haskell are leveraging this quite a bit (I'm leaving the research on how to achieve it in Java as homework).
Another performance improvement, we can make is to not mess withquit employing strings at allwhile checking if a number is palindrome.
But first we need tests (note they already have to be in place during the phase of creating a solution that "just works" and not tidy and performant):.
Note, tests should already be in place during the first phase of writing a solution that "simply works" and neither clean, no performant
Now we can just plug another implementation ofreimplement isPalindrom(int) which doesn't mess with string, but instead is based onusing modular arithmetic instead of messing with strings:
Method isPalindrome(String candidate) becomes a dead codedead code and goes away, we don't need it anymore.
So, the main point is:
Before improving the performance of the palindrome check, it makes sense to define this functionality properly in the first place. It's called a preparatory refactoring. Otherwise, you'll end up with a mess (and potentially even with the broken code).
DESIGN MATTERS period
The algorithm of going through combinations can be improved as well, it's a simple brute force, but I'm not going to poke into this topic, there are already too many things to unpack here.