I've been 'aware' of an awesome feature from using the NullObject pattern since I really started using them. I didn't realize what that feature was until I had to explain it to a colleague today. I say it a lot, maybe not here, but in general - I LOVE TALKING ABOUT THESE THINGS!
Just in general, I really enjoy discussions about software development. I learn different things and often articulate things I just kinda 'do'. This NullObject super power is one of those.
The issue we were talking about was an apparent problem reading in configuration values. Because it's our domain, if we don't get a string value back, we return a NullText. This is our representation of a general 'no string returned'.
/* * The value returned for `NullText` should be updated to whatever * is appropriate for the including system. An EmptyString has always * been successful so far for me. Feel free to leave it if it works. */
I do things slightly differently in my latest experiments; but this still serves as the core idea and foundation of my NullObject pattern. And it's simplified.
MicroObjects style of development has A LOT of classes compared to an equivalent simple system. As the complexity increases, I bet MicroObjects is smaller. Still looking for a project to try that out on. :)
Anyway it takes a bit of time to understand the structure of this type of project (any, but sure, I'll give a little extra ramp for this).
The devs debugging the issue were seeing a
NullText instead of a
Text object with whatever value they expected. Trying to help them debug from my phone forced to think and simplify how I articulated ideas.
What popped up for me is how to identify where the problem could occur. This is how I try to debug things, I don't care /what/ the problem is; I care /where/ it is. Once I identify that, then I focus on what the problem is.
In this case, the problem is "Why
NullText, not expected value" - So how do we find that? MicroObjects has A LOT of hops. Which can confuse developers that are used to walking imperative code vs following object interactions.
Since they were seeing a
NullText the pattern, and the MicroObjects style, make it really easy to identify possible places - Find
return Text.NullInstance. It's one of those. There might be a few, but there will be only ONE that deals with your problem. This situation, it was getting a config value. There's only one place getting config values, so there's only one of the
return Text.NullInstance that is in a config related class.
There shouldn't be a lot of these either. This is a HUGE advantage over allowing
null in your code. This case, there wouldn't be ANY way to find the problem. Not even a
return null to trawl through.
NullObject pattern allows us to quickly and easily identify where the source of the 'unexpected' value comes from. Speeding up the debugging of the problem.
NullObject pattern is almost getting to the idea of Representing the Concept. It represents the "No Value Available" concept. I don't like to represent
null in my system. What does
null mean? Find a way to represent that. Null Object Pattern doesn't represent the concept, it is an object for the system's
null behavior. It exists, we are wrapping it in an object. This is WAY better than
null. I just think it's not as far as we should go with representation.
That's an entirely different rant; right now - Let's appreciate how the NullObject pattern helps us identify where our system is getting unexpected results.