Offensive programming

How to make your code more concise and well-behaved at the same time

Have you ever had an application that just behaved plain weird? You know, you click a button and nothing happens. Or the screen all the sudden turns blank. Or the application get into a “strange state” and you have to restart it for things to start working again.

If you’ve experienced this, you have probably been the victim of a particular form of defensive programming which I would like to call “paranoid programming”. A defensive person is guarded and reasoned. A paranoid person is afraid and acts in strange ways. In this article, I will offer an alternative approach: “Offensive” programming.

The cautious reader

What may such paranoid programming look like? Here’s a typical example in Java:

<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #003399;">String</span> badlyImplementedGetData<span style="color: #009900;">(</span><span style="color: #003399;">String</span> urlAsString<span style="color: #009900;">)</span> <span style="color: #009900;">{</span>
	<span style="color: #666666; font-style: italic;">// Convert the string URL into a real URL</span>
	<span style="color: #003399;">URL</span> url <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #339933;">;</span>
	<span style="color: #000000; font-weight: bold;">try</span> <span style="color: #009900;">{</span>
		url <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">URL</span><span style="color: #009900;">(</span>urlAsString<span style="color: #009900;">)</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">}</span> <span style="color: #000000; font-weight: bold;">catch</span> <span style="color: #009900;">(</span><span style="color: #003399;">MalformedURLException</span> e<span style="color: #009900;">)</span> <span style="color: #009900;">{</span>
		logger.<span style="color: #006633;">error</span><span style="color: #009900;">(</span><span style="color: #0000ff;">"Malformed URL"</span>, e<span style="color: #009900;">)</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">}</span>
 
	<span style="color: #666666; font-style: italic;">// Open the connection to the server</span>
	<span style="color: #003399;">HttpURLConnection</span> connection <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #339933;">;</span>
	<span style="color: #000000; font-weight: bold;">try</span> <span style="color: #009900;">{</span>
		connection <span style="color: #339933;">=</span> <span style="color: #009900;">(</span><span style="color: #003399;">HttpURLConnection</span><span style="color: #009900;">)</span> url.<span style="color: #006633;">openConnection</span><span style="color: #009900;">(</span><span style="color: #009900;">)</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">}</span> <span style="color: #000000; font-weight: bold;">catch</span> <span style="color: #009900;">(</span><span style="color: #003399;">IOException</span> e<span style="color: #009900;">)</span> <span style="color: #009900;">{</span>
		logger.<span style="color: #006633;">error</span><span style="color: #009900;">(</span><span style="color: #0000ff;">"Could not connect to "</span> <span style="color: #339933;">+</span> url, e<span style="color: #009900;">)</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">}</span>
 
	<span style="color: #666666; font-style: italic;">// Read the data from the connection</span>
	StringBuilder builder <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> StringBuilder<span style="color: #009900;">(</span><span style="color: #009900;">)</span><span style="color: #339933;">;</span>
	<span style="color: #000000; font-weight: bold;">try</span> <span style="color: #009900;">(</span><span style="color: #003399;">BufferedReader</span> reader <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">BufferedReader</span><span style="color: #009900;">(</span><span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">InputStreamReader</span><span style="color: #009900;">(</span>connection.<span style="color: #006633;">getInputStream</span><span style="color: #009900;">(</span><span style="color: #009900;">)</span><span style="color: #009900;">)</span><span style="color: #009900;">)</span><span style="color: #009900;">)</span> <span style="color: #009900;">{</span>
		<span style="color: #003399;">String</span> line<span style="color: #339933;">;</span>
		<span style="color: #000000; font-weight: bold;">while</span> <span style="color: #009900;">(</span><span style="color: #009900;">(</span>line <span style="color: #339933;">=</span> reader.<span style="color: #006633;">readLine</span><span style="color: #009900;">(</span><span style="color: #009900;">)</span><span style="color: #009900;">)</span> <span style="color: #339933;">!=</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #009900;">)</span> <span style="color: #009900;">{</span>
			builder.<span style="color: #006633;">append</span><span style="color: #009900;">(</span>line<span style="color: #009900;">)</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">}</span>
	<span style="color: #009900;">}</span> <span style="color: #000000; font-weight: bold;">catch</span> <span style="color: #009900;">(</span><span style="color: #003399;">Exception</span> e<span style="color: #009900;">)</span> <span style="color: #009900;">{</span>
		logger.<span style="color: #006633;">error</span><span style="color: #009900;">(</span><span style="color: #0000ff;">"Failed to read data from "</span> <span style="color: #339933;">+</span> url, e<span style="color: #009900;">)</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">}</span>
	<span style="color: #000000; font-weight: bold;">return</span> builder.<span style="color: #006633;">toString</span><span style="color: #009900;">(</span><span style="color: #009900;">)</span><span style="color: #339933;">;</span>
<span style="color: #009900;">}</span>

This code simply reads the contents of a URL as a string. A surprising amount of code to do a very simple task, but such is Java.

What’s wrong with this code? The code seems to handle all the possible errors that may occur, but it does so in a horrible way: It simply ignores them and continues. This practice is implicitly encouraged by Java’s checked exceptions (a profoundly bad invention), but other languages see similar behavior.

What happens if something goes wrong:

  • If the URL that’s passed in is an invalid URL (e.g. “http//..” instead of “http://…”), the following line runs into a NullPointerException: connection = (HttpURLConnection) url.openConnection();. At this point in time, the poor developer who gets the error report has lost all the context of the original error and we don’t even know which URL caused the problem.
  • If the web site in question doesn’t exist, the situation is much, much worse: The method will return an empty string. Why? The result of StringBuilder builder = new StringBuilder(); will still be returned from the method.

Some developers argue that code like this is good, because our application won’t crash. I would argue that there are worse things that could happen than our application crashing. In this case, the error will simply cause wrong behavior without any explanation. The screen may be blank, for example, but the application reports no error.

Let’s look at the code rewritten in an offensive way:

<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #003399;">String</span> getData<span style="color: #009900;">(</span><span style="color: #003399;">String</span> url<span style="color: #009900;">)</span> <span style="color: #000000; font-weight: bold;">throws</span> <span style="color: #003399;">IOException</span> <span style="color: #009900;">{</span>
	<span style="color: #003399;">HttpURLConnection</span> connection <span style="color: #339933;">=</span> <span style="color: #009900;">(</span><span style="color: #003399;">HttpURLConnection</span><span style="color: #009900;">)</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">URL</span><span style="color: #009900;">(</span>url<span style="color: #009900;">)</span>.<span style="color: #006633;">openConnection</span><span style="color: #009900;">(</span><span style="color: #009900;">)</span><span style="color: #339933;">;</span>
 
	<span style="color: #666666; font-style: italic;">// Read the data from the connection</span>
	StringBuilder builder <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> StringBuilder<span style="color: #009900;">(</span><span style="color: #009900;">)</span><span style="color: #339933;">;</span>
	<span style="color: #000000; font-weight: bold;">try</span> <span style="color: #009900;">(</span><span style="color: #003399;">BufferedReader</span> reader <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">BufferedReader</span><span style="color: #009900;">(</span><span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">InputStreamReader</span><span style="color: #009900;">(</span>connection.<span style="color: #006633;">getInputStream</span><span style="color: #009900;">(</span><span style="color: #009900;">)</span><span style="color: #009900;">)</span><span style="color: #009900;">)</span><span style="color: #009900;">)</span> <span style="color: #009900;">{</span>
		<span style="color: #003399;">String</span> line<span style="color: #339933;">;</span>
		<span style="color: #000000; font-weight: bold;">while</span> <span style="color: #009900;">(</span><span style="color: #009900;">(</span>line <span style="color: #339933;">=</span> reader.<span style="color: #006633;">readLine</span><span style="color: #009900;">(</span><span style="color: #009900;">)</span><span style="color: #009900;">)</span> <span style="color: #339933;">!=</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #009900;">)</span> <span style="color: #009900;">{</span>
			builder.<span style="color: #006633;">append</span><span style="color: #009900;">(</span>line<span style="color: #009900;">)</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">}</span>
	<span style="color: #009900;">}</span>
	<span style="color: #000000; font-weight: bold;">return</span> builder.<span style="color: #006633;">toString</span><span style="color: #009900;">(</span><span style="color: #009900;">)</span><span style="color: #339933;">;</span>
<span style="color: #009900;">}</span>
Related:
1 2 3 4 Page 1
Notice to our Readers
We're now using social media to take your comments and feedback. Learn more about this here.