It takes a week to travel the 8,000 miles overland from Java to Kotlin. If you're an experienced Java developer who has tried the Kotlin language, you were probably productive in about the same time. You'll have found that they do things differently in Kotlin, though. Nullability is important, collections are different, and classes are final by default. Kotlin is more functional, but what does that mean, and how should it change the way that you program? And what about all that Java code that you still have to support? Your tour guides Duncan and Nat first made the trip in 2015, and they've since helped many teams and individuals follow in their footsteps. Travel with them as they break the route down into legs like Optional to Nullable, Beans to Values, and Open to Sealed Classes. Each explains a key concept and then shows how to refactor production Java to idiomatic Kotlin, gradually and safely, while maintaining interoperability. The resulting code is simpler, more expressive, and easier to change. By the end of the journey, you'll be confident in refactoring Java to Kotlin, writing Kotlin from scratch, and managing a mixed language codebase as it evolves over time. Cover Copyright Table of Contents Preface How This Book Is Organized How Did We Choose the Topics? Complexity Perfect Code Code Formatting Conventions Used in This Book Using Code Examples O’Reilly Online Learning How to Contact Us Acknowledgments Duncan’s Bit Nat’s Bit Chapter 1. Introduction The Grain of a Programming Language An Opinionated History of Java Programming Style Primeval Style Bean Style Enterprise Style Modern Style The Future The Grain of Kotlin Refactoring to Kotlin Refactoring Principles We Assume Good Test Coverage We Commit for Git Bisect What Are We Working On? Let’s Get Started! Chapter 2. Java to Kotlin Projects Strategy Adding Kotlin Support to a Java Build Moving On Chapter 3. Java to Kotlin Classes A Simple Value Type The Limitations of Data Classes Moving On Chapter 4. Optional to Nullable Representing Absence Refactoring from Optional to Nullable Refactoring to Idiomatic Kotlin Moving On Chapter 5. Beans to Values Beans Values Why Should We Prefer Values? Refactoring Beans to Values Moving On Chapter 6. Java to Kotlin Collections Java Collections Kotlin Collections Refactoring from Java to Kotlin Collections Fix Up the Java Convert to Kotlin Moving On Chapter 7. Actions to Calculations Functions Calculations Actions Why Should We Care? Why Prefer Calculations? Refactoring Actions to Calculations Existing Code A Better Design End Game Moving On Chapter 8. Static Methods to Top-Level Functions Java Statics Kotlin Top-Level Functions, Objects, and Companions Refactoring from Static Methods to Top-Level Functions Move to Top Level Kotlinify Moving On Chapter 9. Multi- to Single-Expression Functions Take 1: Inlining Take 2: Introduce a Function Take 3: Let Take 4: Stepping Back Moving On Chapter 10. Functions to Extension Functions Functions and Methods Extension Functions Extensions and Function Types Extension Properties Conversions Nullable Parameters Nullable Receivers Generics Extension Functions as Methods Refactoring to Extension Functions Moving On Chapter 11. Methods to Properties Fields, Accessors, and Properties How to Choose Mutable Properties Refactoring to Properties Moving On Chapter 12. Functions to Operators A Foundational Class: Money Adding a User-Defined Operator Calling Our Operator from Existing Kotlin Code Operators for Existing Java Classes Conventions for Denoting Values Moving On Chapter 13. Streams to Iterables to Sequences Java Streams Kotlin Iterables Kotlin Sequences Multiple Iterations Choosing Between Streams, Iterables, and Sequences Algebraic Transformation Refactoring from Streams to Iterables and Sequences Iterables First Then Sequences Extracting Part of a Pipeline Final Tidy Moving On Chapter 14. Accumulating Objects to Transformations Calculating with Accumulator Parameters Refactoring to Functions over Immutable Data Let’s Do That Again Enriching the Abstraction We Discovered Moving On Chapter 15. Encapsulated Collections to Type Aliases Composing Domain Collections Collections with Other Properties Refactoring Encapsulated Collections Convert Operations to Extensions Substitute a Type Alias Refactoring Collections with Other Properties Moving On Chapter 16. Interfaces to Functions Object-Oriented Encapsulation Functional Encapsulation Function Types in Java Mix and Match Comparing the Approaches Coupling Object-Oriented or Functional? The Legacy of Java Traceability Refactoring from Interfaces to Functions Introduce Functions Moving On Chapter 17. Mocks to Maps Replacing Mocks with Maps Have We Really Weaned Off Mocks, Though? Moving On Chapter 18. Open to Sealed Classes Polymorphism or Sealed Classes? Converting an Interface to a Sealed Class Moving On Chapter 19. Throwing to Returning Error Handling Before Exceptions Error Handling with Exceptions Java and Checked Exceptions Kotlin and Exceptions Beyond Exceptions: Functional Error Handling Error Handling in Kotlin Refactoring Exceptions to Errors Our Conversion Strategy Starting at the Bottom Contract Stepping Out More Fixup Layers Moving On Chapter 20. Performing I/O to Passing Data Listening to Tests I/O to Data Efficient Writing Efficient Reading Moving On Chapter 21. Exceptions to Values Identifying What Can Go Wrong Representing Errors What About I/O? Moving On Chapter 22. Classes to Functions An Acceptance Test Unit Testing Headers Different Field Separators Sequences Reading from a File Comparison with Commons CSV Moving On Chapter 23. Continuing the Journey Grain Functional Thinking Simple Design Functional Programming and Textual Reasoning Refactoring Refactoring and Functional Thinking Bibliography Learning Kotlin Testing and Test-Driven Development Working with Legacy Code Software Design and Development Java and the JVM Index About the Authors Colophon Kotlin Has Raised The Bar For Programming Languages On The Java Virtual Machine With Its Compatibility, Readability, Efficiency, And Tool Support. But Adopting A New Language Can Be Daunting, Especially When You're Working With Business-critical Java Code That Must Meet Changing Requirements. This Book Takes A Novel Approach To Introducing Kotlin To Java Programmers: Showing You How To Gradually Refactor Java Code To Idiomatic Kotlin While Continuing To Evolve Its Functionality. But Converting Java To Kotlin Is Just The Starting Point. Kotlin Has Many Features Beyond Java. Using Worked Examples, Authors Duncan Mcgregor And Nat Pryce Guide You Through Honing The Converted Code To Make It Simpler, More Efficient, More Expressive, And Easier To Change. You'll Learn How To Take Advantage Of Functional Constructs To Improve Program Structure, Reliability, And Error Handling. Once You Finish This Book, You'll Be Confident Writing Kotlin From Scratch, Converting Your Existing Java When Appropriate, And Managing A Mixed Java-kotlin Codebase As It Evolves Over Time. This book shows Java programmers how to gradually refactor their Java code using idiomatic Kotlin, while continuing to evolve the code's functionality. Authors Duncan McGregor and Nat Pryce break down the route from Java to Kotlin into legs like Optional to Nullable, Beans to Values, and Open to Sealed Classes.