Do you produce useful exception messages?
Here is a method for adding a new Employee to a database:
public void AddEmployee(AddEmployeeCommand command){ var employee = factory.CreateEmployee(command); repository.Add(employee);}
Here is the same method again, but this time we have vastly improved it, by adding some useful error messages:
public void AddEmployee(AddEmployeeCommand command){ try { var employee = factory.CreateEmployee(command); repository.Add(employee); } catch (Exception e) { var message = String.Format("Error adding Employee '{0}'", command.EmployeeName); throw new Exception(message, e); }}
Why is this such a vast improvement? Good error messages won’t help deliver features faster or make your tests green. But they will make your life a hell of a lot easier when things start to go wrong.
One recent example where I used this was in a system where we had to constructing a big hierarchical object graph of all the training statuses of employees in a geographical area. When we got an error, it looked like this:
Error generating Training report for 'Canterbury' district.--> Error generating report for 'Christchurch' team. --> Error generating report for Employee 'Richard Dingwall' (#3463) --> Error getting Skill 'First Aid' (#12) --> SQL error in 'SELECT * FROM ...'
Error messages like this make it very easy to pinpoint problems, than if we had just a raw invalid identifier ADO.NET exception. Its like wrapping an onion — each layer adds a bit more context that explains what is going on.
Now, you don’t need to add try/catch blocks to every method in your call stack, just important ones like entry points for controllers and services, which mark the boundary of key areas in your application.
Exception messages should tell us two things:
- What was the action that failed?
- Which objects were involved? Names, IDs (ideally both), filenames, etc
When adding exception messages, first target areas that deal with external interfaces, because they are the places most likely to cause headaches through bugs or misconfiguration: databases, files, config, third-party systems etc.
Providing good exception messages is essential for making your application easy to maintain — easy for developers to quickly debug, and easy for system administrators to resolve configuration issues.
Remember, there is nothing more infuriating than getting a NullReferenceException from a third-party library.