Git Product home page Git Product logo

api-guidelines's People

Contributors

alibagherifam avatar asm0dey avatar danicsorbajb avatar elizarov avatar ignatberesnev avatar koshachy avatar louiscad avatar ludeknovy avatar lvmvrquxl avatar petrakovichvictoria avatar qwwdfsad avatar zsmb13 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

api-guidelines's Issues

Incorrect example of narrowing from Collection to RandomAccesss

From https://kotlinlang.org/docs/jvm-api-guidelines-backward-compatibility.html#don-t-make-return-types-narrower

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 to RandomAccess.

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.

Operator overloads as member or extension functions

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...

Extend best-practice list: avoid using static "global mockable state" providers/top-level functions in the favour of injectable ones

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)

The example on avoiding arrays is incorrect because Enum.values() performs a defensive copy.

## Avoid arrays in public signatures
Arrays are always mutable, and Kotlin is built around safe –read-only or immutable– objects. If you have to use arrays
in your API, copy them before passing them anywhere so that you can check that they have not been modified.
As an alternative, use read-only and mutable collections according to your intentions. Generally, it is best to avoid
using arrays and be very cautious if you need to use them.
For example, enum classes in Kotlin have the `values()` function that returns an array of all elements of the enum.
If the array is not copied, a user is able to rewrite elements:
```kotlin
enum class Test { A, B }
fun main() { Test.values()[0] = Test.B }
```
If you cache values inside the enum, the cache will be corrupted after running the code above. If the values are not cached,
it's an additional runtime overhead for each call of the `values()` function.

Extend best-practice list: recommend using typed units instead of integer-based conversions

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.

[Discuss] Best-practice to prefer lists over arrays in any form

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"

[To discuss] Explain the difference between arithmetic- and storage- primitive types

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

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.