• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    迪恩网络公众号

openfresh/android-kotlin-style-guide: Kotlin style guide of FRESH LIVE since Apr ...

原作者: [db:作者] 来自: 网络 收藏 邀请

开源软件名称(OpenSource Name):

openfresh/android-kotlin-style-guide

开源软件地址(OpenSource Url):

https://github.com/openfresh/android-kotlin-style-guide

开源编程语言(OpenSource Language):


开源软件介绍(OpenSource Introduction):

Kotlin style guide of FRESH!

Vision

  • Write Kotlin like code. (Lamda, Collections, Extension functions)

    • Use lambda expression
    • Use extension functions (i.g. scope functions)
  • Write shorter

    • Code that is difficult to read for shortening doesn't mean anything
    • Bad code if you need to think

Rule

  • Use a formatter in /.idea/codeStyleSttings.xml
  • Start a new line at right vertica line on android studio. (about 130 characters)

Coding rules

  • bad
    not recommend
  • not good
    No problem in Kotlin but it is not coding rules in FRESH!
  • good
    recommend in FRESH!

Both bad, not good and good are correct in Kotlin.
These definitions are on coding rules.

Idiom

Use an IDE suggestion

val array = ArrayList<Int>()

// bad
array.get(0)    

// good
array[0]


// bad
getActivity().finish()

// good
activity.finish()

Use a smart cast

fun hoge(value: Boolean?) {
    value ?: return
    if (value) {

    }
}

fun hoge(context: Context) {
    context as Activity
    context.finish() // finish activity
}

// bad
if (hoge !is Hoge) {
    throw IllegalArgumentException("not Hoge!")
}
hoge.foo()

// good
hoge as? Hoge ?: throw IllegalArgumentException("not Hoge!")
hoge.foo()

Line break

  • Start a new line at right vertical line on Android studio. (About 130 characters)

RightVerticalLine

  • Start a new line by a symbol which are ,, :, {, = in case characters over vertical line.
fun hoge(aaa: Int, bbb: Int, ccc: Int, ddd: Int, eee: Int,
     fff: Int, ggg: Int) {
}

fun hoge(aaa: Int, bbb: Int, ccc: Int, ddd: Int, eee: Int) =
   hoge().apply {
   }

data class Hoge(private val aaa: Int, private val bbb: Int) :
         AbstractHoge() {
}

it in Lambda expression applies to wide scope.

// bad
{ hoge -> 
  hoge?.let { it.foo() }
}

// good
{ 
  it?.let { hoge -> hoge.foo() }
}

Should use a type interface

You can write a type if it is difficult to understand.

  • property
val hoge = 0  // Int
val foo = 10L // Long
val bar = 100f //Float
  • function
// return Boolean
fun Context.isConnectToWifi() =
      (getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager)
         .activeNetworkInfo?.type == ConnectivityManager.TYPE_WIFI

// return Point
fun Display.getSize(): Point = Point().apply { getSize(this) }

Don't write for loop

You don't have to write for loop because threre is forEach in collections package of Kotlin.

// not good
for (i in 0..9) {
}

// good
(0..9).forEach {
}

// good (if you want to know index)
(0..9).forEachIndexed { index, value ->
}

Use to expression creating Pair class

// bad
val pair = Pair(foo, bar) 

// good 
val pair = foo to bar
  • to is infix function

public infix fun <A, B> A.to(that: B): Pair<A, B> = Pair(this, that)

Use range

val char = 'K'

// bad
if (char >= 'A' && 'c' <= 'Z') print("Hit!")

// good
if (char in 'A'..'Z') print("Hit!")

when (char) {
   in 'A'..'Z' -> print("Hit!")
   else -> return
}

when

Use when in case there are two or more branches of if-else

// bad
val hoge = 10if (hoge > 10) {

} else if (hoge > 5) {

} else if (hoge > 0) {

} else {

}

// good
when {
    hoge > 10 -> print("10")
    hoge > 5 -> print("0")
    hoge > 0 -> print("0")
    else -> print("else")
}

Use is in case of comparing a class type

val hoge: Hoge = Hoge()
when (hoge) {
    is Hoge -> {

    }
    else -> {
       
    }
}

Use range in case comparing Int values

val hoge = 10
when (hoge) {
    in 0..4 -> print("0..4")
    in 5..10 -> print("5..10")
}

Don't start a new line in variable declaration using if-else

val foo: Int = 5

// bad
val bar = if (foo > 10) {
    "kotlin"
} else {
    "java"
}

// good
val bar = if(foo > 10) "kotlin" else "java"

Null

Don't use !!

Don't use !!, it will erase the benefits of Kotlin.
You use it only when you want to explicitly raise a Null Pointer Exception.

Use a scope function in case of checking a null value

class Hoge {
    fun fun1() {}
    fun fun2() {}
    fun fun3() = true
}

var hoge: Hoge? = null

// not good
if (hoge != null) {
    hoge.fun1()
} else {
    val hoge = Hoge()
    hoge.fun1()
    hoge.fun2()
}

// good
hoge?.run { 
   fun1()
} ?: run {
    hoge = Hoge().apply {
        fun1()
        fun2()
    }
}

// good
if (hoge != null && hoge.fun3()) {
    hoge.fun1()
} else {
    hoge = Hoge().apply {
       fun1()
       fun2()
    }
}

Property

Property rules

  • Use non-null value as much as possible
  • Don't use a m-prefix
  • Property priority
    • non-null & val
    • non-null & var
    • nullable & var

Use a lateinit or Delegates.notNull() if you cannot set a initial value.
lateinit is better than Delegates.notNull() because Delegates.notNull() uses reflection. But primitive values is not applied to lateinit.

// non-null & val
private val hoge: Hoge = Hoge()
private val drawablePadding: Int by lazy { activity.resources.getDimensionPixelSize(R.dimen.drawable_padding) }

// non-null & var
private lateinit var hoge: Hoge
private var hoge: Hoge = Delegates.notNull()

// nullable & var
private var hoge: Hoge? = null

Constant

Use const val for static final in Java. But primitive values is not applied to const.

Write a companion object block under class declaration.

Scope function

Should use scope function

class Hoge {
    fun fun1() {}
    fun fun2() {}
}

// bad
val hoge = Hoge()
hoge.fun1()
hoge.fun2()

// good
val hoge = Hoge().apply {
   fun1()
   fun2()
}

You don't need to use with because you can substitute run, let, apply, also.

Don't declare variables that used only once

You can express using a scope function.
But it becomes hard to read in case it excessibely use.
You should declare variables if you need to think.

class Foo

class Bar(val foo: Foo)

class Hoge {
    fun fun1() {}
    fun fun2(bar: Bar) {}
    fun fun3(foo: Foo) {}
}

// bad
val hoge = Hoge()
val foo = Foo()
val bar = Bar(foo)
hoge.fun1()
hoge.fun2(bar)
hoge.fun3(foo)

// good
Hoge().run {    
   fun1()
   Foo().let {        
       fun2(Bar(it))
       fun3(it)
   }
}

which use run or let

  • Use let to substitute into functions
  • Use run to use outside functions
class Foo

class Bar(val foo: Foo)

class Hoge {
    fun fun1() {}
    fun fun2(bar: Bar) {}
    fun fun3(foo: Foo) {}
}

// not good
Hoge().let {
   it.fun1()
   Foo().run {
       it.fun2(Bar(this))
       it.fun3(this)
   }
}

// good
Hoge().run {    
   fun1()
   Foo().let {        
       fun2(Bar(it))
       fun3(it)
   }
}

Function

Omit a type of return value

Basically, we omit a type of return value as declaration variables using type interface.
You should write it in case we cannot guess from a method name.

fun createIntent(context: Context, foo: Int, bar: Boolean) = 
Intent(context, HogeActivity::class.java).apply {    
   putExtra("foo", foo)
   putExtra("bar", bar)
}

fun hoge(value: Int): String = when (value) {
   in 0..10 -> "foo"
   in 100..500 -> "bar"
   else -> "else"
}

Don't name setHoge, getHoge

Don't name setHoge, getHoge at property and function because it is used in Kotlin language.

// bad
fun setHoge() {
}

Use named arguments for function overloading

// bad
class Hoge {
   fun hoge() {
      print("hoge")
   }

   fun hoge(prefix: String) {
       print(prefix + "hoge")
   }
}

// good
class Hoge {
   fun hoge(prefix: String = "") {
      print(prefix + "hoge")
   }
}

Use typealias

// bad
interface CallBackListener {
   fun onHoge(foo: String, bar: Int)
}

// caller
var callback: CallBackListener? = null
callback?.onHoge("foo", 100)

// callee
val callback = object : CallBackListener {
  override fun onHoge(foo: String, bar: Int) {
    print("$foo : $bar")
  }
}

// good
typealias CallBackListener = (foo: String, bar: Int) -> Unit

// caller
var callback: CallBackListener? = null
callback?.invoke("foo", 100)

// callee
val callback = { foo, bar -> 
  print("$foo : $bar")
}

Extension functions

  • Use it as utility functions in Java

  • It is not necessary to use extension functions in case it is defined wide scope. i.g. String In case we recommend the private extension functions.

  • Extension class name : HogeExt.kt

  • Structure of package

main
 |-data
 |-ui
   |-util
     |-ext
 |-util
   |-ext

Private extension functions

Functions taking only one object as an argument replace private extension functions. (not necessary)

enum class Hoge() {
    FOO,
    BAR,
    NONE
}

// not good
fun toHoge(arg: String): Hoge {
    if (!arg.startsWith("hoge")) {
        return Hoge.NONE    
    }
    return when (arg) {
       "hogeFoo" -> Hoge.FOO
       "hogeBar" -> Hoge.BAR
       else -> Hoge.NONE
    }
}

// good
fun String.toHoge(): Hoge {
    if (!startsWith("hoge")) {
        return Hoge.NONE    
    }
    return when (this) {
       "hogeFoo" -> Hoge.FOO
       "hogeBar" -> Hoge.BAR
       else -> Hoge.NONE    }
    }
}

Don't create extension functions in same class.

class Hoge {

   // bad
   fun Hoge.foo() {
   }

   // good
   fun foo() {
   }
}

Others

Rx


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
ArpitShukIa/KotlinWorkshop发布时间:2022-07-07
下一篇:
cambridge/thesis: A LaTeX document class that conforms to the Computer Laborator ...发布时间:2022-07-09
热门推荐
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap