Why do we use let{} as null checking in Kotlin? - kotlin

Why do we use exactly let{} as null checking in Kotlin?
Aren't other scope functions suitable for this? They do pretty much the same thing.

It's an idiom. When everybody usually does things in basically the same way, it makes code easier to read and follow because your brain has to do less work to comprehend it. You can immediately grasp what's happening when you see an idiomatic pattern without having to reason through all its logic.
The reason let is the natural choice out of the scope functions, I think:
You usually only need to do this kind of null-check so you can do something with the non-null object. If you just wanted to call something on the non-null object, you could have just used ?.doWhatever() instead of ?.run { doWhatever() }. This rules out run and apply for readability reasons. run { doSomething(this) } is considered a little more awkward than let { doSomething(it) }.
Not always, but often, you want to do something with the return value of whatever function you're passing the non-null object to. This rules out also.
And with can't be used with ?. safe invoke since it is a top level function with no receiver.
Those other functions run, apply, and also could be the best choice under some circumstances, but in most cases they have no readability advantage over let and so you may as well use the idiomatic choice.

Related

What is the usage scenario of kotlin overloading the invoke operator?

Why not use top-level functions but overloaded invoke operators?
Is there any advantage to overloading the invoke operator?
class GetFollowableTopicsUseCase #Inject constructor(
private val topicsRepository: TopicsRepository,
private val userDataRepository: UserDataRepository
) {
operator fun invoke(sortBy: TopicSortField = NONE): Flow<List<FollowableTopic>>
...
}
There's an old pair of sayings that floats around programming communities like these.
Closures are a poor man's objects, and objects are a poor man's closures.
The fact of the matter is that, in a sufficiently modern language like Kotlin (or like most languages that we use nowadays), objects and closures are pretty similar. You could replace every class in your Kotlin program with a mess of functions and mutable variables they close over. Likewise, you could replace every function in your program with an object that has an invoke function. But the former would be a constant wrestling match with the type system, and the latter would be absurdly verbose.
So Kotlin lets us do both. Which should you use? The advantage of functions is that they're short and snappy and to-the-point. And, to a functional programmer at least, functions should generally be free of side-effects. Objects, on the other hand, are loud and verbose. That's a bad thing, in that it takes longer to read and comprehend when skimming the code. But it's also a good thing, because it stops you from hiding complexity.
So if your function is simple, use a function. If it's complicated or stateful, use a named object and document it like any public class. As a few examples, here's how I would handle some different situations.
A function to add two numbers together is simple, side-effect-free, and referentially transparent. Use a function.
A function to add a number to a local val is still very simple. It's a closure, but the val is immutable, so the function's behavior is predictable. Using an object would be overkill, so make it a function.
A function that keeps track of how many times it's been called and prints out that number each time has side effects and local state. While it could be written as a fancy closure around a var, it would be better to make this a real object, whose counter variable is a genuine instance variable, so that anyone reading the code can see at a glance what's happening.
In addition to Silvio's general answer, one specific case is for factory methods.
If you define a factory method like this:
class MyClass(…) {
…
companion object {
operator fun invoke(…): MyClass = …
}
}
Then calling the factory method looks exactly like calling a constructor: MyClass(…). This makes factory methods, with all their advantages, easier to use and hence more likely to be adopted.
(Obviously, this only makes sense when the parameter type(s) clearly distinguish the factory method from any public constructors, and also clearly indicate its purpose. In other cases, named factory methods are preferably.)

In which cases you don't want or you shouldn't use coroutines in Kotlin?

I'd read a lot of the many adventages of using coroutines, but I find nothing about why you shouldn't or couldn't use them.
Why not use all methods as suspend methods, by the way?
I'm having some trouble to understand some concepts here, so with my question I pretend to make the opposite case (why not use it), so I can understand better by contrast.
The main reason not to have all functions suspendable is the overhead they introduce, at least on the JVM. Every suspendable function compiles into a Java method that receives another parameter, the continuation object, and its body compiles into pretty complex state machine code that, among other things, always instantiates another continuation object and daisy-chains it to the one received as the parameter.
So, whenever you have nothing to gain from coroutines, you shouldn't use them as the default way to do things.
Please see my answers inline to your questions:
but I find nothing about why you shouldn't or couldn't use them.
Answer:
a. You should not use them for any foreground task.
b. You should not use them for any simple/real quick operations.
c. You should not use them for any kind of initialization.
Why not use all methods as suspend methods, by the way?
Answer:
a) This will be treated as code smell. Bad practice to do so.
b) If you mark all functions as suspend, then whenever you want to call a suspend function you will have to create a Coroutine Scope to run it.
c) Testing of suspend function is difficult. It needs some additional setup of RunBlockingTest from AndroidX.

Should Kotlin's DAO return Optional or null?

Prior to Kotlin/JPA , I used to write my DAO layer like this :
public interface UserDao extends JpaRepository<User,Long> {
Optional<User> findBySsn(String ssn);
}
And in the caller side , if I want to find someone or create user by SSN , I can write this:
val user = userDao.findBySsn(value).orElseGet {
userDao.save(value)
}
It works well and looks fluent.
But since Kotlin introduces null-safety , there is another idiomatic way (dao still in Java ):
public interface UserDao extends JpaRepository<User,Long> {
Optional<User> findBySsn(String ssn);
#Query("select u from User u where u.ssn = :ssn")
#Nullable User findBySsnNullable(#Param("ssn") String ssn)
}
And in the client side :
val user = userDao.findBySsnNullable(value)
.takeIf{ it -> it != null}? : userDao.save(User(value))
Both ways work good. But I wonder which is preferred ? Is it good for Kotlin to dependent on Java8's Optional in API design ? What's the cons for a Kotlin project to depend on (or intercommunicate via) Java8's Optional/Stream API (since Kotlin has its own) ?
Kotlin can compile to JavaScript (I haven't studied that). If the project is depend on Java's Optional/Stream , will it have problem compiling to JS?
---- updated ----
According to Jetbrains
No, common code can only depend on other common libraries. Kotlin has
no support for translating Java bytecode into JS.
I wouldn't use Optional if you don't have to. It only adds unnecessary overhead as working with nullable types is more readable and more idiomatic in Kotlin. There's no advantage of using Optional in Kotlin.
Here's another discussion on that: https://discuss.kotlinlang.org/t/java-api-design-for-kotlin-consumption-optional-or-null/2455
I have to say I disagree with #s1m0nw1
What Kotlin does is to give us a nice way of dealing with a mistake. Kotlin cannot remove that mistake, because it's so inherent in the JVM and would damage the integration with legacy Java and poorly written Java. However, because it has a nice tool to deal with the bad design does not mean that we should embrace the bad design and do it ourselves.
Some reasoning:
Nullable still give the same set of problems the second your Kotlin code is called from Java. Now you just masked the underlying problem, actively damaging your clients. - By itself this is a strong enough reason IMO.
Null is still ambiguous, what does null mean? Error? Value missing? Or? Null has no clear meaning, even if you assign it a meaning, you have to document it everywhere and hope that people reads it. Value.EMPTY, Value.MISSING, throw new Exception() all have (somewhat) clearly defined meanings clearly readable from your code. It's the same problem as with booleans as a shortcut for binary enum values, e.g.:
val testPassed = runTest()
if (testPassed) // ...
this has a clear meaning, only as long a you have the variable name. Passing it on, refactoring etc. can quite fast obfuscate it. What the user meant:
val testResult = runTest()
if (testResult == TestResult.PASSED)
is clear and readable. So per the same argument, let your code communicate your intent. Do not take the shortcut. Again I see the Kotlin dealings with null as extremely nice, for dealing with poor code, I do not see it as an excuse for producing poor code.
Null is logically illogical, essentially it's a pointer that doesn't point. It's basically a nonsense "value" that isn't really a value. It's not really anything.
With nulls you will still have to do weird things for API's that utilize various stream functionality, so by using null you will either have to do hacky things like illustrated in the debate that s1m0nw1 links to, or do explicit conversions anyway, so you'll end up having them both anyway, saving exactly nothing by choosing null, but ending up dealing with both the semantics of the nullable and Optional.
It's a minimum amount work to ensure that you return Optional. I mean come one, we are not talking about a lot of extra code here. Don't be afraid of writing a few extra lines to do things right. Readability, flexibility etc. should come before short code. Just because there's a new smart feature to write things shortly and avoid mistakes does not mean you have to use it all the time. Keep in mind that to a hammer everything looks like a nail :)
The problem with not doing null though is the lack of a proper "Maybe"-type in Java. The more correct solution is the Option/Maybe types utilized by functional languages, however, Java's Optional is only a half measure. It does not fully capture the semantics of a true Maybe/Option type, which is why you shouldn't use Optional for parameters and fields.
For parameters this isn't an issue, since you can easily ensure an overload that doesn't take that parameter to begin with - a task that's even easier in languages like Kotlin.
For fields it seems the current "solutions" are to define a proper Maybe/Option-type, perhaps specific for each of your types, to ensure that type erasure and serializations doesn't hinder you. You could use the NullObject pattern, which seems like a slightly uglier way to do the exact same. Or have the nasty null value, but encapsulate it completely in your class. So far I've been doing the last, but I'm not fond of it :/ but pragmatism has its place ;)

Anti-if purposes: How to check nulls?

I recently heard of the anti-if campaign and the efforts of some OOP gurus to write code without ifs, but using polymorphism instead. I just don't get how that should work, I mean, how it should ALWAYS work.
I already use polymorphism (didn't know about anti-if campaign), so, I was curious about "bad" and "dangerous" ifs and I went to see my code (Java/Swift/Objective-C) to see where I use if most, and it looks like these are the cases:
Check of null values. This is the most common situation where I ever use ifs. If a value could possibly be null, I have to manage it in a correct way. To use it, instead I have to check that it's not null. I don't see how polymorphism could compensate this without ifs.
Check for right values. I'll do an example here: Let's suppose that I have a login/signup application. I want to check that user did actually write a password, or that it's longer than 5 characters. How could it possibly be done without if/switches? Again, it's not about the type but about the value.
(optional) check errors. Optional because it's similar to point 2 about right values. If I get either a value or an error (passed as params) in a block/closure, how can I handle the error object if I just can't check if it's null or isn't?
If you know more about this campaign, please answer in scope of that. I'm asking this to understand their purposes and how effectively it could be done what they say.
So, I know not using ifs at all may not be the smartest idea ever, but just asking if and how it could effectively be done in an OOP program.
You'll never completely get rid of ifs, but you can minimize them.
Regarding null value checks, a method that would otherwise return a null value can return a Null Object instead, an object that doesn't represent a real value but implements some of the same behavior as a real value. Its callers can just call methods on the Null Object instead of checking to see if it's null. There is probably still an if inside the method, but there don't need to be any in the callers.
Regarding correct value checks, the best path is to prevent an object from being instantiated with incorrect attributes. All users of the object can then be confident that they don't have to inspect the object's attributes to use it. Similarly, if an object can have an attribute that is valid or invalid, it can hide that from its users by providing higher-level methods that do the right thing for the current attribute value. Again, there is still a if inside the object, but there don't need to be any in the callers.
Regarding error checks, there are a couple of strategies that are better than returning a possibly null error value that the caller might forget to check. One is raising an exception. Another is to return an object of a type that can hold either a result or an error and provides type-safe, if-free ways to operate on either result when appropriate, like Java's Optional or Haskell's Maybe.
Note also that case statements are just concatenated ifs (in fact I'd have written the code on the campaign's home page with a switch rather than if/else if), and there are also patterns which replace case with polymorphism, such as the Strategy pattern.
This is a great question and is something that's asked at every OO bootcamp I've been a part of. To begin with, we need to understand why code with a lot of ifs is 'bad' or 'dangerous':
they increase the cyclomatic complexity of the code, making it hard to follow/understand.
they make tests more complicated to write. Ensuring that you test each branch flow in the method under test becomes increasingly more difficult with each conditional and makes test setup cumbersome.
they could be a sign that your code has not been broken into small enough methods
they could be a sign that your methods have not been encapsulated well
However, there is one important thing to remember - ifs cannot(and should not) be eliminated from the code completely. But, we can generally abstract them away using techniques like polymorphism, extracting small behaviours, and encapsulating these behaviours into the appropriate classes.
Now that we know some of the reasons why we should avoid ifs, let's tackle your questions:
Checking for null values: The Null object pattern helps you eliminate null checks from your code(polymorphism FTW). Instead of returning null, you return a Special Case NullObject representation of the expected object. This NullObject has the same interfaces as your actual object and you can safely call any of the object's methods without worrying about a null pointer exception being thrown.
Checking for correctness of values: There are a lot of ways to do this. For example, you could create a separate ValidationRule class for each of your validations and then chain calls to them together when you want to validate your object. Notice that the ifs still remain, but they get abstracted away into the individual ValidationRule implementations. Look up the Command pattern and the Chain Of Responsibility pattern for ideas.
It's better to use if to check the null instead of raising an exception. Also in common cases checking for null helps us to prevent operations with non-initialized variables.
Using switch plus SOLID. Other thinks inherited from this.

Why stick to get-set and not car.speed() and car.speed(55) respectively?

Apart from unambiguous clarity, why should we stick to:
car.getSpeed() and car.setSpeed(55)
when this could be used as well :
car.speed() and car.speed(55)
I know that get() and set() are useful to keep any changes to the data member manageable by keeping everything in one place.
Also, obviously, I understand that car.speed() and car.speed(55) are the same function, which makes this wrong, but then in PHP and also in Zend Framework, the same action is used for GET, POST, postbacks.
In VB and C# there are "properties", and are used by many, much to the disgust of purists I've heard, and there are things in Ruby like 5.times and .each, .to_i etc.
And you have operator overloading, multiple inheritance, virtual functions in C++, certain combinations of which could drive anyone nuts.
I mean to say that there are so many paradigms and ways in which things are done that it seems odd that nobody has tried the particular combination that I mentioned.
As for me, my reason is that it is short and cleaner to read the code.
Am I very wrong, slightly wrong, is this just odd and so not used, or what else?
If I still decide to stay correct, I could use car.speed() and car.setSpeed(55).
Is that wrong in any way (just omitting the "get" )?
Thanks for any explanations.
If I called car.speed(), I might think I am telling the car to speed, in other words to increase speed and break the speed limit. It is not clearly a getter.
Some languages allow you to declare const objects, and then restrict you to only calling functions that do not modify the data of the object. So it is necessary to have seperate functions for modification and read operations. While you could use overloads on paramaters to have two functions, I think it would be confusing.
Also, when you say it is clearer to read, I can argue that I have to do a look ahead to understand how to read it:
car.speed()
I read "car speed..." and then I see there is no number so I revise and think "get car speed".
car.getSpeed()
I read "for this car, get speed"
car.setSpeed(55)
I read "for this car, set speed to 55"
It seems you have basically cited other features of the language as being confusing, and then used that as a defense for making getters/setters more confusing? It almost sounds like are admitting that what you have proposed is more confusing. These features are sometimes confusing because of how general purpose they are. Sometimes abstractions can be more confusing, but in the end they often serve the purpose of being more reusable. I think if you wanted to argue in favor of speed() and speed(55), you'd want to show how that can enable new possibilities for the programmer.
On the other hand, C# does have something like what you describe, since properties behave differently as a getter or setter depending on the context in what they are used:
Console.WriteLine(car.Speed); //getter
car.Speed = 55 //setter
But while it is a single property, there are two seperate sections of code for implementing the getting and setting, and it is clear that this is a getter/setter and not a function speed, because they omit the () for properties. So car.speed() is clearly a function, and car.speed is clearly a property getter.
IMHO the C# style of having properties as syntatic sugar for get and set methods is the most expressive.
I prefer active objects which encapsulate operations rather than getters and setters, so you get a semantically richer objects.
For example, although an ADT rather than a business object, even the vector in C++ has paired functions:
size_type capacity() const // how many elements space is reserved for in the vector
void reserve(size_type n) // ensure space is reserved for at least n elements
and
void push_back ( const T& ) // inserts an element at the end
size_type size () const // the number of elements in the vector
If you drive a car, you can set the accelerator, clutch, brakes and gear selection, but you don't set the speed. You can read the speed off the speedometer. It's relatively rare to want both a setter and a getter on an object with behaviour.
FYI, Objective-C uses car.speed() and car.setSpeed(55) (except in a different syntax, [car speed] and [car setSpeed:55].
It's all about convention.
There is no right answer, it's a matter of style, and ultimately it does not matter. Spend your brain cycles elsewhere.
FWIW I prefer the class.noun() for the getter, and class.verb() for the setter. Sometimes the verb is just setNoun(), but other times not. It depends on the noun. For example:
my_vector.size()
returns the size, and
my_vector.resize(some_size)
changes the size.
The groovy approach to properties is quite excellent IMHO, http://groovy.codehaus.org/Groovy+Beans
The final benchmarks of your code should be this:
Does it work correctly?
Is it easy to fix if it breaks?
Is it easy to add new features in the future?
Is it easy for someone else to come in and fix/enhance it?
If those 4 points are covered, I can't imagine why anybody would have a problem with it. Most of the "Best Practices" are generally geared towards achieving those 4 points.
Use whichever style works for you, just be consistent about it, and you should be fine.
This is just a matter of convention. In Smalltalk, it's done the way you suggest and I don't recall ever hearing anybody complain about it. Getting the car's speed is car speed, and setting the car's speed to 55 is car speed:55.
If I were to venture a guess, I would say the reason this style didn't catch on is because of the two lines down which object-oriented programming have come to us: C++ and Objective-C. In C++ (even more so early in its history), methods are very closely related to C functions, and C functions are conventionally named along the lines of setWhatever() and do not have overloading for different numbers of arguments, so that general style of naming was kept. Objective-C was largely preserved by NeXT (which later became Apple), and NeXT tended to favor verbosity in their APIs and especially to distinguish between different kinds of methods — if you're doing anything but just accessing a property, NeXT wanted a verb to make it clear. So that became the convention in Cocoa, which is the de facto standard library for Objective-C these days.
It's convention Java has a convention of getters and setters C# has properties, python has public fields and JavaScript frameworks tend to use field() to get and field(value) to set
Apart from unambiguous clarity, why should we stick to:
car.getSpeed() and car.setSpeed(55)
when this could be used as well : car.speed() and car.speed(55)
Because in all languages I've encountered, car.speed() and car.speed(55) are the same in terms of syntax. Just looking at them like that, both could return a value, which isn't true for the latter if it was meant to be a setter.
What if you intend to call the setter but forget to put in the argument? The code is valid, so the compiler doesn't complain, and it doesn't throw an immediate runtime error; it's a silent bug.
.() means it's a verb.
no () means it's a noun.
car.Speed = 50;
x = car.Speed
car.Speed.set(30)
car.setProperty("Speed",30)
but
car.Speed()
implies command to exceed speed limit.