[Biojava-dev] Errors versus Exceptions

Mark Schreiber markjschreiber at gmail.com
Tue May 18 09:28:24 UTC 2010


Yikes! OK, in that case you will need to declare IOExceptions in lots
of places. In this day and age I would not advise making your lazy
loading dependent on a file system. You will need to allow for
distributed FS's, databases, AmazonS3, distributed memory caches.
Could turn into a bit of a headache

- Mark

On Tue, May 18, 2010 at 5:22 PM, PATERSON Trevor
<trevor.paterson at roslin.ed.ac.uk> wrote:
> Yes... But...
>
> If our implementation relies on a lazy load underneath every Sequence method implementation..
>
> Then every method can throw an IO type Exception
>
> In essence you can instantiate a valid Sequence object with a LazyLoading Reader before you get the valid SequenceData,
> unlike the case where you can check that you can make a valid Sequence object from the Reader.
>
>
>> -----Original Message-----
>> From: Mark Schreiber [mailto:markjschreiber at gmail.com]
>> Sent: 18 May 2010 10:11
>> To: Andy Yates
>> Cc: PATERSON Trevor; biojava-dev at lists.open-bio.org
>> Subject: Re: [Biojava-dev] Errors versus Exceptions
>>
>> Your ability to recover really depends on the context and how
>> much effort you want to make. If you are in a long running
>> app on a server you should try very hard to recover or at
>> least fail gracefully without crashing. For small programs,
>> who cares? In interactive contexts you can request feedback
>> from the user. For example, if your FASTA file is not FASTA
>> you could ask for another file.
>>
>> Clarifying a little more, Unchecked exceptions are for things
>> that could easily be avoided if the API allows for it by
>> doing simple checks (testing for null, validating input etc).
>> Checked exceptions should be for things that are difficult to
>> check or can be unpredictable; IOException is a good example.
>> An IOException can happen because of something completely out
>> of your control. It needs to be checked because defensive
>> programming is near impossible; you could check that a file
>> exists but a sporadic network failure between calls might
>> make it unreachable.  Finally, Errors are for the
>> unrecoverable. Things that will probably even bring down a
>> long running app or server app (or at least require some
>> reconfiguration or redeployment).
>>
>> I think a well designed API can make most exceptions
>> unchecked (and avoidable with good programming), small
>> numbers of Checked exceptions for things that can't be
>> avoided with defensive programming and a very small number of
>> things that can cause errors.
>>
>> - Mark
>>
>> On Tue, May 18, 2010 at 4:52 PM, Andy Yates <ayates at ebi.ac.uk> wrote:
>> >
>> > You've made that previous decision a lot harder now Mark (I
>> knew it was over too quickly).
>> >
>> > On reflection I'm not sure how well you can recover from
>> something like an unknown compound. When you hit that
>> exception what are you going to do with it? Something like
>> IOExceptions for a file not being open you can do something
>> about that (say it's NFS you could always retry after an
>> allotted amount of time has passed). But an unknown compound
>> ... not sure how you can deal with that apart from callbacks
>> in the parsers. If you think of this in terms of FASTA input
>> into an aligner program and you have an unknown compound
>> there all you're going to do is to pass a message back to the
>> user saying you didn't understand the input sequence with the
>> error message from the Exception something like "Compound '?'
>> is not supported". You could always recover attempting to
>> move through different CompoundSets seeing if one works but
>> are you going to do that?
>> >
>> > I guess the thing to do is to start with checked exceptions
>> in potentially recoverable situations and if they prove to be
>> too clumsy then as BioJava did previously we will switch to
>> the RuntimeException as a base class. We should also
>> endeavour to pass on exceptions and avoid excessive exception
>> wrapping.
>> >
>> > I do think there is a situation where we can relax these
>> rules; I would like to see the relaxation of them when a
>> developer is building say a DNASequence but only using a
>> String. The same should happen for helper classes.
>> >
>> > That's my 2p :)
>> >
>> > Andy
>> >
>> >
>> > On 18 May 2010, at 04:53, Mark Schreiber wrote:
>> >
>> > > To give some historical perspective. This started happening in
>> > > BioJava 1.5. We switched BioException to extend RuntimeException
>> > > (which is not checked). This came from some thinking at the time
>> > > that Java's exception checking was a little bit broken (as
>> > > exemplified by BioJava).  Checked exceptions are good as
>> long as you
>> > > don't swallow them in the API or just use them to spew a stack
>> > > trace. Spitting a stack trace is pointless as the JVM
>> will do a much
>> > > better job of this when it dumps you out. Swallowing them
>> in the API
>> > > is stupid because it is the developer who needs to do
>> something with
>> > > it. Unless it is truly an Error which is the only time an Error
>> > > should be used (unrecoverable problems).
>> > >
>> > > RuntimeExceptions should be used for any type of
>> exception that can
>> > > be avoided by defensive programming. NullPointerExceptions and
>> > > IndexOutOfBounds exceptions are classic examples. There
>> are hundreds
>> > > of places in Java where you could get one of these but you can
>> > > easily avoid them by checking if a collection contains an item,
>> > > doing simple if( x == null) checks, using array.length
>> etc. For this
>> > > reason these and some other Java exceptions extend
>> RuntimeException
>> > > and are not checked. Can you imagine what Java would look like if
>> > > you actually had to put every array access in a try,
>> catch statement?
>> > >
>> > > Therefore, as much as possible I think BioJava3 should have
>> > > exceptions that extend RuntimeException and provide a defensive
>> > > mechanism to avoid having them happen. For example in
>> creating a DNA
>> > > sequence from text you could provide a validator which
>> will check if
>> > > there are any "incorrect" characters. Good code examples
>> on the wiki
>> > > should show the use of defensive programming and not just
>> surround
>> > > everything with a try catch.  Importantly
>> RuntimeExceptions should
>> > > be declared so people are aware they may occur. This is
>> not required
>> > > by the compiler but it is good practice for documentation
>> purposes.
>> > > The Exception class itself should probably contain some Javadoc
>> > > which explains how it can be avoided in the first place. Checked
>> > > exceptions are good for cases where you can recover
>> (although this
>> > > is often more challenging than people think) but it is
>> always easier
>> > > and faster to check yourself, throwing the exception and
>> generating
>> > > the stacktrace etc takes quite a lot of effort from the JVM.
>> > >
>> > > Finally, I don't think you should be throwing Errors to often.
>> > > Although Errors are unchecked and give you the same effect as
>> > > RuntimeExceptions they imply something really bad has gone wrong.
>> > > These should be reserved for things like configuration
>> files being
>> > > corrupt or things that would prevent BioJava from being
>> used, like
>> > > not finding a required JAR file or plugin. You can't
>> recover from these.
>> > > If your API has lots of places where Errors can occur it might
>> > > indicate poor design.
>> > >
>> > > - Mark
>> > >
>> > > On Mon, May 17, 2010 at 10:30 PM, Andy Yates
>> <ayates at ebi.ac.uk> wrote:
>> > >>
>> > >> There's something that irks me with checked exceptions &
>> I found code worked better once I went to a fail-fast method
>> of coding but for an API I can see the usefulness of them.
>> > >>
>> > >> Wow I think this could be the fastest any group has ever
>> dealt with
>> > >> the Checked/Unchecked exception argument :)
>> > >>
>> > >> Andy
>> > >>
>> > >> On 17 May 2010, at 14:58, PATERSON Trevor wrote:
>> > >>
>> > >>>
>> > >>>
>> > >>>> Is the problem in the code the fact that errors are
>> used or that
>> > >>>> they are not declared on the method signatures?
>> > >>>
>> > >>> Declaring them would help - but
>> > >>> Even if you declare Errors in the signature, there is
>> nothing to force you to catch them.
>> > >>> So nothing to alert you to the chance that they may be
>> thrown when you are writing code.
>> > >>>
>> > >>> public class Demo {
>> > >>>
>> > >>>       public  static void main(String[] args) throws Exception{
>> > >>>
>> > >>>       Demo.demo();
>> > >>>               System.out.println("never reached");
>> > >>>
>> > >>>       }
>> > >>>
>> > >>>       public static void demo() throws Error {
>> > >>>               throw new Error("kills the runtime");
>> > >>>       }
>> > >>> }
>> > >>>
>> > >>> Compiles OK with or without declaring the throwable -
>> but throws a runtime error.
>> > >>>
>> > >>> :. IMHO throwing errors is not very useful to developer
>> > >>> - they can use them - IF they know the code well enough to know
>> > >>> they might be thrown
>> > >>>
>> > >>> If Exceptions were used
>> > >>> 1. they would HAVE to be dealt with - if a developer
>> just swallows
>> > >>> something bad, than that's their responsibility for
>> shitty code ;)
>> > >>> 2. like Errors they would be extendable, so real case
>> dataloaders
>> > >>> could use their own exception types and decide how to
>> deal with or
>> > >>> ignore them
>> > >>>
>> > >>> I guess in my background of coding for data access over
>> the wire
>> > >>> with jdbc and webservices
>> > >>> - you need to be aware of the real probability of
>> connection and
>> > >>> request failures
>> > >>> - so explicitly using Exceptions forces the developer to code
>> > >>> defensively
>> > >>>
>> > >>>
>> > >>>
>> > >>>
>> > >>>>
>> > >>>> On a more design note I do not like checked exceptions for two
>> > >>>> reasons. The first is they seem to make more junior developers
>> > >>>> catch Exception and swallow it. The second is whenever
>> I've been
>> > >>>> Java coding in the past whenever a checked exception
>> gets thrown
>> > >>>> (say IOException because of incorrect file
>> permissions) I cannot
>> > >>>> deal with it which in the past has meant I either
>> forward on the
>> > >>>> problem or re-throw in an unchecked exception.
>> > >>>>
>> > >>>> That said as Scooter mentioned the exception system was rushed
>> > >>>> out in the hackathon and did not have much work put into it.
>> > >>>>
>> > >>>> Andy
>> > >>>>
>> > >>>> On 17 May 2010, at 13:15, PATERSON Trevor wrote:
>> > >>>>
>> > >>>>> resending cos of bad headers
>> > >>>>>
>> > >>>>> ________________________________
>> > >>>>>
>> > >>>>> From: PATERSON Trevor
>> > >>>>> Sent: 17 May 2010 13:02
>> > >>>>> To: biojava-dev at lists.open-bio.org
>> > >>>>> Subject: Errors versus Exceptions
>> > >>>>>
>> > >>>>>
>> > >>>>> Could I ask a quick question about why BJ3 seems to use
>> > >>>> Errors rather
>> > >>>>> than Exceptions
>> > >>>>> - maybe this is already documented somewhere on the wiki
>> > >>>> for BJ3 or 1 - and you can point me there.
>> > >>>>>
>> > >>>>> Obviously for us dataloading from remote databases we need
>> > >>>> to have a method to catch connection,sql, datamapping
>> errors etc.
>> > >>>>> We ususally throw DataAccessExceptions when this happens,
>> > >>>> which wrap any java.net, Ibatis and SQL exceptions.
>> > >>>>>
>> > >>>>> It is difficult for us to plug in our lazyload over your
>> > >>>> signatures in
>> > >>>>> the BJ3 sequence readers, as these don't throw exceptions,
>> > >>>> because you
>> > >>>>> seem to use Errors throughout - which dont need to be
>> > >>>> declared. Infact I cant actually see examples of you
>> catching and
>> > >>>> responding to thrown errors.
>> > >>>>>
>> > >>>>> for example the setContents routine of the Sequence Readers
>> > >>>> throws a
>> > >>>>> CompoundNotFoundError if there is no mapping for a base -
>> > >>>> but I can't see what is done with this.
>> > >>>>>
>> > >>>>> According to the Java Lang Spec, errors are used for
>> > >>>> "serious problems
>> > >>>>> that a reasonable application should not try to catch" -
>> > >>>> but I would
>> > >>>>> have thought finding an unrecognized base in a sequence was
>> > >>>> just the
>> > >>>>> sort of thing that should be thrown and caught and acted
>> > >>>> on. As error
>> > >>>>> throwables are not reported in the signature - developers
>> > >>>> don't have
>> > >>>>> any clue ( or requirement) that they should be catching and
>> > >>>>> dealing with errors - which seems a bit dangerous to me... If
>> > >>>> Exceptions were
>> > >>>>> thrownrather than Errors that would force the developer to
>> > >>>>> handle runtime errors
>> > >>>>>
>> > >>>>> Cheers Trevor
>> > >>>>>
>> > >>>>> --
>> > >>>>> The University of Edinburgh is a charitable body,
>> registered in
>> > >>>>> Scotland, with registration number SC005336.
>> > >>>>>
>> > >>>>>
>> > >>>>> _______________________________________________
>> > >>>>> biojava-dev mailing list
>> > >>>>> biojava-dev at lists.open-bio.org
>> > >>>>> http://lists.open-bio.org/mailman/listinfo/biojava-dev
>> > >>>>
>> > >>>> --
>> > >>>> Andrew Yates                   Ensembl Genomes
>> Engineer EMBL-EBI
>> > >>>> Tel: +44-(0)1223-492538 Wellcome Trust Genome Campus   Fax:
>> > >>>> +44-(0)1223-494468 Cambridge CB10 1SD, UK
>> > >>>> http://www.ensemblgenomes.org/
>> > >>>>
>> > >>>>
>> > >>>>
>> > >>>>
>> > >>>>
>> > >>> --
>> > >>> The University of Edinburgh is a charitable body, registered in
>> > >>> Scotland, with registration number SC005336.
>> > >>>
>> > >>>
>> > >>> _______________________________________________
>> > >>> biojava-dev mailing list
>> > >>> biojava-dev at lists.open-bio.org
>> > >>> http://lists.open-bio.org/mailman/listinfo/biojava-dev
>> > >>
>> > >> --
>> > >> Andrew Yates                   Ensembl Genomes Engineer
>> EMBL-EBI
>> > >> Tel: +44-(0)1223-492538 Wellcome Trust Genome Campus   Fax:
>> > >> +44-(0)1223-494468 Cambridge CB10 1SD, UK
>> > >> http://www.ensemblgenomes.org/
>> > >>
>> > >>
>> > >>
>> > >>
>> > >>
>> > >> _______________________________________________
>> > >> biojava-dev mailing list
>> > >> biojava-dev at lists.open-bio.org
>> > >> http://lists.open-bio.org/mailman/listinfo/biojava-dev
>> >
>> > --
>> > Andrew Yates                   Ensembl Genomes Engineer
>> EMBL-EBI
>> > Tel: +44-(0)1223-492538 Wellcome Trust Genome Campus   Fax:
>> > +44-(0)1223-494468 Cambridge CB10 1SD, UK
>> > http://www.ensemblgenomes.org/
>> >
>> >
>> >
>> >
>>
>
> --
> The University of Edinburgh is a charitable body, registered in
> Scotland, with registration number SC005336.
>
>




More information about the biojava-dev mailing list