GithubHelp home page GithubHelp logo

Comments (6)

morikuni avatar morikuni commented on September 1, 2024 1

The only difference is in the behavior of CodeOf function?

Yes, for now, it just makes a difference in CodeOf function.
MessageOf does not check "unexpected" wrapper because even if the error is unexpected, I want to provide a hint to fix the error to the developers.
But in the future, I may change MessageOf to respect "unexpected" errors. I'm still considering which behavior is more appropriate.

How to define unexpected?

With failure, an unexpected or unknown error is one that doesn't have error code.
So your code

	code := failure.StringCode("unknown state")
	return 0, failure.New(code)

is a part of expected errors.

Reduce declare Sentinel errors.

const (
  NotFound failure.StringCode = "NotFound"
)

I guess you want to reduce this kind of declaration regarding the article, right?
The Sentinel error that is described in the article is one that is completely static.
But failure allows you to add more information into errors even if you definefailure.Code as public const variables.
So it is different from the Sentinel error.

I recommend defining all error codes public and use it as a part of your function's/method's interface.

This article may be helpful for you: https://middlemost.com/failure-is-your-domain/

from failure.

morikuni avatar morikuni commented on September 1, 2024

@Min-Feng Hello! Let me explain the idea of "unexpected" functions.
To put it simply, if you have already gotten an error from some function call, and that error should not happen, then you can use MarkUnexpected. If you haven't gotten any errors yet, you can use Unexpected.
BUT basically, you shouldn't use both two functions unless you want to stop error code propagation. The errors that happen in your application should have some error code as much as possible.

For Unexpected example,

type State int

const (
  A State = iota + 1
  B
)

func (s State) Value() (int, error) {
  switch s {
  case A:
    return 10, nil
  case B:
    return 20, nil
  default:
    return 0, failure.Unexpected("unexpected state")
}

For here, you don't have an error in default block, therefore you can use Unexpected. But if the situation can be expected to happen, you should use New with some error code instead of Unexpected.

For MarkUnexpected example,

const (
  NotFound failure.StringCode = "NotFound"
  InvalidArgument failure.StringCode = "InvalidArgument"
  AlreadyExists failure.StringCode = "AlreadyExists"
)

// CallAPI may return NotFound or InvalidArgument error.
func CallAPI() error {
  // do something
} 

// Do may return InvalidArgument (doesn't return  NotFound or other codes).
func Do() (int, error) {
  err := CallAPI()
  if err != nil {
    switch { // you can also switch with failure.CodeOf, but to be simple here.
    case failure.Is(err, NotFound):
      return 1, nil
    case failure.Is(err, InvalidArgument):
      // just return InvalidArgument, but wrap it to add function name Do into err.Error().
      return 0, failure.Wrap(err)
    default: // I don't expect Do returns other errors.
      // since I don't want to propagate other errors like AlreadyExists, wrap the error with MarkUnexpected
      return 0, failure.MarkUnexpected(err)
    }
  }
}

For here, the CallAPI function may return some error code but I don't want to propagate it transparently. Therefore, I used MarkUnexpected to prevent returning unexpected error code from the Do function. If you use Unexpected here, the original error from CallAPI is discarded, therefore MarkUnexpected is more appropriate.

Note: if you wrap an error by MarkUexpected, the underlying error code is not returned from CodeOf function.

from failure.

KScaesar avatar KScaesar commented on September 1, 2024

I don't know that stop error code propagation what you mean.
what is the error you're talking about error by std lib or error by StringCode?

failure.Wrap(err) vs failure.MarkUnexpected(err)
What's the difference between them?
They're both error type.

return 0, failure.MarkUnexpected(err), the statement does stop error propagation?
But I see the statement still returning error.
return error != propagation ?

My English is poor.
Can you understand my description?
Thank you very much for your detailed reply.

from failure.

morikuni avatar morikuni commented on September 1, 2024

I don't know that stop error code propagation what you mean.
what is the error you're talking about error by std lib or error by StringCode?

"Stop error code propagation" means that it performs like it hides error code made by StringCode.

failure.Wrap(err) vs failure.MarkUnexpected(err)

The difference is here.

https://play.golang.org/p/LV1pWrKi5Dl

If you use Wrap function, CodeOf function will return an error code in the error with true.
If you use MarkUnexpected function, CodeOf function will not return an error code in the error, and it will return false.

I recommend following way, if you don't understand when you should use it.

  • Do not use failure.Unexpected and failure.MarkUnexpected
    • These two functions should not be used so often. So you don't have to use it until you will want those functions
  • Use failure.New, failure.Tarnslate when you want to add an error code into the error
    • These three functions are fundamental functions in failure to handle errors by error code
  • Use failure.Wrap when you want to add stack trace into the error
    • If you want to write code with the normal (no-failure) Go way but just want stack trace, failure.Wrap can perform like an alternative to pkg/errors.Wrap.

from failure.

KScaesar avatar KScaesar commented on September 1, 2024

problem 1

If you use Wrap function, CodeOf function will return an error code in the error with true.
If you use MarkUnexpected function, CodeOf function will not return an error code in the error, and it will return false.

The only difference is in the behavior of CodeOf function?
I try to use two functions, MessageOf and CauseOf.
The results are identical.
https://play.golang.org/p/BnsgLgm519s

This question is just to reconfirm.

problem 2

// your code
switch s {
case A:
  return 10, nil
case B:
  return 20, nil
default:
  return 0, failure.Unexpected("unexpected state")
// my code
switch s {
case A:
	return 10, nil
case B:
	return 20, nil
default:
	code := failure.StringCode("unknown state")
	return 0, failure.New(code)
}

I try to follow suggestions from the article: Don’t just check errors, handle them gracefully
Reduce declare Sentinel errors.

Do you have any suggestions for my code?
How to define unexpected?
I knew for a fact that something would go wrong.
But defining unexpected error?

end

Once pkg/errors.Wrap is executed multiple times, it print call stack is Redundant
I like format of your stack trace.
beautiful and clear!!

from failure.

KScaesar avatar KScaesar commented on September 1, 2024

I guess you want to reduce this kind of declaration regarding the article, right?

Yes

Thank you for your reply.
I'll read the articles you recommend.

from failure.

Related Issues (3)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.