kotlin / api-guidelines Goto Github PK
View Code? Open in Web Editor NEWBest practices to consider when writing an API for your library
Home Page: https://kotl.in/api-guide
License: Apache License 2.0
Best practices to consider when writing an API for your library
Home Page: https://kotl.in/api-guide
License: Apache License 2.0
For example, sometimes you realize that you need index access to the elements of your collection and want to change the return type from
Collection
toRandomAccess
.
However, RandomAccess
is a marker interface, not a subtype of Collection
, so this is an incorrect example.
Also, the section name "Don't make return types narrower" leads reader to an implicit assumption that "making return types wider" is somehow a good thing. It clearly needs a clarification that narrowing, unlike widening, is mostly source-compatible, so it is tempting to do, yet should not be done.
Kover?
Dokka
Accordingly to the section Use member and extension functions appropriately, only properties, overrides and accessors should be members. But what about operator overloads?
For example, considering the following NotEmptyString
class, if we would like to overload the plus
operator for concatenating them, should we declare the overload as a member or as an extension function?
class NotEmptyString(private val value: String) {
init {
require(value.isNotEmpty()) { "String shouldn't be empty." }
}
/*
* First case - member function.
* The main advantage is that consumers don't have to import the function for using it.
* We can also access declarations available only in that class.
*/
operator fun plus(other: NotEmptyString): NotEmptyString = NotEmptyString(value + other.value)
override fun toString(): String = value
}
/*
* Second case - extension function.
* This the way suggested by the Kotlin API guidelines to declare a function that is not part of the "very" core API
* (because this is not an override, an accessor or a property of the receiver class).
* But importing this operator function when writing 'NotEmptyString + NotEmptyString' feels less convenient...
*/
operator fun NotEmptyString.plus(other: NotEmptyString): NotEmptyString = NotEmptyString("$this$other")
fun main() {
val hello = NotEmptyString("hello")
val world = NotEmptyString(" world")
println(hello + world) // hello world
}
Overloading operators may be an exception that should be declared as a member function...
It would be nice to recommend avoiding using "global" state in the libraries, that later is almost impossible to test and/or mock.
We tend to favor explicitly spelled-out APIs for the such state: datetime's Clock.System.now()
, Okio's FileSystem.DEFAULT.read*
as opposed to top-level now()
, read(path)
etc. (the most notable existing API that falls into this trap is coroutine's Dispatchers.Default
)
api-guidelines/docs/topics/jvm-api-guidelines-predictability.md
Lines 152 to 170 in 461bd2b
It would be nice to recommend using typed units of measurement whenever possible.
E.g. in our official libraries we gave up on API in the form of foo(timeMillis: Long)
and foo(time: Long, unit: TimeUnit)
-- it's unnecessarily verbose, unclear from the call site (esp. when callers do not follow the naming convention), and, most importantly, is error-prone (off-by-order-of-magnitude errors). AFAIR Google even used to have a JVMLS talk about that, but all I can find is this discussion.
The same applies to any "easily-convertible" units -- SI, durations, bytes (kilo-/mega-) etc.
This recommendation is a natural extension over "avoid varargs".
There are enough arguments for that (mutability, covariance, no compile-time safety).
The question is whether it is applicable enough to be included into API guidelines or should be a part of something like "Effective Kotlin instead"
It would be nice to explain and provide recommendations regarding usages of various types in public API.
The overall recommendations should make a clear distinction between arithmetic types (e.g. Int
, Long
and Double
, ones that folks do arithmetics around) and storage types (e.g. Short
, Byte
, Float
, ones that are rather a memory layout optimization), as well as provide a recommendation what should be used in public's API and why
Also let's deprecate Char
while we are here
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.