Kt. Academy Logo

Effective Kotlin

Our special learning place

Item 1: Limit mutability
Exercise: A mutability problem
Exercise: Flow with history
Item 2: Eliminate critical sections
Exercise: Correct InMemoryUserRepository
Exercise: Chunking a flow
Item 3: Eliminate platform types as soon as possible
Item 4: Minimize the scope of variables
Item 5: Specify your expectations for arguments and state
Exercise: Specify expectations
Item 6: Prefer standard errors to custom ones
Item 7: Prefer a nullable or Result result type when the lack of a result is possible
Item 8: Close resources with use
Item 9: Write unit tests
Exercise: Unit testing
Exercise: Unit testing using mocks
Part 1: Good code
Item 10: Design for readability
Item 11: An operator’s meaning should be consistent with its function name
Item 12: Use operators to increase readability
Item 13: Consider making types explicit
Item 14: Consider referencing receivers explicitly
Item 15: Properties should represent a state, not a behavior
Item 16: Avoid returning or operating on Unit?
Item 17: Consider naming arguments
Item 18: Respect coding conventions
Chapter 2: Readability
Item 19: Do not repeat knowledge
Item 20: Do not repeat common algorithms
Item 21: Use generics when implementing common algorithms
Item 22: Avoid shadowing type parameters
Item 23: Consider using variance modifiers for generic types
Item 24: Reuse between different platforms by extracting common modules
Part 2: Code design
Item 25: Each function should be written in terms of a single level of abstraction
Item 26: Use abstraction to protect code against changes
Item 27: Specify API stability
Item 28: Consider wrapping external APIs
Item 29: Minimize elements’ visibility
Item 30: Define contracts with documentation
Item 31: Respect abstraction contracts
Chapter 4: Abstraction design
Item 32: Consider factory functions instead of secondary constructors
Item 33: Consider a primary constructor with named optional arguments
Item 34: Consider defining a DSL for complex object creation
Item 35: Consider using dependency injection
Chapter 5: Object creation
Item 36: Prefer composition over inheritance
Exercise: Composition vs inheritance
Item 37: Use the data modifier to represent a bundle of data
Item 38: Use function types or functional interfaces to pass operations and actions
Item 39: Use sealed classes and interfaces to express restricted hierarchies
Item 40: Prefer class hierarchies instead of tagged classes
Item 41: Use enum to represent a list of values
Item 42: Respect the contract of equals
Item 43: Respect the contract of hashCode
Item 44: Respect the contract of compareTo
Exercise: Make DeckConnector comparable
Item 45: Consider extracting non-essential parts of your API into extensions
Item 46: Avoid member extensions
Chapter 6: Class design
Item 47: Avoid unnecessary object creation
Item 48: Consider using object declarations
Item 49: Use caching when possible
Item 50: Extract objects that can be reused
Item 51: Use the inline modifier for functions with parameters of functional types
Item 52: Consider using inline value classes
Item 53: Eliminate obsolete object references
Exercise: Eliminate a memory leak
Part 3: Efficiency
Item 54: Prefer Sequences for big collections with more than one processing step
Item 55: Consider associating elements to a map
Exercise: Prime access list
Item 56: Consider using groupingBy instead of groupBy
Exercise: Crime analysis
Item 57: Limit the number of operations
Item 58: Consider Arrays with primitives for performance-critical processing
Item 59: Consider using mutable collections
Item 60: Use appropriate collection types
Chapter 8: Efficient collection processing