Whenever I have a function which has gotten large enough to warrant decomposing into smaller functions, I always go for creating the smaller functions as nested functions of the larger functions scope like so:
class Foo {
fun bar() : Int {
fun a() : Int {
// Do a load of stuff
return 1
}
fun b() : Int {
// Do a load of stuff
return 1
}
return a() + b()
}
}
I do this as it provides encapsulation of these functions which as of yet only have a single callsite; that of the enclosing scope.
However I am frequently asked at work to refactor these functions out to private functions of the enclosing class like so:
class Foo {
fun bar() : Int {
return a() + b()
}
private fun a() : Int {
// Do a load of stuff
return 1
}
private fun b() : Int {
// Do a load of stuff
return 1
}
}
My argument against this is that these functions only have 1 callsite, and by hoisting them to class level private functions I am muddying the class with methods that are only called in one place.
An additional minor argument can also be made that if I make them private functions of the class, someone can come in later and start inserting methods between those private functions and the function that calls them, such that there could be 100's of lines of code between the callsite and the functions themselves, causing mental gymnastics to be required to understand the calling function (as you now need to scroll the calling function off the screen to see the private functions).
I always comply and move them to private functions of the class after my argument doesn't pursuade the reviewer(s).
Is my argument valid or are there legitimate reasons (performance, code readability) that make my argument invalid?
Kotlin allows you to nest functions, one within another. We can declare and use a function within another function. When you declare a function within another function, the nested functions, visibility will stay exclusively within the parent function and cannot be accessed from outside.
Creating the infix function is just like creating the inline function. The only difference in syntax is that we use the infix keyword instead of inline . Now, let's see how to invoke infix functions. With the help of infix functions, we can make code more readable and concise.
Any function in a program file can include a nested function. The primary difference between nested functions and other types of functions is that they can access and modify variables that are defined in their parent functions.
A nested function can access other local functions, variables, constants, types, classes, etc. that are in the same scope, or in any enclosing scope, without explicit parameter passing, which greatly simplifies passing data into and out of the nested function. This is typically allowed for both reading and writing.
I find very confusing to transform nested functions into private functions within the class that contains the function, since the only purpose is just to improve the readability of the main function. The private clause only protects against inadvertent use outside the class, but it hinders the readability of the class's source code.
In terms of efficiency, there are no problems, quite the opposite, but it's irrelevevant. In compiler time the search for valid functions within the class is more streamlined, since the nested functions are not even part of the data dictionary.
In terms of efficiency, there is a small overhead when allowing the nested function to see part of the context of the parent function, which is in an earlier section of the code. Since use is only as a means of achieving better readability, I see no problem with that.
As a private function, the compiler can access the function anywhere in the class, which I think is an encapsulation flaw, since that is not the purpose of a local and nested function.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With