I want to fail fast if a specific function is returning null. I have no case where default value would make processing meaningful.
This is the snippet:
val entityAttributes = entity.optJSONObject("Attributes") ?: run {
LOG.error("Could not find 'Attribute' entry in Entity object")
return
}
So if entity.optJSONObject("Attributes") returns null (which it does desipite the opt*) I want to escape from the function scope.
Is the way I did it the proper one? I am fairly new to Kotlin and want to get used to the proper ways of doing these things as early as possible.
You can return from the function early like you do above. If your function returns something besides Unit, then you'd have to return some default value.
Throwing an exception allows you to exit a function without returning anything, but the exception will crash the program if you don't catch it somewhere. Sometimes this is exactly what you want to happen if the error is something that should never happen, because then you'll catch it during testing and be able to fix it before releasing your application.
Use the global error(cause: Any) function and it will immediately throw an IllegalStateException.
Related
We have an API service call that returns a bunch of validation messages. In each message there is a string that contains an error code.
Our implementation converts the validation string into an enum value and then we process the enumeration as there are some error code we just don't care about.
The question becomes, how to handle the loop of messages in a Kotlin way:
response.validationErrors?.forEach {
val mediaFailure = decodeValidationMessage(it.message)
if (mediaFailure != MediaFailure.Unknown) {
return when (mediaFailure) {
MediaFailure.Encrypted -> DomainResponse(ErrorReasonCode.ERR_DOCUMENT_ENCRYPTED)
MediaFailure.NotSupported -> Response.validationFailed()
MediaFailure.InternalError -> Response.serviceFailed()
else -> throw NotImplementedError()
}
}
}
Here we loop through all the messages, then once the message error is not "Unknown" it returns the necessary response to the caller.
However, IntelliJ wants the else path, even though the if prevents that from happening.
Is there a proper Kotlin way of implementing this kind of loop?
From what I understood, you want to return a response for the first mediaFailure which is not MediaFailure.Unknown and you don't want that throw NotImplementedError() part in your function.
One way to fix this is to remove the if condition and continue the forEach loop when MediaFailure.Unknown is found.
response.validationErrors?.forEach {
val mediaFailure = decodeValidationMessage(it.message)
return when (mediaFailure) {
MediaFailure.Encrypted -> DomainResponse(ErrorReasonCode.ERR_DOCUMENT_ENCRYPTED)
MediaFailure.NotSupported -> Response.validationFailed()
MediaFailure.InternalError -> Response.serviceFailed()
MediaFailure.Unknown -> return#forEach // continue the loop
}
}
I think this is one of the many cases when it pays to step back from the code a bit and try to look at the big picture. To ask “What's the ultimate goal here? What am I trying to achieve with this code?”
(In traditional, lower-level languages, almost anything you want to do with a list or array requires a loop, so you get into the habit of reaching for a for or while without thinking. But there are often alternative approaches in Kotlin that can be more concise, clearer, and harder to get wrong. They tend to be more about what you're trying to achieve, rather than how.)
In this case, it looks you want to find the first item which decodes to give a known type (i.e. not MediaFailure.Unknown), and return a value derived from that.
So here's an attempt to code that:
val message = response.validationErrors?.asSequence()
?.map{ decodeValidationMessage(it.message) }
?.firstOrNull{ it != MediaFailure.Unknown }
return when (message) {
MediaFailure.Encrypted -> DomainResponse(ErrorReasonCode.ERR_DOCUMENT_ENCRYPTED)
MediaFailure.NotSupported -> Response.validationFailed()
MediaFailure.InternalError, null -> Response.serviceFailed()
else -> throw NotImplementedError()
}
This is still fairly similar to your code, and it's about as efficient. (Thanks to the asSequence(), it doesn't decode any more messages than it needs to.) But the firstOrNull() makes clear what you're looking for; and it's obvious that you go on to process only that one message — a fact which is rather lost in the original version.
(If there are no valid messages, message will be null and so this will return serviceFailed(), as per comments.)
There are of course many ways to skin a cat, and I can think of several variations. (It's often a worthwhile exercise to come up with some — if nothing else, it gives you more confidence in the version you end up with!) Try to pick whichever seems clearest, simplest, and best matches the big picture of what you're doing; that tends to work out best in the long run.
Is it possible to define a function in Kotlin where you can either return something or return nothing? I thought maybe to use Any as the return type, but that still requires the function to return something, although perhaps there is a way to return a Unit when the return type is Any?
I also found "Nothing":
Nothing has no instances. You can use Nothing to represent "a value that never exists": for example, if a function has the return type of Nothing, it means that it never returns (always throws an exception).
Unfortunately that will throw an exception. That's too bad. I wonder why they throw an exception?
You can wrap the result in a sealed class
sealed class Result<out T> {
data class Success<out T>(val value: T): Result<T>()
object Failure: Result<Nothing>()
}
Then for calling it you can
fun <Type>calculateResult(...): Result<Type> {
//calculate and return some implementation
}
And then
val result = calculateResult(inputs)
when (result) {
is Success -> {
val value = success.value
}
is Failure -> {
//Do something like show an error the user you know your value is Nothing
}
}
You can just use a nullable return type.
Otherwise, to address whether you can return Unit, you can. Unit is just a Kotlin object so you can get the instance by name:
return Unit
However I wouldn't recommend it, there are plenty of better options.
In regards to Nothing, it is a special type that is used to represent a function never returning. So if I wanted to write a function that throws an exception, I could do so with the Nothing return type. Then the inference engine knows that nothing past my function call will get executed.
Well if you think about it, a function can't return something or nothing, because what's the result of calling it? Do you have a value, or nothing at all? If you assign the result to a variable, but there is no result, that variable has no value, so what is it? The function has to either be defined as always returning something or always returning nothing, so you always know if there's a return value and what its possible types are. Otherwise we're getting into philosophical territory!
In fact in Kotlin, functions always return something - if you don't specify a type, like a void function in Java, it will default to returning Unit. This is a special value that represents a function not returning a result, but it is still a result type that gets returned. It's not nothing, it's a a thing. Every function has to return a thing.
So if you want to define the thing you return as either "a value that represents a thing" or "a value that represents nothing", you need a type that is capable of expressing both those ideas. You have three basic approaches I think:
use a specific value to represent "no value", e.g. -1 for an Int, "NO_VALUE" for a String, that kind of thing
create a type that defines a "no value" version of itself, like the Result type in one of the answers, the Optional type in Java, etc
just use null because nullable versions of every type are built into Kotlin's type system, and the standard library is geared towards handling them. Check out these features built around working with nulls
Use the nullable types IMO - return a String? or whatever and if the result is non-null, do something with the value. If it is null, ignore it. Kotlin makes that pretty easy! If you get to the point where you need to roll a special type, you'll probably know why you need it over your good friend null
I'm new to Kotlin and there's a common pattern that I'm not sure how to deal with most correctly. Take this code, for example, which doesn't compile:
git_repo?.add().addFilepattern()
add() is a call in the JGit library which is purely Java, so its return type is AddCommand!.
I have two options:
git_repo?.add()!!.addFilepattern("test.txt")
and
git_repo?.add()?.addFilepattern("test.txt")
Both work fine and given that
I don't know the intricacies of the library implementation,
the documentation of the JGit library doesn't specify whether add() can return null, and
within this context I'd typically expect add() to not return a null
Which version is more idiomatically correct to write in Kotlin? It seems that this would be a fairly common issue to deal with since basically every non-Kotlin library would introduce this issue.
I would use the ?. safe operator and then put your own exception at the end after an ?: Elvis operator. This way you get a message that is meaningful. Using just !! isn't a very helpful message to someone down the road who has no idea what the intricacies were either.
val cmd = gitRepo.add()?.addFilepattern("test.txt") ?: throw IllegalStateException("assert: gitRepo.add() returned an unexpected null")
cmd.doSomething() // never is null guaranteed
If the value is every null you will have a custom error.
assert: gitRepo.add() returned an unexpected null
And after this line, you will not have to null check because the result of the expression is guaranteed never to be null.
If you inspect the code of the other library and ensure it would never ever be null no matter what, then a !! is appropriate. But if not sure, do one better with the custom message.
Note I dropped the first ?. from your example because I'm assuming git_repo itself is not nullable. Plus I renamed it not to have an underscore which isn't normal Kotlin naming convention.
If you are sure that git_repo will always return a value!! is fine in that case.
It is ugly but !! will always be there when you use Java libraries, and you can't avoid it.
The only reason i would use git_repo?.add()?.addFilepattern("test.txt"), would be if you are returning a value, and you want the value to be nullable so that your calling method can handle the nullable.
fun nullableMethod(): string? {
return git_repo?.add()?.addFilepattern("test.txt")
}
fun callingMethod() {
if(this.nullableMethod() != null) {
}
//Else
}
If you are guaranteed it is never going to null, use !!
I'm just trying to make a simple function that will return all the data from my SQLITE database as an array. But it looks like when my function is returning the array, the SQL statement is actually still executing... so it's empty... Does anyone have a suggestion? Or am I just going about this whole thing wrong.
I know I could just have the event listener functions outside this function, and they could then set the data. But i'm trying to make a AS3 Class that holds all my SQL functions, and It would be nice to have everything for this particular function just in one function, so it can return an array to me.
public function getFavsGamesArray():Array
{
getFavsArraySql.addEventListener(SQLEvent.RESULT, res);
getFavsArraySql.addEventListener(SQLErrorEvent.ERROR, error);
getFavsArraySql.text = "SELECT * FROM favGames";
getFavsArraySql.execute();
var favsArr:Array = new Array();
function res(e:SQLEvent):void
{
trace("sql good!");
favsArr=getFavsArraySql.getResult().data;
}
function error(e:SQLEvent):void
{
trace("sql error!");
}
trace(favsArr);
return favsArr;
}
Assuming I understood your question, Instead of expecting getFavsGamesArray() to actually return the results from an asynchronous event (which it likely never will), consider passing a function (as an argument) to call within your res() function that would then process the data.
In your SQL helper class, we'll call it SQLHelper.as:
private var processResultsFun:Function;
public function getFavsGamesArray(callBackFun:Function):void
{
processResultsFun = callBackFun;
...
} //Do not return array, instead leave it void
function res(e:SQLEvent):void
{
trace("sql good!");
if(processResultsFun != null)
{
processResultsFun(getFavsArraySql.getResult().data);
}
}
In the class(es) that call your SQL helper class:
function processRows(results:Array):void {
//Make sure this function has an Array argument
//By the time this is called you should have some results
}
...
SQLHelper.getFavsGamesArray(processRows);
You can optionally pass an error handling function as well.
Your problem is that your task is asynchronous.
favsArris a temporary variable, and you return its value directly when getFavsGamesArray completes. At that time, the value will always be null, because the listener methods are called only after the SQL statement is complete - which will be at some time in the future.
You need some way to delay everything you are going to do with the return value, until it actually exists.
The best way to do it is to dispatch your own custom event, and add the value as a field to the event object, or to add a listener method outside of your SQL class directly to the SQLStatement - and have it do stuff with event.target.getResult().data. That way you can always be sure the value exists, when processing occurs, and you keep your SQL behavior decoupled from everything on the outside.
I would also strongly encourage you not to declare your event listeners inside functions like this: You can't clean up these listeners after the SQL statements completes!
True: Declaring a function inside a function makes it temporary. That is, it exists only for the scope of your function, and it is garbage collected when it's no longer needed - just like temporary variables. But "it is no longer needed" does not apply if you use it as an event listener! The only reason this works at all is that you don't use weak references - if you did, the functions would be garbage collected before they are even called. Since you don't, the listeners will execute. But then you can't remove them without a reference! They continue to exist, as will the SQL statement, even if you set its references to null - and you've successfully created a memory leak. Not a bad one, probably, but still...
If you really want to encapsulate your SQL behavior, that is a good thing. Just consider moving each SQL statement to a dedicated class, instead of creating one giant SQLHelper, and having your listener methods declared as member functions - it is much easier to prevent memory leaks and side effects, if you keep references to everything, and you can use these in a destroy method to clean up properly.
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);
};