Build a tool and then extract a library
Recently, I wrote tool X that accepts a Boolean SAT formula (in conjunctive form) along with a model/interpretation — an assignment of truth values to variables in the formula — and checks if the model satisfies the formula.
Then, I started planning for a tool Y that identifies a satisfying model (if one exists) for a given Boolean SAT formula. Clearly, tool Y could use the algorithm in tool X as a subroutine to check if a model satisfies the formula. For reasons such as efficiency (avoid data transfers between programs via the file system), simplicity of use (install one tool), and avoiding code duplication, it is better if tool X could be refactored into a tool t-X and a library l-X where t-X uses l-X. This would enable tool Y to use library l-X and be more efficient, simple, and avoid code duplication.
While all of the above makes sense from a software engineering perspective — reuse, simplicity, reduced code duplication, etc., I am now wondering “should I refactor tool X into t-X and l-X before I implement tool Y?”
Is one possible reuse good enough to refactor out a library from a tool?
I think the answer is No. My reasons are as follows:
- One possible reuse is not the same as one reuse. For all I know, it may be a sub-optimal idea to use the algorithm in tool X as subroutine in tool Y. So, it is better to verify such use is indeed optimal and then refactor tool X and tool Y.
- One reuse is not the same as multiple reuses. Once there is a (possible) second reuse, it makes more sense to refactor both tool X and tool Y. Until then, C-n-P will suffice as a simple and cost efficient option.
- Such refactoring entails the creation of a test suite for library l-X. Since test suite creation takes time and effort (even if it is based off of the test suite for tool X), it is best to delay it until the refactoring is necessary.
- Multiple uses can help design the interface of library l-X. The largest intersection of behaviors required by different uses can trivially help identify the behaviors to be captured by the library. Consequently, this can help design a general enough interface of library l-X that makes the behaviors accessible to many clients.
The above is nothing more than avoiding premature optimization.
Now, off to implementing tool Y :)