The other day, I was watching one of the Test Driven Development (TDD) episodes in the Clean Coder video series by Robert C. Martin. In the episode, Robert Martin (aka Uncle Bob) was using the Red-Green-Refactor approach to refactoring some HTML formatter class. As he was walking through the demonstration, something completely tangential struck me - his HTML formatter class had "state." The ease with which he invoked internal methods of this object gave me pause - I think "state" is something that I have been overlooking for a long time.
Historically, when I've created a "utility" class, I've done so with the intention of using it as a singleton that has an exposed method. This requires the class to be stateless, being used over and over again by many requests in a given application. As a side effect of this approach, any state required internally would have to be passed around with every internal method call.
This creates long, private method signatures that obfuscate the meaning of the code. If I were to, instead, treat the singleton as a "newable" entity, to be instantiated as needed, I could maintain useful state information that would allow for the coding of smarter private methods.
To put this in practical terms, let's look at a service object that I created for an AngularJS application. A while back, I blogged about how AngularJS maps the view model ($scope) onto DOM (Document Object Model) elements using the $$hashKey property. To integrate cached data into this rendering approach, I created a service object that would copy the $$hashKey values from one data structure (the cached one) into another data structure (the live one).
This service object lived for the duration of the web app and exposed one method:
hashKeyCopyService.copyHashKeys( source, destination ) :: destination
Internally, the copyHashKeys() method builds up an index of all $$hashKey values contained within the source object; then, it applies this index to the destination object. And, since this service is a singleton, all of this data has to be passed around with every method call.
Now, what if I didn't use a Singleton? What if, instead, I instantiated this "service entity" every time that it was needed. From the outside, things would look fairly similar:
new HashKeyCopier( source, destination ).copyHashKeys() :: destination
... but, from the inside, things would be significantly more straightforward. Rather than passing around the state with every internal method call, state could be centralized; then, each private method could write to and read from that state information as necessary.
I think that I need to be thinking about state much more often. I think it will force me to create smaller, more cohesive components that have a focused responsibility. Perhaps this is the moment - the moment where I can look back and see a turning point in the way I think about and build software?