[Biojava-dev] Errors versus Exceptions

Mark Schreiber markjschreiber at gmail.com
Tue May 18 09:23:47 UTC 2010


The script example is a good one. If you truly want to do something
quick and dirty you could use BioJava with Groovy and ignore
exceptions completely.  This also eludes to a problem with making
BioJava easy to use and safe.

I have come to the conclusion that you can't really make a Java API
easy for beginners. You can make it safe using all kinds of best
practices from Bloch's effective Java (private setters, no public
constructers etc) but that makes it quite a bit harder for people who
are newer to Java (and are used to bean like patterns). Alternatively
you can use bean like patterns (useful in JEE settings) at the great
danger that people will corrupt objects using public setters and cause
all kinds of concurrent problems with threads. An experience developer
should be able to handle both. Someone new will struggle with both.

Languages like Groovy might be best for the casual or new user. Very
quick to get up and running and somewhat safe (scripting languages are
never really safe). It wouldn't be too hard to make some convenience
Groovy objects; you could make a GSequence for example to make use of
Groovy's overloaded operators.

Anyhow, making BioJava easier to use was one argument for making
exceptions inherit from RuntimeException. Ultimately I don't think we
made it easier to use for beginners although it did make code tidier
and hopefully forced people to think about defensive code.

- Mark

On Tue, May 18, 2010 at 5:06 PM, PATERSON Trevor
<trevor.paterson at roslin.ed.ac.uk> wrote:
>
>
>> 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?
>
> I think it depends on what level your application is working at -
> if your application is just a script doing some data munging maybe
> that is a fatal exception that you want to cause the script to die gracefully...
> But if you are running a large graphical display program and you ask for the
> sequence of have a particular component  - you need to be catching the exception
> and handling the failed request
>
> That's my 2.5p ;)
>
> Trevor
>
>
>
>
>
>
>> -----Original Message-----
>> From: Andy Yates [mailto:andyyatz at gmail.com] On Behalf Of Andy Yates
>> Sent: 18 May 2010 09:53
>> To: Mark Schreiber
>> Cc: PATERSON Trevor; biojava-dev at lists.open-bio.org
>> Subject: Re: [Biojava-dev] Errors versus Exceptions
>>
>> 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