Detailer
interface has no sense outside of interface/object
errors.Printer
context. I don't see any reason, to make it dedicated from Printer type. The 'fmt' is just module to output formatted texts. Adding additional responsibility to 'fmt' module looks like not good idea. SRP - forever!
I don't see cases for using
error.IsAny(...)
that you suggested. The chained errors will belong different levels of abstraction and they should be checked on their levels. I suppose It'd be useful to implement ability to use errors object with type switch expression.
1: I'm saying it should be used instead of errors.Printer and errors.Formatter.
errors.Formatter is bad because this has more chance for programmer error. If the programmer forgets to print Error(), or return the next error, the purpose of Formatter has an extremely negative impact on anything trying to print it. It leaves for too much human error.
This doesn't violate SRP any more than errors.Formatter does. Either way, fmt, golang.org/x/text/message, etc. will each need to implement errors.Printer, where fmt.Print doesn't have the same function as p.Print. If we didn't want to violate SRP, we should be forced to implement fmt.Formatter rather than a special errors.Formatter.
Using Detailer instead of Formatter also allows for much more parsable errors. For instance, if I wanted JSON for my error, I can now very easily parse my error to:
To do this with Formatter, you would need to create a custom errors.Printer and assume what is error vs what is details, because it is not clear as to what's what.
2: Yeah, honestly the more I think about it, the more I think that it should just be a function that the developer creates for their own needs.
All looks reasonable. I have only couple remarks:
Detailerinterface has no sense outside of interface/objecterrors.Printercontext. I don't see any reason, to make it dedicated from Printer type. The 'fmt' is just module to output formatted texts. Adding additional responsibility to 'fmt' module looks like not good idea. SRP - forever!error.IsAny(...)that you suggested. The chained errors will belong different levels of abstraction and they should be checked on their levels. I suppose It'd be useful to implement ability to use errors object with type switch expression.1: I'm saying it should be used instead of
errors.Printeranderrors.Formatter.errors.Formatteris bad because this has more chance for programmer error. If the programmer forgets to printError(), or return the next error, the purpose ofFormatterhas an extremely negative impact on anything trying to print it. It leaves for too much human error.This doesn't violate SRP any more than
errors.Formatterdoes. Either way,fmt,golang.org/x/text/message, etc. will each need to implementerrors.Printer, wherefmt.Printdoesn't have the same function asp.Print. If we didn't want to violate SRP, we should be forced to implementfmt.Formatterrather than a specialerrors.Formatter.Using
Detailerinstead ofFormatteralso allows for much more parsable errors. For instance, if I wanted JSON for my error, I can now very easily parse my error to:To do this with
Formatter, you would need to create a customerrors.Printerand assume what iserrorvs what isdetails, because it is not clear as to what's what.2: Yeah, honestly the more I think about it, the more I think that it should just be a function that the developer creates for their own needs.
I seem that name of interface
Formattermatches better to context offmtmodule, than nameDetailer. The nameDetaileris better forerrorsmodule.