Git Product home page Git Product logo

kotlin-guides's Introduction

kotlin-guides's People

Contributors

austinaryain avatar benwicks avatar caleb-allen avatar chickenbane avatar davethomas11 avatar dector avatar dhartwich1991 avatar fython avatar gps035 avatar hereisderek avatar jakewharton avatar jaynewstrom avatar jmslau avatar joshskeen avatar kernald avatar louiscad avatar mareklangiewicz avatar mattiamaestrini avatar pawegio 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  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

kotlin-guides's Issues

Interop Guide Lint Check

Suggestion if you do not change anything else think about the beginner with Kotlin and Android Studio
The path to Lint Checks in kotlin-guides page reads as follows
File -> Preferences -> Editor -> Inspections
I am sure Preferences does not equal the word Settings also sure Preferences was used at one time
this compounded by the accompanying screen shot is nothing but confusing to beginners lets change it
As a Android novices I have learned to read between the lines a skill no one should need to develop
Screen shot included no I did not edit as a novices my skill level is not proficient enough
kotlin

Add explicit exception for spaces around range operator

The style guide says that spaces are required "On both sides of any binary operator.", and does not give an exception for the .. operator. However, various examples do show that you prefer .. to be used without spaces around it. The exception should be noted explicitly.

Clarify formatting for multi-line, single-argument method calls

The Kotlin language code style documentation makes clear that for multi-line, multi-argument method calls the arguments should appear on their own lines (potentially in groups):

drawSquare(
    x = 10, y = 10,
    width = 100, height = 100,
    fill = true
)

where ( ends the line it is on while the ) appears on its own line. The specific rule is

In long argument lists, put a line break after the opening parenthesis. Indent arguments by 4 spaces. Group multiple closely related arguments on the same line.

Is there any guidance for long method calls that wrap to multiple lines when there is only a single argument?

For example, are both the following correct?

setOnClickListener(object : View.OnClickListener {
    override fun onClick(v: View) {
        //...
     }
})

setOnClickListener(
        object : View.OnClickListener {
            override fun onClick(v: View) {
                //..
            }
         }
)

or is one preferred (ignoring for now that you'd just use a lambda here)? What if there is wrapping involved in the argument value itself? Are each of these valid:

someMethod(callsAVeryVeryLongFunctionWithHorribleName(
        andTonsAndTonsOfParameters,
        andMoreParameters
))

someMethod(
        callsAVeryVeryLongFunctionWithHorribleName(
                 andTonsAndTonsOfParameters,
                 andMoreParameters
        )
)

Keywords order

Properties and functions may often have more keywords which order is not strictly ordered in Kotlin but may be confusing. Few examples:

lateinit on properties:

  • private lateinit var foo: Foo - OK
  • lateinit private var foo: Foo - WRONG, breaks the relation between lateinit and var, the visibility modifier is kind of optinal (when public)

abstract on functions:

  • protected abstract fun foo() - OK
  • abstract protected fun foo() - WRONG

open/final on properties and functions:

  • open protected val foo: Foo - seems better to me
  • protected open val foo: Foo
  • final override fun foo() - seems better to me
  • override final fun foo()

Do you think such rules might be valuable in the Style Guide?

Clarify wrapping rules for expression functions

The guide sets the following guidelines for single-expression functions:

Expression functions should not wrap to two lines. If an expression function grows to require wrapping, use a normal function body, a return declaration, and normal expression wrapping rules instead.

It should be understood that it prohibits the use of this kind of constructs:

fun veryVeryLongFun() = 
        callsAVeryVeryLongFunctionWithHorribleName(andTonsAndTonsOfParameters)

Instead, the following form should be used:

fun veryVeryLongFun() { 
    return callsAVeryVeryLongFunctionWithHorribleName(andTonsAndTonsOfParameters)
}

However, the following expression function, although multiline, doesn't contain wrapping, as it returns a single multiline expression:

fun getFoo(index: Int) = when (index) {
    in 0..10 -> "foo"
    in 11..20 -> "bar"
    else -> "baz"
}

It's easy to misread the style guide and get the impression that expression functions are only valid if they occupy exactly one line. It would be great to have a more clear description of the wrapping rules in this case.

Companion object

Is the recommendation for companion objects? Should they be at the bottom or top of a class?

Allow wildcard imports

https://android.github.io/kotlin-guides/style.html#import-statements

Wildcard imports (of any type) are not allowed.

This rule seems contradictory to currently accepted standards for general Kotlin and Kotlin w/ Android development. To borrow from what @Rosomack and others said in this ktlint issue about wildcard imports:

  1. Kotlin coding conventions never mention rules for imports. Also, it reasons to stand that usage of wildcard imports should be by coder-preference given that the language allows them. Why should the Android Kotlin style guide have rules about imports when Kotlin does not?

  2. According to @BenjaminSchaaf, the source code for Kotlin itself contains over 6000 wildcard imports across 35303 Kotlin source files.

  3. ItelliJ / Android Studio use wildcard imports by default in these cases:

  • When more than 5 names are used from the same file.
  • When importing classes form java.util.* (ex. LinkedList)
  • When importing synthetic properties generated by the Kotlin Android extension. ex)
import kotlinx.android.synthetic.main.activity_main.*

Note that this is specific behavior set up by the plugin, not because of > 5 names being used.


Most Kotlin linters (such as ktlint) are based off this style guide. Because of this rule, programmers are having to go out of their way to change the default behavior of the IDE to stop using wildcard imports altogether. I propose this rule be removed from the guide.

Standardize positions of closing parentheses

The style guide is currently silent about which of these is preferred:

someFunction(
    someOtherFunction(
        someThirdFunction(
            param1,
            param2,
            param3)))
someFunction(
    someOtherFunction(
        someThirdFunction(
            param1,
            param2,
            param3
        )
    )
)

The Google Java style guide mandates the first style and it'd be great if the Kotlin style guide was similarly specific. Doesn't matter to me which of the two styles it settles on, just that it picks one for consistency.

Using expression functions.

The style guide says that expression functions should not wrap to two lines. But the IDE inspection suggests that even multi-line functions with a single expression should be converted to an expression function:

screen shot 2017-11-20 at 14 07 58

Change the rule that expression functions should only be one line.

One line for expression functions?!? I must rebel on this one.

I like seeing code like this:

fun computeCollatzSteps(n: Int) = generateSequence(n) {
  require(it > 0)
  if (it % 2 == 0) it / 2 else it * 3 + 1
}.takeWhile({ it != 1 }).count()

Versus something like this:

fun computeCollatzSteps(n: Int): Int {
  require(n > 0)
  return generateSequence(n) {
    if (it % 2 == 0) it / 2 else it * 3 + 1
  }.takeWhile({ it != 1 }).count()
}

This function is for counting the number of steps in the Collatz Conjecture for a number. Taken from here http://exercism.io/exercises/kotlin/collatz-conjecture/readme

I know the second one is better because it calls require only once. But I added that so I could call out the reason for my argument, which is not for efficiency but for a certain coding style. When efficiency is not a concern but rather the benefits of functional programming are important, I feel that function expressions lead themselves towards this.

I do not claim to be an expert on functional programming by any means. I am a total newbie to these concepts. Concepts that have been around for a long time. But when you lock down a function in Kotlin into a simple expression format, to me it adds constraints on that function that make it work in more of a purely mathematical way. It makes it harder for the coder to write a none pure function. While it is still possible, I feel like it limits your options with the function, and encourages you to keep it more focused on its task.

I like having those limitations, I like having to think in a functional chain. Why? I feel like it makes code less error-prone. Also, forget being "cute", I think code written in this manner can actually be easier to read and maintain. Having one stream of flow to a function forces you to not rely on state manipulating changes. While that is still possible, I would frown on that in an expression function and strive for a purely functional approach. An approach where we have the same output for every input used.

Obviously a matter of opinion, but I think we should open expression functions to being more than one line for those of us that use them to express our code in that manner. My ask is for this restriction in the coding style to be removed, and for functional programming styles to be encouraged.

Perhaps the rule should be if your expression function does not modify the state of its surrounding code container and it always returns the same output for every input then multiple lines should be allowed.

One line is not enough to express some mathematical functions.

Also, nevermind simple cases where we have long class names ;) For example:
Ie.

  @Provides fun provideDatabase(context: Context): AppDB = 
      Room.databaseBuilder(context, AppDB::class.java, dbName).build()

That's 123 characters on one line.

I don't want to have to write that as a function with the return keyword.

Personally, I'd like to see the return keyword taken out back and put on a shelf for only the most necessary of use cases.

In my mind, you either have a void method that is doing a bunch of setup work or you have a function that returns some result. That result returned should be simple enough that an expression function should suffice.


Those that are more informed on these topics than I, please call me out where I am wrong on any concepts that I am thinking/writing here!

This one line rule for expression functions does not sit right with me.


So in conjecture with possible varying opinions on the matter of expression functions, would it be possible to loosen up this restriction?

We could perhaps say, "Multiple lines are allowed for expression functions that are pure functions"

A pure function is a function where the return value is only determined by its input values, without observable side effects.


My two cents, and this is by no means critical. Just sharing my opinion at the moment =)

Wrapping and +/- operators

The current guide says: "When a line is broken at a non-assignment operator the break comes before the symbol". Unfortunately this breaks semantics for +/- operators, which can be used in unary form. For example, this is a string concatenation:

val s = "abc" +
    "def"

This is a simple string initialization, followed by an unused expression that applies unary + to a string literal:

val s = "abc"
    + "def"

The wrapping rules should be changed to either break after all operators (preferably), or to make exceptions for +/-.

Is there a rule for line break on chains?

I feel very dumb asking this, which is supposedly simple, but I searched all over the documentation and couldn't find anything.

There are a few operations that take a lot of space. For instance, a Firebase call might be:

FirebaseFirestore
            .getInstance()
            .collection("meetings")
            .document(currentId)
            .collection("all")
            ...
            .whereEqualTo("kind", kind)
            .get()
            .addOnCompleteListener { ... }

Is there supposed to be any rule regarding this kind of thing? For example, always break the line when there are more than two operations/"." going on..
I'm not sure if it is non-existent because "common sense" is enough, someone forgot, or it is there, but I couldn't see.

Thanks!

Enum constant names

The style guide doesn't talk about naming enum constants. They don't fall under "Constant values can only be defined inside of an object or as a top-level declaration", so they are not covered by that rule, and there should be a separate one for them.

(And please don't require UPPER_CASE for all enum constants; that would be ugly. Our style guide allows both UPPER_CASE and CamelCase.)

Be concrete about && and || at the beginning or end of a line

I think Java prefers

if (condition1
    && condition 2
    || condition3) {

    // do something
}

This style would make sense to me in Kotlin as well, but I couldn't find anything regarding to that in the IJ Kotlin style guide or Android style guide. Note that there has been some discussion going on in the ktlint project what prefers

if (condition1 &&
    condition2 ||
    condition3) {

    // do something
}

pinterest/ktlint#168

Update guide to avoid hungarian notation

Many developers have adopted the mHungarian notation (prefixing fields with a 'm') in their Android apps based off of early Android samples and the Android source code itself. Even though it has since come to light that field prefixing is not recommended, I've seen this style creeping into Kotlin now too unfortunately.

Could the Android Kotlin Style guide be updated to explicitly state that hungarian notation should not be used?

Table of Contents

Any chance of a table of contents in the Style Guide and the Interop Guide, like the one at the top of the Google Java Style Guide?

Thanks - these documents are incredibly useful to have!

if else expression

An if/else conditional that is used as an expression may omit braces only if the entire expression fits on one line.
https://android.github.io/kotlin-guides/style.html#expressions

I propose to relax the rule to allow

val value = if (string.isEmpty())
    calculator.zero() else
    calculator.one()

It's a syntax that I first saw in kotlinx.coroutines and after getting used to it, I found it to be elegant

// https://github.com/Kotlin/kotlinx.coroutines/blob/985f56e54060d05387d25319e630f39e2cce5d5d/js/kotlinx-coroutines-core-js/src/main/kotlin/kotlinx/coroutines/experimental/Deferred.kt#L143-L155
public actual fun <T> async(...): Deferred<T> {
    val newContext = newCoroutineContext(context, parent)

    val coroutine = if (start.isLazy)
        LazyDeferredCoroutine(newContext, block) else
        DeferredCoroutine<T>(newContext, active = true)

    coroutine.initParentJob(newContext[Job])
    start(block, coroutine, coroutine)
    return coroutine
}

Prefer parameters with default values last in the parameter list.

https://android.github.io/kotlin-guides/interop.html#function-overloads-for-defaults
mentions this but in a different context.

This is useful even in pure Kotlin, regardless of Java interop because it doesn't require naming the other parameters at the call site.

data class Pizza(val cheese: Boolean, val toppings: List<String> = listOf())
Pizza(true)

instead of

data class Pizza(val toppings: List<String> = listOf(), val cheese: Boolean)
Pizza(cheese = true)

Continuation indent for parameter lists

The current Google style guide requires 8-space indent for wrapped function parameter lists: https://android.github.io/kotlin-guides/style.html#functions

In our style guide, we'd really prefer to require 4-space indents. The reason why 4-space indents work better is primary constructor parameters: we really want to have the same indent for val/var properties defined in the primary constructor and in the body of the class. And to separate the parameters from the body, the wrapped closing parenthesis followed by the opening curly brace (which your current example already shows) works well enough.

Is there any strong reason why you prefer 8-space indents? If not, could you change the guidance?

Backticked function names in tests

The function names section permits using underscores in test function names to ease reading: @Test fun pop_emptyStack()

I propose:

  1. Permitting the usage of backticked test function names together with spaces for separating logical components of the name: @Test fun `pop emptyStack`()
  2. Recommending either the underscored naming or the backtick-spaced as a preferred way of naming for test functions

Guidelines for constructors

I was wondering if there were currently any thoughts on constructors and guidelines around those, or if these are more of a personal preference / per basis thing?

For example, using the primary constructor where only a few param passed in is usually quite readable, but there may be some cases where there are multiple classes passed in which can cause things to get a little hard to read within a primary constructor. The constructors here are probably a bit of an exageration but are just for example case.

class ExampleClass @Inject constructor(private val dogRepository: DogRepository,
private val catRepository: CatRepository, private val fishRepository: FishRepository,
private val rabbitRepository: BirdRepository, private val birdRepository: BirdRepository) 
: SomeClass { }

compared to:

class ExampleClass : SomeClass {

    private val dogRepository: DogRepository
    private val dogRepository: DogRepository
    private val catRepository: CatRepository
    private val fishRepository: FishRepository
    private val rabbitRepository: BirdRepository
    private val birdRepository: BirdRepository

    @Inject constructor(dogRepository: DogRepository, catRepository: CatRepository, 
        fishRepository: FishRepository, rabbitRepository: BirdRepository, birdRepository) : 
        BirdRepository) {

        //assign fields

    }

}

For data classes and objects this is usually a lot more readable, but for other classes it can become harder to read.

This could be down to a lower level problem of class design and structure, but it would be good to hear if anyone is already enforcing some form of rule as I guess I'm looking for some kind of consistency ๐Ÿ™‚ Maybe you're enforcing secondary constructors for certain classes or limiting constructors to a certain number of parameters - or you're not doing anything and just going with your gut!

View IDs when using Kotlin Android Extensions

When using the Kotlin Android Extensions plugin (https://kotlinlang.org/docs/tutorials/android-plugin.html) which automatically provides properties for your views, so you do not have to do lookup via findViewById, the naming convention for these IDs are in many cases in conflict with variable and property naming conventions. Should ID's follow camelCase patterns, or should property names deviate from the convention in this situation?

I think the style guide would benefit from saying something about this, but there is probably a discussion that needs to be had before we can define any style guide for this - hence this post.

My personal view is that any ID naming conventions should yield to Kotlin naming conventions in this case, as the impact of changing the naming convention will have a bigger positive impact on code readability than the negative impact on layout file readability.

Commence discussion! :)

Consider 120 character limit

What's the reasoning behind having a 100 character limit? I advocate bumping it to 120.

Pros (of 120 limit)

  • Allows the developer to be more expressive and write more readable code
    • helps make up for the lack of 2/2/4 indenting
    • kotlin's coroutines and let/run/etc functions add a lot of indenting
  • Jetbrains Kotlin style guide does not specify a column limit, so this doesn't conflict
  • Monitors are more than wide enough today to accommodate this

Cons

  • Google Java style is 100
  • IntelliJ doesn't seem to be able to support different line lengths per file type

Note: The primary goal for line wrapping is to have clear code, not necessarily code that fits in the smallest number of lines.

I believe 120 helps achieve this goal by not forcing line breaks when they don't make sense. Though of course this could be abused.

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.