Failure is OK
Roland was working on code that implemented HTTP service methods. The 'status' variable held one of those pass-it-everywhere objects that were sometimes called 'RunData'. It contained the request, response, security context, and other needed information. When JavaScript sent an asynchronous HTTP request, one of the service methods performed some backend magic and returned a JSON object with the appropriate data.
That was the good case. In the bad case, the service method called status.fail, added one or more user messages, and returned without sending a reply. The error handling in the base class detected that the call failed, and sent an error response containing the user messages.
Roland had just introduced that pattern, which was meant to put an end to the convoluted error handling in older parts of the codebase. It seemed to work well. Then one day, he encountered a different use case: a service method that didn't return any data in the good case. For the sake of symmetry, he decided it would return an empty JSON object, and got to work implementing that.
You're doing something wrong, his inner voice cautioned.
Roland had just copied some code from the good case of another service method: setting the MIME type and charset of the response, getting the OutputWriter, writing the data, closing the stream. Five lines total.
Still, he supposed his inner voice was right. Five lines of code for an empty reply was a bit excessive, but that was how he'd implemented the good case elsewhere.
Yes it is, the voice said. But for this? There's got to be a better way.
Roland reviewed the base class, checking whether there was any code he could reuse. Unfortunately not. The five lines were built into the error handling logic, and could not be invoked directly.
Time for some refactoring, the voice said.
Roland cringed hard at the thought. He'd spent so much time in the base class already. He was thoroughly fed up with refactoring.
You've got all the access you need, and you've got the source code in the editor already! Go on now...
Just as he was about to give in, Roland noticed something interesting: when he triggered the error handling without adding user messages, it sent an empty JSON object.
What the hell?
And he could specify the HTTP status code! Roland set it to 200.
// slight abuse of the fallback error handling: send back status OK status.fail(HttpServletResponse.SC_OK);
You've got to be kidding.
It returned an empty JSON object with status OK. That was exactly what Roland needed.
Whoever sees that code will think it's completely screwed up and 'fix' it for the worse. This is unmaintainable!
"That's why I put that comment in there," Roland muttered under his breath.
Oh come on, you're not serious. Just check out the base class and put in a little helper method-
"No, damn it!" Roland snapped, waking up all cubicle-nappers in the vicinity. "I'm coding business logic now! No refactoring! This is the only service method that sends an empty reply! I'm not going to implement a helper in a base class for that! Look, it's either this, or the five-line block of code from the other good cases!"
No, please! Nooo!
And that was how Roland introduced a little WTFery into his otherwise fine code. Of course, it didn't stop there. Over time, more service methods were added- some of them with empty replies. No problem- Roland just followed the pattern of the first one. And the one-liner spawned many offspring.
Everything worked fine, but it was a dirty stain on his programming psyche. Over a year later, when Roland had to change something in the class where it all started, he used the opportunity to clean up those ridiculous one-liners.
There were still one or two spawns that had escaped to other classes, but he'd get to them eventually. And when he did, the inscription on their gravestones would read:
sendJsonReply(status, "{}");[Advertisement] BuildMaster is more than just an automation tool: it brings together the people, process, and practices that allow teams to deliver software rapidly, reliably, and responsibly. And it's incredibly easy to get started; download now and use the built-in tutorials and wizards to get your builds and/or deploys automated!