I am new to Kotlin and I have the following problem: In my project I am using a small library (JAR, no sources). In it there are few custom exception classes defined which inherit Exception class. Some methods throw these exceptions.
In my code I bump into the problem that I don't know what exception the library code might throw so I can catch it and thus sometimes the exception goes trough the roof.
What it is the usual way to handle such situations in Kotlin?
Normaly such exceptions should be declared in the documentation of the library that you are using (either the JavaDoc, KDoc, or a website). There is no structured way to get all exceptions a function can throw, other than decompiling the code and step through it yourself. (by using the build in decompiler, that jet brains ship in IntelliJ for example)
You could also catch all exceptions, but I would always argue, that this is not a good decision in almost all cases.
I don't exactly know the right approach in kotlin, but you may use the following idea from scala:
Try -
try Success(r) catch {
case NonFatal(e) => Failure(e)
}
If exception is not fatal:
case _: VirtualMachineError | _: ThreadDeath | _: InterruptedException | _: LinkageError | _: ControlThrowable => false
case _ => true
then just return Failure(e) otherwise throw it.
How can you use it? At least you will not end up like this:
try {
...
} catch {
case _ : Throwable => ... // catch all exceptions
}
Yes, you still don't know which exceptions code may throw, but using this approach you can control the general execution flow.
But of course, it will be much better if docs list exceptions which may be thrown.
Related
i'm studying kotlin.
I have a question about using exception.
which is better to use object exception or class exception in kotlin?
object CustomDuplicateId : RuntimeException("Invalid user with Id")
class CustomDuplicateId : RuntimeException("Invalid user with Id")
if im using this exception only one location, than stacktrace is always same.
so i think... it doesn't need to use class. is it right?
or is it bad to use singleton exception?
can anyone let me know what's better code to write exception?
There are multiple reasons why it's incorrect to use object.
the stacktrace is wrong in several ways:
It's created at instantiation time, so you'll see <clinit> as first line in the stacktrace because it's created when initializing the object's class for the first time
Even if you throw it from the same place, it won't necessarily be when called from the same caller, so the bottom (root) of the stacktrace will be incorrect if this exception is thrown multiple times across the life of your application
technically the exception class has mutable parts and it would be dangerous/incorrect to allow user code to tamper with this. A very concrete example of this is that user code could add suppressed exceptions to your exception instance (which would only be valid for one throw and yet persist in your object). This is technically a memory leak.
it's likely you would need different messages with more information about why it was thrown (in that case the duplicate ID is very much needed) - so you need different instances with different data anyway
you might throw it from different places in the future (even now in tests/mocks maybe?), and in that case the stacktrace would be even more wrong
independently of technicalities like the above, class vs object also sends a message to the reader that is a bit unclear - why an object here? This exception is not inherently unique. It just so happens that you throw it in one specific place right now and rely on the stacktrace being the same.
Here is an example for the major issue (#1):
object MyExceptionObject : RuntimeException("boom")
fun main() {
try {
caller1() // line 7
} catch (e: Exception) {
}
caller2() // line 10
}
fun caller1() = doStuff() // line 13
fun caller2() = doStuff() // line 14
fun doStuff() {
throw MyExceptionObject // line 17
}
The caller1() throws the exception but that one is caught. The caller2() throws the exception again and that one is not caught. The stacktrace we get for the uncaught exception incorrectly shows the caller 1 (with lines 7 and 13) but the correct one should be caller 2 (with lines 10 and 14):
Exception in thread "main" com.example.MyExceptionObject: boom
at com.example.MyExceptionObject.<clinit>(ExceptionObjectExample.kt)
at com.example.ExceptionObjectExampleKt.doStuff(ExceptionObjectExample.kt:17)
at com.example.ExceptionObjectExampleKt.caller1(ExceptionObjectExample.kt:13)
at com.example.ExceptionObjectExampleKt.main(ExceptionObjectExample.kt:7)
at com.example.ExceptionObjectExampleKt.main(ExceptionObjectExample.kt)
All in all, just use a class.
I am pretty new Kotlin world and do not understand the following code snippet:
#GET
#Path("/env/{id}")
fun read(#PathParam("id") id: EnvStageId): Uni<Environment> =
createUni(repo.read(id)).map {
it ?: throw WebApplicationException(Response.status(Response.Status.BAD_REQUEST)
.type(TEXT_PLAIN)
.entity("Environment $id does not exist")
.build())
}
The question is, if it is null it will then throw an exception right?
The elvis operator ?: is not null or the continuation.
Yes. If it is null then it will throw an exception.
The thing is, sometimes it is better to crash: if that operation is supposed to always return something from the local db, then if it fails you get an alert that there is something very bad going on, crashalytica for prod are standard this days.
Maybe the design is exceptions throwing exceptions on low level implementations. I do not think so, because that seems to be mixing network with repository, so I will doubt it. But on the other hand it seems to be so, because someone wrote an special exception for that, if it so, then the next architecture layer should catch those exceptions and handle them gracefully.
A basic use case would be calling MyEventListener::class without having imported use MyNamespace\MyEventListener. The result would be a broken piece of code that's relatively hard to debug.
Does PHP 7 provide a directive to crash instead of returning the class name if no class exists? For example:
After calling use Foo\Bar;, Bar::class would return 'Foo\Bar'.
But if no import statement, PHP returns 'Bar', even though the class doesn't exist, not even in the global namespace.
Can I make it crash somehow?
The thing you need to keep in mind is that use Foo\Bar; is not "importing" anything. It is telling the compiler: when I say "Bar" I mean Bar from the namespace Foo.
Bar::class is substituted blindly with the string "Foo\Bar". It isn't checking anything.
Until you attempt to instantiate or interact with a class it will not check to see if it exists. That said, it does not throw an Exception, it throws an Error:
// this doesn't exist!
use Foo/Bar;
try {
$instanceOfBar = new Bar();
}
catch (Error $e) {
// catching an Exception will not work
// Throwable or Error will work
}
You can trap and check for non-existent classes at run time, but until you do it will happily toss around strings referring to classes that don't exist.
This is a blessing in the case of Laravel's IoC container and autoloader that abuses this to alias classes as convenient top-level objects. A curse, if you were expecting PHP to throw a fuss on ::class not existing.
Update:
My suggestion for anyone worried about this problem is to use PHPStan in your testing pipeline. It prevents a lot of mistakes, and unlike php -l it will catch if you were to try and interact with a non-existent class.
As far as I know you're going to get a nice error message when you try to instantiate a class that cannot be found through autoloading or explicitly added.
If you want to check if the class exists, first, try this:
$classOutsideNamespaceExists = class_exists('Bar');
$classInsideNameSpaceExists = class_exists('\\Foo\\Bar'));
Or you could try this syntax available since PHP 5.5:
class_exists(MyClass::class)
Finally, you can always use the tried and true method of a try-catch block.
try {
$instanceOfMyClass = new MyClass();
}
catch (Exception $e) {
// conclude the class does not exist and handle accordingly
}
PhpStorm proposes and generates hints like ArrayShape, Pure, etc.
But automatically it is adding
php use JetBrains\PhpStorm\ArrayShape;
or another.
Is not that dangerous that on some production server I will get error
'Class JetBrains\PhpStorm\ArrayShape not found'?
(c)LazyOne:
Well, just use composer require --dev jetbrains/phpstorm-attributes to add such classes to your project. See github.com/JetBrains/phpstorm-attributes
As long as instance of such a class is not actually gets instantiated (created) you should have no error because use statement is just a declaration.
In some applications, I came across some lines of code which deliberately eats the exceptions. In my application the benefit of doing this is - To ignore the exception and just continue with the loop(The exception handled is for an error thrown inside the loop). The following lines of code looks evil to even an experienced developers. But is sensible to the context(I mean, that is the requirement - to process all the files in the directory).
try{
//some lines of code which might throw exception
}catch(Exception e){
//no code to handle the error thrown
}
What other benefits can ignoring exceptions provide?
If it is a requirement to process all the files, if you get an exception during processing one of them, is not the requirement broken already? Either something failed or the exception is not needed.
If you want to continue the processing handle the exception, then continue. Why not just report the problem with processing a given file,so someone can later process it manually? Probably even stupid cerr << "Hey I had trouble with this file '" << file <<', so I skipped it.\n" would be better than nothing.
Exception is there to signal something. If you are ignoring it either you are doing something nasty, or the exception is not needed.
The only valid reason for ignoring the exception I can think of is when someone throws exceptions at you for no good reason. Then maybe, yeah, ignore.
This is generally the mark of bad code - you always want to handle your exceptions by at a minimum reporting what the exception is. Ignoring exceptions will let your program keep running, but generally exceptions are thrown for a reason and you or the user need to know what that reason is. Doing a catch-all and escaping just means the coder was too lazy to fix whatever problems cropped up.
The exception is if the coder is throwing exceptions merely to pass arguments, which is something I saw on DailyWTF once.
Usually we should not absorb the exception but there can be reason like there is a function which is out of business logic that is just to help some kind of extra functionality, then you do not want your application to break if that function throw the exception in that case you absorb/eat the exception. But I do not recommend the empty catch block, one should log this in ELMAH or other error logging tools for future.
I don't think there any any benefits of ignoring exceptions. It will only cause problems. If you want the code to be executed in the loop, after handling it, it will continue with the loop because exception is handled. You can always process the files in your directory even if you are not doing anything after handling exceptions.
It will be better if you write some log regarding the files for which exception is thrown
If you eat the exception. You may never know what is the actual cause of the problem.
Considerr this example
public class Test {
private int x;
public void someMethod(){
try {
x = 10/0;
} catch (Exception e) {
}
}
public static void main(String[] args) {
Test test = new Test();
test.someMethod();
System.out.println(test.x);
}
}
This will print simply 0 the default value of x as exception occured during division and value was not assigned to x
Here you are supposed to get actual result of the division. Well it will definitely throw an ArithMeticException because we are dividing by zero and we have not written anything in catch block. So if the exception occurs, nothing will be printed and value of x will be 0 always and we can't know whether the division is happend or not. So always handle exceptions properly.
Should I be using this method of throwing errors:
if (isset($this->dbfields[$var])) {
return $this->dbfields[$var];
} else {
throw new FieldNotFoundException($var);
}
or this style:
try {
return $this->dbfields[$var];
} catch (Exception $e) {
throw new FieldNotFoundException($var);
}
...or something else altogether?
quick explanation of the code: $this->dbfields is an array. isset() checks if a variable is set, in this case, whether the array element exists.
The second example is bad. You're taking a lot of overhead to catch an exception when, as you demonstrate, it's just as easy to prevent the exception in the first place. Plus you also assume you know why that exception was thrown - if there was some other exception, like say an out of memory or something, you're reporting it as a "field not found" even if it wasn't.
Keep in mind that try/catch in languages like C++ and Java are very expensive because of all the state they have to save and restore. Python, on the other hand, has very cheap exceptions and they positively encourage you to use a try/except for simple validation. But even so, catching everything and pretending it's one type of exception is still bad.
//First let's do the checks.
if(!isset($this->dbfields[$var]))
throw new FieldNotFoundException($var);
//Now we're in the clear!
return $this->dbfields[$var];
Catching "Exception" is not, most of the time, considered a good practice, out of the two you displayed, I would use option 1.
Catching all exceptions may hide a different exception and mask it as a FileNotFoundException.
I prefer the first one, but if dbfields[$var] throws something reasonable when you access a non-existent element, then I'd prefer just returning it without checking.
I don't particularly like changing the exception type unless I have a good reason -- also if you do, make sure to try to preserve the original exception and stack trace.
Just re-read your explanation.
I guess your method there in #1 is going to catch any exceptions that might be thrown and simply return a bool. I definitely don't like the catching of the generic exception most of the time, so #2 wouldn't be my choice.
"...or something else altogether?"
Neither is very good, so something else would be appropriate.
Fix version 2 to catch the correct exception, not every possible exception. Post that as option 3. I'll upvote something that catches a specific exception instead of Exception.
This is far from language-agnostic.
Some languages won't throw errors for accessing non-existant fields, and the preferred pattern depends a lot on the implementations of the arrays, tables, objects, etc.