Writing robust software is a pain.
There, I said it. It’s not a sentiment most folks working in software development like to admit, but it’s true.
My point is not to extol my virtues as a polyglot programmer. I know many software folks with significantly greater breadth of experience than I have. Rather, my point is that writing robust software is difficult, no matter what language I’ve used. That goes for language features, libraries, frameworks, etc. Nothing replaces the hard work and good judgement required to know where and when to put in the effort to write truly robust software.
What’s the worst that can happen?
Most software developers can write code that is functionally sufficient. It gets the job done, and so long as nothing bad happens, it works just fine.
So what can go wrong? Those pesky users of our software can cause problems, so there’s bad input, invalid configurations, and insufficient privileges, to name a few. There are also all kinds of environmental problems that can make writing robust software difficult, such as attempting to write to a full disk, attempting to access a resource that is currently unavailable, running out of memory, etc. 
When is it worth the effort to write robust software? Let me start with the obvious. Anything sold as an enterprise-grade product must be robust.  Enterprise customers are demanding. They pay a lot of money for the software they use to solve their business problems, and they expect that software to work. If that software encounters a problem, an enterprise customer expects the software to accurately report the problem.
That seems simple enough. Maybe. What is required for software to accurately report a problem it encounters? First the software developer must be aware of the possibility that a problem can occur. Every operation that can fail must be checked.
For example, the return code of a function call must be tested to ensure that the function succeeded before the calling code continues to the next statement. Not checking the return code can lead to a later failure in a seemingly unrelated module, making the real source of the error difficult to find.
As another example, if a called function can throw an exception, then the exception must be caught and handled.
Adding thorough error checking to code is a lot like going to the gym. Most people don’t bother at all. Many do so, but only half-heartedly. But those who truly put in the effort often achieve spectacular results.
In the next installment, I will describe a common scenario where error handling is tedious to write but absolutely necessary in enterprise software. I will then present a solution in Java, although the general concepts in the solution apply in other languages.
 I have encountered plenty of other factors that make writing robust software difficult, including bad designs, buggy third-party components, race conditions, inconsistent coding standards in a large code base, etc.
 Many other categories of software also require robustness. These include device drivers, embedded systems, and large-scale systems.
(image credit: @unsplash @schmidy)