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?
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With