Say the following layers
controllers try { } catch ()
business (services) try { } catch {}
database (repository) try { } catch {}
suppose when a exception occurs in database layer caught in catch block we throw it. same goes at service layer.
now we are re-throwing twice here
database
try {
error occurred
} catch(e) {
throw new Error("db error", e);
}
service layer
try {
A call db method that either returns results or dbException
OR
B throw some error if business rule is not met
} catch(e) {
// here how can differentiate 'e' is a business exception or dbException. Of coz we create CustomError classes. But 'e' can only say either BusinessException or dbException. Logically a dbException (A) in an innerException of businessException from call stack point of view.
throw new Error(e)
}
controller layer
try {
A call service method that either returns results or businessException
} catch(e) {
next(e);
// here the global error handler should be able to decide what to return. the problem here is that a BusinessLayer should not decide what HttpStatusCode to return. Its the controller to Decide that. The reason is if I want to use the BusinessLayer services in another project as a package, I should be able to because it is tightly coupled with context of Http or its codes.
}
The classic example is I am searching for user with specific ID.
Now query return NULL
.
The business layer can return 401 user not found, there controller such have return the response as is.
However it is HttpContextBound. If I ship the same Business Service in some other project which dont have Http layer at all, it becomes a problem.
Rather if Business service return says "USER_NOT_FOUND"
, its controllers to decide what status code to return. Again the problem is
controller if-else
or swtich
statements grows depending on the Business Rule exceptions or Db returned data
This is something I could not able to resolve nor find a proper efficient ErrorHandling solution without multiple rethrows.As I heard from some core devs, stack trace and recursive exceptions are quite expensive operations. A DbException I like to keep it internal and tracing but BusinessException is for clients / users
Better exception handling from N-Tier apps