When writing object-oriented code from scratch, I try to follow these steps:
- Write a test that fails.
- Write a function that makes the test pass.
- When enough tests and functions are complete, refactor functions with similar signature into a class.
- When the class functionality is complete, make private as many of the class methods as possible.
The last step seems sound to me, since object orientation is all about hiding complexity behind abstractions, and keeping the public part of those abstractions as small as possible.
However, this leads me to discard many of the tests that I wrote when still working with plain functions — since they are now testing the private part of a class' API. This makes me uncomfortable because:
remaining tests are suddenly forced to "cover more complexity".
For instance: if I wrote a method to
swap_rows
in a matrix while inverting it, but that method is now private and only used from the public methodinvert
, then thetest_invert
has to somehow convey to the reader that "swapping rows happens while inverting".More importantly, that remaining test possibly will not pinpoint that it is the swapping of rows that has been broken by a careless change (and not any other part of the inverting process).
private class methods may become public again when writing client code that has a reasonable cause to access their results.
This is difficult to foresee. Recovering the tests from a previous commit is possible but it feels like wasted time.
A solution would be to refactor the methods out into a helper class that is package private. However, this looks like abusing object-oriented principles for the sake of TDD principles; also, it makes me wonder if there will ever be a good reason to make something private at all.
I realize I am asking here about "how to grow an architectural design", and that this cannot be done in a completely "bottom-up" approach; but I would like practical advice on keeping or discarding such early tests while still figuring out the shape of a piece of software.
This question is similar, but here I do not question that it is possible to get an initial public API right with TDD: I seek for good advice on how to get there. This answer is useful, but I do not think I am trying to adapt my coding to my tests, but rather my tests to my — still uncertain — design.
To summarize: should I keep or discard early tests while writing object-oriented code from scratch? Should I still strive to make as many methods as possible private, or is this leading me to a bad design and the forced removal of tests is just a symptom thereof?