it forces you to use concrete types and can lead to confusing bugs when refactoring. Use with care! • Be sure to enable type hints within Android Studio : Preferences -> Editor -> General -> Appearance -> Show parameter type hints -> Configure -> Language -> Kotlin
members are public by default • Everything is implicitly final except protected / interface members / override • internal stands for module-private visibility • private is either class-private or file-private for top-level members
init {…} 4. Subclass constructor 5. Subclass properties initialization 6. Subclass init {…} Avoid using open members in the constructors, property initializers, and init blocks in a base class
init blocks in a base class abstract class BaseGrid<out E> : Grid<E> { final override val rows = 0 until height final override val columns = 0 until width … } BAD: Accessing non-final properties in constructor
rows by lazy { 0 until height } final override val columns by lazy { 0 until width } … } Avoid using open members in the constructors, property initializers, and init blocks in a base class
Reified Erased Array<E> List<E> Runtime type safety Compile-time type safety Since Java 1 Since Java 5 reify | ˈriːɪfʌɪ, ˈreɪɪfʌɪ | verb (reifies, reifying, reified) [with object] formal make (something abstract) more concrete or real: these instincts are, in man, reified as verbal constructs.
fun <E> String.toMutableArrayGrid(toValue: (Char) -> E) : MutableArrayGrid<E> { val s = trimMargin().filter { it != '\n' } val array = Array(s.length) { i -> toValue(s[i]) } val width = trimMargin().lines().first().length return MutableArrayGrid(array, width) } Cannot use ‘E’ as reified type parameter. Use a class instead.
class ArrayGrid<E>( protected val array: Array<E?>, final override val width: Int) : BaseGrid<E?>() open class ArrayGrid<E>( protected val array: Array<E>, final override val width: Int) : BaseGrid<E>() BAD: Only supports nullable types
when possible • by keyword for Decorator pattern (i.e. class delegation) • object for Singleton pattern • Higher-order functions for Strategy pattern • Delegated properties for simple Observer pattern • sealed class for State pattern • Type-safe builder / default arguments for Builder pattern https://github.com/dbacinski/Design-Patterns-In-Kotlin
appropriate • require(…) throws IllegalArgumentException • check(…) throws IllegalStateException • Use assert(…) for internal or very expensive sanity checks. Won’t be compiled unless the -ea (enable assertions) flag is passed.
Int) : BaseGrid<E>() { init { require(array.size % width == 0) { "Grid must be a rectangle but array of size ${array.size} " + "wasn't divisible by width $width” // Lazy-evaluated } } … } Use check() and require()instead of if (…) throw {…} when appropriate
sort the method declarations alphabetically or by visibility, and do not separate regular methods from extension methods. Instead, put related stuff together, so that someone reading the class from top to bottom would be able to follow the logic of what's happening. Choose an order (either higher-level stuff first, or vice versa) and stick to it.”
a type and its extensions) into a single file, as long as the file stays short enough. • If you can’t find a good name for a variable, consider inlining it. Use let {…}, apply {…}, also {…}, run {…} or with(…) if need be.
is the root of all evil • Once your core structure is in place and your library is public, it’s too late to change it without introducing breaking changes for its users.
of a Function object, along with primitive boxing (unlike Java 8). Use inline keyword when appropriate. Be wary of local functions as they can’t be inlined. • companion object generate a lot of extra methods • Auto-generated null checks (can be disabled with ProGuard) • lazy properties are synchronized by default • Prefer for-loops over forEach {…} https://medium.com/@BladeCoder/exploring-kotlins-hidden-costs-part-1-fbb9935d9b62
that correctly measure the performance of a small part of a larger application is hard. There are many optimizations that the JVM or underlying hardware may apply to your component when the benchmark executes that component in isolation. These optimizations may not be possible to apply when the component is running as part of a larger application. Badly implemented microbenchmarks may thus make you believe that your component's performance is better than it will be in reality. http://tutorials.jenkov.com/java-performance/jmh.html
Object Black hole "consumes" the values, conceiving no information to JIT whether the value is actually used afterwards. This can save from the dead-code elimination of the computations resulting in the given values.
just copy-paste things from the Internet until they work (i.e. StackOverflow- Driven Development) THIS IS GRADLE. IT’S A BUILD SYSTEM FOR THE JVM THAT WORKS THROUGH A BEAUTIFUL DIRECTED ACYCLIC GRAPH MODEL.