kotlin singleton exception is bad or good? - kotlin

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.

Related

How to inform in Kotlin that a function passed by parameter can throw an exception?

I need to inform in my class code that the function passed by parameter (convertorCall) can throw an exception.
suspend operator fun <T> invoke(
convertorCall: () -> T
): T?
For example, if this function were as a method of a class I could do this:
#Throws(JsonSyntaxException::class)
suspend fun <T> convertorCall(): T
However, as said before, I need this to be informed in the function passed by parameter of the invoke function.
I tried this:
suspend operator fun <T> invoke(
#Throws(JsonSyntaxException::class) convertorCall: () -> T
): T?
But a syntax error is generated:
This annotation is not applicable to target 'value parameter'
Kotlin doesn't have checked exceptions, i.e. ones where a function explicitly states what it could throw, and any callers are required to wrap the call in a try/catch to deal with that possibility. Or not catch it, state that they themselves might produce that exception, and pass the responsibility to handle it up the chain.
That link explains the rationale, and links to some sources talking about the issue, but it's basically just how things are done (or not done) in Kotlin. There's a #Throws annotation for interoperability with other languages where checked exceptions is how things are done, but it's not used in Kotlin itself.
If you want to inform the caller that an exception could be thrown, you're supposed to put it in the documentation comment for the function. There's a #throws tag (or an #exception one if you like) for that purpose, but like it says:
Documents an exception which can be thrown by a method. Since Kotlin does not have checked exceptions, there is also no expectation that all possible exceptions are documented, but you can still use this tag when it provides useful information for users of the class.
So it's purely informational really, and the user can choose to handle or not handle those potential exceptions - it's not required. And if you're writing your own functions, you might want to consider whether they should throw an exception to the caller at all during normal, anticipated behaviour, or if they should return some kind of error value (like null) or an error type (e.g. a sealed class that has some kind of failure subclass as well as success types).
// You could return this type instead of throwing an exception
sealed class Result<T> {
class Conversion<T>(data: T) : Result<T>()
class Error<T>(message: String) : Result<T>()
}
Basically, if you know a specific thing can go wrong during normal operation, is it really exceptional? Or just another kind of result to inform the caller about so it can take action if it needs to?

Will it throw an exception if it is null?

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.

NullReferenceException on bool, int, or other stack variable

First of all: the title of this post does not match the actual question I have.
But I am also supplying the answer to the original problem (NullRefExcp on bool), so other users will find it's solution here by the chosen title.
I have a class, similar to the following:
ref class CTest
{
bool m_bInit;
void func()
{
if (!m_bInit)
return;
...
}
...
}
Today I had the problem that func crashed with a NullReferenceException at some point although it had been executed successfully many times before.
The exception occured in the line if (!m_bInit)!
I know, you all are saying now, that this is impossible. But it actually was this line. The reason was following:
I have two different variables, both named oTest, but at different places. One of them was initialized: oTest = gcnew CTest. Calling func on this oTest worked well. The first call of func on the other oTest failed with the exception from above. The curious thing is, that the crash seems to happen at the query on m_bInit, also the stacktrace of the exception tells so. But this was just the first place where a member of the not initialized object (it was still nullptr) was called.
Therefore, the advice for other users with the same problem: Check the stack backwards to find a function call on an object that is nullptr/null.
My question now is:
Why does the execution not fail on the first call of a function of oTest which is nullptr?
Why is the function entered and executed until the first access to a member?
Actually, in my case 3 functions were entered and a couple of variables were created on the stack and on the heap...
This code:
void func()
{
if (!m_bInit)
return;
...
}
could actually be written as:
void func()
{
if (!this->m_bInit)
return;
...
}
Hopefully now you can see where the problem comes from.
A member function call is just a regular function call that includes the this parameter implicitly (it's passed along with the other parameters).
The C++/CLI compiler won't perform a nullptr check when calling non-virtual functions - it emits a call MSIL opcode.
This is not actually the case in C#, since the C# compiler will emit the callvirt MSIL opcode even for non-virtual functions. This opcode forces the JIT to perform a null check on the target instance. The only ways you could get this error in C# is by calling the function via reflection or by generating your own IL that uses the call opcode.

Ignoring Exceptions in Object Oriented Programming

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.

How to return often occurring error in object oriented environment?

assume you have a function that polls some kind of queue and blocks for a certain amount of time. If this time has passed without something showing up on the queue, some indication of the timeout should be delivered to the caller, otherwise the something that showed up should be returned.
Now you could write something like:
class Queue
{
Thing GetThing();
}
and throw an exception in case of a timeout. Or you
write
class Queue
{
int GetThing(Thing& t);
}
and return an error code for success and timeout.
However, drawback of solution 1 is that the on a not so busy queue timeout is not an exceptional case, but rather common. And solution 2 uses return values for errors and ugly syntax, since you can end up with a Thing that contains nothing.
Is there another (smart) solution for that problem? What is the preferred solution in an object oriented environment?
I would use exceptions only when the error is serious enough to stop the execution of the application, or of any big-enough application's component. But I wouldn't use exceptions for common cases, after which we continue the normal execution or execute the same function again. This would be just using exceptions for flow control, which is wrong.
So, I suggest you to either use the second solution that you proposed, or to do the following:
class Queue
{
bool GetThing(Thing& t); // true on success, false on failure
string GetLastError();
};
Of course you can stick with an int for an error code, instead of a string for the full error message. Or even better, just define class Error and have GetLastError() return it.
Why not just return null from GetThing in your first solution, changing it to return a Thing *? It seems to fit the bill, at least from the information you've given so far.
In the first, and second case, you can't do anything but throw an exception. When you return a Thing, or a Thing&, you don't have the option of not returning a Thing.
If you want to fail without using an exception then you need:
class Queue
{
// Either something like this. GetThing retuns NULL on an error,
// GetError returns a specific error code
Thing* GetThing();
int GetError();
// This kind of pattern is common. Return a result code
// and set ppOut to a valid thing or NULL.
int GetThing(Thing** ppOut);
};