I'm working on an API and am trying to report back to the consumers certain errors (e.g. input errors, errors that occur during the processing of their requests, etc.). My API returns an array of errors (and warnings, and notices).

I'm starting to see a couple of problems:

  1. I'm not completely DRY. A number of the errors, warnings, and notices tend to occur repeatedly in different parts of the code. So, at these different parts of the code, I'm having to set the error's code, title, description repeatedly (the descriptions tend to have more specific details about the particular error, so one could argue that this difference does make it DRY -- but the code and title are the same, so not-DRY).
  2. My classes (parent, child) are getting bloated with all the code to handle errors, warnings, notices.

I'm tempted to create a class that just contains errors, warnings, and notices (probably in the form of a massive array). Perhaps I make it a base class -- and my current base class would just extend that. I could make some sort of method in it to make it easier for the classes that extend it to add errors (there is a protected member for errors, warnings, notices).

What's a good approach? Using PHP.


Returning a "massive array" sounds like a nightmare for your users. You're creating an API. Why are you recovering from errors rather than clearly reporting them? How could you possibly know what errors should be recovered from when you're just an API? Let the API user decide if an error should be recovered from.

If that doesn't simplify things to simple fail-early one-shot exceptions then accept a log you can use to log errors.

It can also help to create unique exception classes that add nothing but unique names. One of the few things I still use inheritance for.

  • When I encounter a situation I cannot recover from, I consider that an "error", quit what I'm doing, and report back to the user. However, not everything I encounter forces me to stop what I'm doing. So, I report those back as "warnings" and "notices" -- just as a courtesy to the user. Should I forget about that approach? – ProgrammerNewbie Jun 19 '17 at 12:32
  • Can you please elaborate on your "unique exception classes?" What might that look like? And why is it one of the few things you still use inheritance for? Do you have a general rule of avoiding inheritance? If so, why? – ProgrammerNewbie Jun 19 '17 at 12:33
  • I favor composition (with delegation) over inheritance because composition lets me remain at a consistent level of abstraction while stacks of inheritance tend to cause the yo-yo problem. If you're certain recovering is the correct thing to do report it in a log. Being certain of that when you're an API is a tricky thing because you don't know what what the calling code expects exactly. – candied_orange Jun 19 '17 at 13:39
  • Thanks for the insight. Do you have a sample of how you handle errors? – ProgrammerNewbie Jun 19 '17 at 15:16
  • Fail fast. Don't bury the lead by making it hard to discover where things first went wrong. Throwing well named custom exceptions can make it easy to realize where the problem came from without having to dig into the trace. Don't make it hard to find the original exception. – candied_orange Jun 19 '17 at 15:56

Before you can plan around how to keep track of problems you have to think about the real requirements. Let me share how we handled this (different language, but same concept) in a batch file processing tool:

  • User needed to know success, warning, or failure for each file
  • User needed chance to correct problems and attempt re-import (i.e. change field mapping etc.)
  • Processing had to continue even if there was a problem on one line or one file

We had a table in memory to track file level processing. There was a column for the file, status (pending, processing, success, failure, warning), and messages. The messages was just a CSV file with one line per warning or failure.

Processing was pretty straightforward.

  • Populate the in-memory table with the list of files to process
  • The processing controller updated the status, and called a parser for the file
  • The parser returned the CSV content for all errors and warnings
  • The processing controller updated the status again and assigned the CSV to the messages column

The UI was able to present the status, and let the user view the content of the error list. It was a desktop app, so some of this status updating was easy to do.

The bottom line is that you'll probably have to track errors at more than one level. The complexity has to match your real requirements.

You can pass the object you are tracking process in to each method/component that needs to reference it, or you can have that same code return the collection of status to the caller. Make it clear what the message belongs to by providing any identifiers you can (like file name, line number etc.). You might have repeated errors, but it is for different records.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.