Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Better to return None or throw an exception when fetching URL?

I have a Scala helper method that currently tries to fetch a URL and return an Option[String] with the HTML of that webpage.

If there are any exceptions (malformed url, read timeouts, etc...) or if there are any problems it returns a None. The question is, would it be better to just throw the exception so the calling code can log the exception or is it preferable to return the None in this case?

like image 568
James Avatar asked Jul 31 '11 17:07

James


2 Answers

Creating exceptions is expensive because the stack trace has to be filled. Throwing and catching exceptions is also more expensive than a normal return. Considering that, you might ask yourself the following questions:

  • Do you want to force handling of an error by the caller? If so, don't throw an exception, as Scala has no checked-exception mechanism that forces the caller to catch them.

  • In case of an error, do you want to include details on why it failed? If not, you can just return Option[A], where A is your return type, and then you'd either have Some(validContent) or None, with no additional explanation. If yes, you can return something like Either[E, A] or a Scalaz Validation[E, A]. All of this options force the caller to somehow unwrap the result while being free to process the error E as he wants. Now what should E be?

  • Do you want to provide a stack trace in case of failure? If so, you could return Either[Exception, A] or Validation[Exception, A]. If you really go with the exception, you'll want to use Try[A], whose two possible cases are Failure(exc: Throwable) and Success(value: A). Note that you will of course incur the costs of creating the throwable. If not, you can maybe just return Either[String, A] (and be extra careful to remember whether Right means success or failure here — Left is usually used for errors, and Right for the “right” value — Validation is maybe clearer). If you want to optionally return a stack trace, you could use Lift's Box[A], which could be Full(validContents), Empty with no additional explanation (very similar to Option[A] up to here), or indicate a Failure which can store an error string and/or a throwable (and more).

  • Do you maybe want to provide multiple indications as to why it failed? Then return Either[Seq[String], A]. If you do this frequently, you may probably want to use Scalaz and a Validation[NonEmptyList[String], A] instead, which provides some other nice goodies. Look it up for more info about it or check out these usage examples.

like image 149
Jean-Philippe Pellet Avatar answered Sep 18 '22 16:09

Jean-Philippe Pellet


I think that in this case, if is important to log the exceptions then by all means throw the exceptions (and possibly just return String instead of the option). Otherwise you might as well just return the None. One warning- there may be exceptions for other reasons that you don't foresee, in which case it may be dangerous to make a catch-all bit of code.

One thing that you could do is something like Lift's Box system. A Box is essentially an Option, but with a couple features added in: A Full is like a Some, an Empty is like a None, but Lift goes a step further and has a Failure, which is like an Empty but with a reason/message.

like image 38
Dylan Avatar answered Sep 18 '22 16:09

Dylan