Here is a simple Kotlin question for which I don't...
# announcements
j
Here is a simple Kotlin question for which I don't have a simple answer Where should I put my extension functions?
w
I typically group them by receiver type receiver,
LiveDataExtensions.kt
, StringExtensions.kt` etc. It’s not bad, not great either, as some of those files only have one extension. I suppose I’d group by functionality but I don’t think I had a case when I though that’d be preferable. Interested to hear what others do though, too
g
Maybe this is not the best practice, but if it was me, I would put in a package like
com.company.project.extensions.Extensions.kt
. And if I have too much extensions I would replicate the package of the function inside of my project with something like:
com.company.project.extensions.java.util.ArrayList.kt
m
Utils.kt
😄
j
Is there any reason that we should put the extension fonction in a different file than a normal function? I don't see it. So maybe in
Lists.kt
instead of
ListExtensions.kt
?
c
where my extension functions go is entirely dependent upon the scope of their usage. For extensions that have a pretty small “scope” (used only for a handful of classes), I usually put them in an
extensions.kt
file in the package closest to their common usage. No special grouping by receiver or anything here, and intentionally placed to indicate limited usage. For globally-applicable extensions, custom DSLs over existing APIs, things like that, I will put them under an
extensions
package just under the root package. And within there I will group extensions by feature, trying to keep related extensions close together even if they have differing receivers.
👌 1
👍 5
To your later point, i prefer my extensions files to include
extension
somewhere in the filename, just to emphasize what’s in there. My extensions tend to just be wrappers around existing APIs, rather than defining entirely new APIs/features themselves, so I prefer to not name them as if they are a feature.
If I am defining entirely new APIs, I will create a base file somewhere else with the core features (e.g.
com.root.package.features.List.kt
), and then provide extensions to that API in a separate extensions file (`com.root.package.extensions.ListExtensions.kt`_. Helps me to keep straight the internal implementations vs the usage of its API, to make sure each isn’t doing too much work (SRP)
p
I regularly create an Ext.kt file in the package where the Receiver/s class is/are at.
l
I personally create modules specifically for them which I call
extensions
or
extensions-appcompat
,
extensions-location
when they bundle non trivial libraries. Then, I name the subpackages after the packages of the types they are extending, and name the files after the name of the type they are targeting, or after what's inside the file. Sometimes, I put extensions directly in the module that needs it (not in the extensions module), but still follow the same set of guidelines for the package and file name.
👍 1
g
It depends on case as was mentioned above: - If extension used only in single class, than it will be private and member of the class. - If used in a single file by multiple classes/top level functions, than top-level and private - If it used by multiple files of module, than just a separate file (sometimes just with some module-level utils, sometimes a separate file for one or more extensions). Usually with Ext/Util prefix. Also do not use generic name as
Ext.kt
, it make it harder to navigate across the project - Do not group by receiver type, only if it’s super global extensions that provide some generic features for this type (like stdlib File/Collection extensions) - If extension is generic and belongs to some interface/class (so I don’t want to pollute API of this interface/class with it), keep in a file with this type - I do not create modules with name “extensions” and less and less use this for file, because sometimes I have also some utilities functions (not extensions) in file/module, so name become misleading. So use
Utils
for files or utils modules
👍 1
j
Thank you everybody, great answers