Yesterday, at work we had a bug in application we’re developing. Nothing critical but rather inconvenient. Our application has a very common functionality of file download. Some users can upload files to the system and some other users can download those files. Pretty straightforward functionality, right? It’s an ASP.NET application so it should be very easy to implement this. Here's the code (not the real code but the relevant part of it):
protected void ViewFile(int fileId) { byte[] fileData = DAL.GetFile(fileId); Response.ContentType = "application/octet-stream"; Response.AddHeader("Content-Disposition", "attachment; filename=test.txt"); Response.OutputStream.Write(fileData, 0, fileData.Length); Response.End(); }
So what could possibly go wrong here? Not much? Except…, files can be EMPTY too! An empty file is a file that is 0 bytes in size. So if you try to write an empty file with the code above an exception would be throw at Response.OutputStream.Write() line. How do we write an empty file to HttpResponse then? Very simple: you DONT write anything. Just skip Response.OutputStream.Write line and call the Response.End(). Anyway, what am I trying to prove here with this simple example? My point is that we need to be more thoughtful when writing code. We must carefully think about code we write. What could go wrong? How is API we’re using behaving? What exceptions can be thrown? What assumptions are being made? One approach I find useful with dealing this kind of issues is Defensive programming. Here’s quote from wiki about Defensive programming:
A difference between defensive programming and normal practices is that few assumptions are made by the programmer, who attempts to handle all possible error states. In short, the programmer never assumes a particular function call or library will work as advertised, and so handles it in the code.
If the code had been written in Defensive programming mind-set this bug would have never been made. I must also note that Defensive programming is not only choice for solving these kind of issues. Another approach is Design by contract. In the end it really does not matter which approach you choose, the goal is to create more robust and quality software.
No comments:
Post a Comment