groovy-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Mr Andersson <mr.andersson....@gmail.com>
Subject Re: Is it possible to enable CompileStatic for an entire project
Date Sun, 26 Jun 2016 20:20:02 GMT


On 06/26/2016 11:18 AM, Jochen Theodorou wrote:
> On 26.06.2016 09:11, Mr Andersson wrote:
>>
>>
>> On 06/24/2016 10:55 PM, Jochen Theodorou wrote:
>>> On 24.06.2016 18:12, Mr Andersson wrote:
>>> [...]
>>>>> static Groovy is on par most of the time, dynamic Groovy depends, but
>>>>> I think it is more in the range of being 2.5 times java (100ms 
>>>>> runtime
>>>>> becomes 250ms). I think that is close enough.... and there is still
>>>>> some potential
>>>>
>>>> But a Java fork would be almost 1:1, if all it generated was Java like
>>>> code.
>>>
>>> Java like code means to do what Java does. Basically you want a
>>> language that includes Java and does things different only in parts,
>>> which are not in Java... That means loosing ==, that means loosing our
>>> array access logic, that means loosing double dispatch of course..
>>> doing builders will become difficult... unless you want to do them
>>> like Kotlin. Runtime meta programming basically impossible
>>>
>>>> I think the performance issues is the invokeDynamic calls that
>>>> groovy does internally, and they might not necessarily be needed.
>>>
>>> there not that many of those, really.
>>>
>>> [...]
>>>> However, any editor could in principle, and in theory tell you on any
>>>> call, what exceptions can be thrown and what kind of exceptions you
>>>> could choose to handle. Ofcourse that would result in many exceptions
>>>> often but the need to declare them on each method is largely 
>>>> syntatical
>>>> and ugly.
>>>
>>> think of a public method and an unknown subclass overriding that
>>> method. How can your editor know, that your library method can only
>>> throw the exceptions you use in your code and no other? It cannot,
>>> unless you make the method final, or say you don´t do libraries ;)
>>
>> Yes, I also mentioned that case. But since that abstract method either
>> has an throws exception declaration on it for specifically stating what
>> kind of exception can be thrown, to notify the editor. One should still
>> however expect other types of exceptions. The thing is that currently,
>> even if an abstract method does not directly state it throws an
>> exception type, it can still throw a new RuntimeException(new
>> IOException()) so why force the wrapping in the first place?
>
> wrapping is irritating me. The JVM does not really know a difference 
> between a checked and a unchecked exception. Thus on the JVM level you 
> really do not need to wrap anything.... and in Groovy we do not do 
> that, if we can avoid it. In fact I removed lots of wrapped exceptions 
> over the years, that have been only required to transport them through 
> the runtime for the satisfaction of the java compiler.
>
>> Why force an implementor to either handle an exception type when most of
>> the time it doesn't even make sense to do so. If an implementor to a no
>> throw exception abstract method, say has to open a file and read it, and
>> then return a String, what should that implementor really do to handle
>> the IOException? First it happens so rarely that it doesn't make sense
>> to handle it, then even if you do handle it, you can only log it. The
>> abstract method caller still excepts a response, and you can not abort
>> the caller, unless you throw a RuntimeException and hope that he manages
>> it, or return null. Why trycatch(Runtime) when you could just as well
>> trycatch(Throwable) in this case. You would not need a getCause call to
>> figure out if it's wrapped or how many times it has been wrapped.  You
>> could also without wrapping trycatch(IOException) directly.
>
> and then your project is also checked with sonar and it wants to force 
> you to not just ignore the exception as well.. yeah, I know that pain
>
>> But to be honest, the entire notion of exceptions is kind of broken. An
>> IOException is not unique other than by at best it's message, and if one
>> decides to bubble an IOException, at some point you will no longer know
>> what actually was the root reason if in the call hierarchy as multiple
>> places can throw an IOException for various reasons.
>
> but the question is how to make it better. Just making all checked 
> exception unchecked won´t solve this.

Yes, that's the million dollar question :)

>
> I know of 3 ways of error handling...
>
> (a) exceptions, like in Java, Python and many other languages
> (b) error object or status code as return value, like C for example
> (c) using multiple return to transport status code (or error object) 
> as well as normal return value.. like Go
>
> I don´t like option b much, but in all cases you need to adapt the 
> control flow of your code to the error handling in some way or other.

Hmm, what about d) If all objects by default have access to three 
methods, hasException(), setException() and getException() .. including 
*nul**l*** which can be returned as a new Error('...'), the caller would 
by default check if the value is not null, and then he could proceed to 
get the error();

for instance:

public String getText(URL file) {
         // we try to get the content but fail because there is no 
internet connection
        return new Exception( theIOException );      // basically (new 
null).setException( exception );
}

Just an idea. The problem here though is that the editor in my first 
argument would be able to see that an exception/error could occur so we 
would be back at the first problem. Since we are talking about Java, 
real exceptions are a real thing and we can't get away from the existing 
code and API's, so this would just introduce complexity and offer two 
different way of managing exceptions.

I would still like to argue for treating checked and unchecked the same. 
There really isn't any difference in theory. It is just forced upon by 
the API desginers that something can throw a checked exception just 
because they were unable to communicate a different return type any 
different way. The only difference is that the API designer has 
determined that YOU MUST handle it or bubble it. Bubbling it is not 
always easy. Since Runtime exceptions can be thrown by any API, 
including for instance *ConurrentHashMap.compute* the problem with 
knowing what a method can throw has already moved from the throws 
declaration to be added as *pure documentation instead*. The compiler if 
it did not ignore runtime exceptions would despite lack of documentaion 
many times be able to tell you at least some of teh exceptions that can 
be thrown, the remaining would have to be declared or experienced.

https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ConcurrentHashMap.html#compute-K-java.util.function.BiFunction-

With Java 8 and lambdas this problem is just getting bigger and bigger. 
Most the Java API's that accepts lambdas are not allowed to throw 
Exceptions which i a major mistake if you ask me. At least one exception 
should've been allowed by default on all those major lambdas. Instead, 
we are now literally *forced* to wrap them as RuntimeException simple to 
avoid having to handle a getText(file) call. How ugly isn't that? not 
only design but also try catch blocks all over the place too doing 
nothing other than hide the real exception.

The difference between checked and unchecked really isn't that big. 
Checked exception should really only be thrown when there is a critical 
error, where the caller MUST manage it. Checked exceptions are abused 
and thrown instead, probably mostly to get that easy documentation with 
your code, since most of the time no one knows what kind of 
RuntimeExceptions that can be thrown if there is no documentation of them.

And yes, you are right, the compiler does allow for a checked exception 
to be thrown without a warning. I have code for that, but I have yet to 
use it.

For instance this works:

public static <E extends Exception> E bubble(Throwable ex) throws E { 
throw (E)ex; // Silences checked exceptions. Casting won't actually work 
but fools the compiler. }

However, I would still like info in my editor what exceptions the call 
hierarchy as good as it can analyze it.

Most of the time, if an abstract class has 10 implementions which can 
fire, the editor would be able to tell you that 5 of them can occur by 
direct invocation, and then you have 3 other "possible" ones depending 
on the   implementation path that's taken. The code most of the time 
exist for what you need to get done.









>
>  bye Jochen
>
>


Mime
View raw message