I've been trying to refactor some existing code which is in essence a giant nested procedural call inside what should otherwise be an object oriented architecture. The entry point to the relevant code is a static function, which iteslf calls other static functions calling other static functions etc. totaling to a few thousand lines of code. At a high level, the calls perform two actions of
- Performing metadata updates prior to real work
- Executing work related to the call
For the metadata updates, it can be further subdivided into 3 sections which are relatively granular
- Query for some data related to the overall call
- Use information from step 1 to update physical file level metadata
- Use information from step 1 to perform a metadata update at a higher abstraction level than step 2
Originally I had created a class to handle all of the metata updates, with 3 private methods for each of the work. Roughly the following code
class Metadata(...) {
def updateOnEvent(...): Unit = {
val data = queryFromStep1()
if (data.requiresUpdating) {
updatePhsicalFileMetadata(data)
}
updateHigherLevelMetadata(data)
}
private def queryFromStep1(): Data = ???
private def updatePhsicalFileMetadata(data: Data): Unit = ???
private def updateHigherLevelMetadata(data: Data): Unit = ???
}
The issue I'm having is that I feel the urge to unit test the 3 private methods here, and my understanding is that this is a sign of a poor class abstraction.
My next thought was to extract each method into a separate class, and test each class individually, in addition to tests for the Metadata
class to make sure everything is glued together properly. However this doesn't seem to be a great solution either since now we have many tiny classes each exposing only a single public method, with no private methods either.
I'm wondering what a better solution could possibly be. I'm hesitant to expose all 4 methods as public from the Metadata
class, because the caller really only cares about updateOnEvent
for the purpose of handling an event. Is there a simple solution I'm missing? I can provide more details if needed.