Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Functional Android

Functional Android

For the most part, programming in Android has meant living in the imperative programming world. Recently, many aspects of functional programming have become standard with the adoption of Kotlin and RxJava. What does it mean to use functional paradigm properties in our Android code, and how can it help us? In this talk you’ll learn some of the fundamentals of functional programming, and what this might look like on Android.

Victoria Gonda

February 27, 2018
Tweet

More Decks by Victoria Gonda

Other Decks in Programming

Transcript

  1. @TTGonda WHO AM I? ➤ Android Engineer at Buffer ➤

    Author for Ray Wenderlich ➤ Chicago ➤ Dancer
  2. @TTGonda THANKS TO ANUP COWKUR ➤ His blog posts provided

    lots of help in the research of this topic. ➤ Functional Programming for Android Developers
  3. @TTGonda WHY FUNCTIONAL PROGRAMMING? ➤ We’re seeing an increase of

    the use of the paradigm (Kotlin, RxJava, Λrrow) ➤ Features can be used to write cleaner, more expressive code ➤ Simplifies concurrency ➤ Easier to test Photo by Jennifer Pallian on Unsplash
  4. @TTGonda WHAT IS FUNCTIONAL PROGRAMMING? ➤ Came from lambda calculus

    ➤ Mimics the evaluation of mathematical functions ➤ Easier to test ➤ Some key characteristics of FP ➤ Declarative ➤ Explicitness ➤ Concurrency ➤ Higher Order Functions ➤ Immutability Photo by Patrick Tomasso on Unsplash
  5. @TTGonda WHAT ARE WE GOING TO TALK ABOUT? ➤ Pure

    functions ➤ No side effects ➤ Ordering ➤ Immutability ➤ Concurrency ➤ Higher order functions ➤ Error handling
  6. @TTGonda PURE FUNCTIONS ➤ Always gives the same output for

    a given input ➤ Independent of the outside world ➤ No side effects ➤ Easy to test Photo by Toa Heftiba on Unsplash
  7. @TTGonda NO SIDE EFFECTS ➤ Don’t change anything outside ➤

    Lessens the dependence on context ➤ Eliminates surprises ➤ You guessed it, easier to test Photo by Annie Shelmerdine on Unsplash
  8. @TTGonda NO SIDE EFFECTS fun blend(milk: Milk, icecream: IceCream, ingredients:

    List<Ingredient>): Milkshake { return glasses.pop() .fill(Milkshake(milk, icecream, ingredients)) }
  9. @TTGonda NO SIDE EFFECTS fun blend(glass: Glass, milk: Milk, icecream:

    IceCream, ingredients: List<Ingredient>): Milkshake { return glass.fill(Milkshake(milk, icecream, ingredients)) }
  10. @TTGonda ORDERING ➤ Things that can be executed in any

    order ➤ Something we get to do when we have pure functions ➤ This means they can also be concurrent! Photo by Gabriel Gurrola on Unsplash
  11. @TTGonda IMMUTABILITY ➤ No changing things ➤ Want something different,

    make a new one ➤ You know it won’t change on you ➤ Watch for mutable child objects Photo by Alireza Etemadi on Unsplash
  12. @TTGonda IMMUTABILITY public class Burger { private String type; public

    Burger(String type) { this.type = type; } public final String getType() { return this.type; } public final void setType(String type) { this.type = type; } }
  13. @TTGonda IMMUTABILITY final public class Burger { final private String

    type; public Burger(String type) { this.type = type; } public final String getType() { return this.type; } }
  14. @TTGonda IMMUTABILITY class Burger(var type: String, val toppings: MutableList<String>) val

    burger = Burger("veggie", mutableListOf()) burger.toppings.add("onion")
  15. @TTGonda IMMUTABILITY final public class Burger { final private String

    type; final private List<String> toppings; public Burger(String type, List<String> toppings) { /* ... */ } public final String getType() { /* ... */ } public final List<String> getToppings() { List<String> toppingsCopy = new ArrayList<>(); toppingsCopy.addAll(toppings); return toppingsCopy; } }
  16. @TTGonda CONCURRENCY ➤ We want concurrency, but it can be

    hard ➤ Using pure functions with no side effects and immutability helps ➤ We can do things on different threads, without worrying about unexpected behavior ➤ Locks aren’t required, so we don’t have to worry about deadlock Photo by ål nik on Unsplash
  17. @TTGonda CONCURRENCY fun addToppings(burger: Burger, toppings: List<String>) : Observable<Burger> {

    burger.toppings.addAll(toppings) return Observable.just(burger) .subscribeOn(kitchenThread) }
  18. @TTGonda CONCURRENCY fun addToppings(burger: ImmutableBurger, toppings: List<String>) : Observable<ImmutableBurger>? {

    val newBurger = burger.copy(toppings = toppings) return Observable.just(newBurger) .subscribeOn(kitchenThread) }
  19. @TTGonda HIGHER ORDER FUNCTIONS ➤ Functions as first class citizens

    ➤ Pass functions into a function ➤ Share logic the way you do an object ➤ Lose single abstract method interfaces Photo by Emmy Smith on Unsplash
  20. @TTGonda HIGHER ORDER FUNCTIONS fun makePotatoes(potatoes: Potatoes, cookPotatoes: (Potatoes) ->

    CookedPotatoes) { val cleanPotatoes = washAndPeelPotatoes(potatoes) val cookedPotatoes = cookPotatoes(cleanPotatoes) eatPotatoes(cookedPotatoes) }
  21. @TTGonda HIGHER ORDER FUNCTIONS makePotatoes(Potatoes(), ::fryPotatoes) makePotatoes(Potatoes()) { fryPotatoes(it) }

    makePotatoes(Potatoes(), { fryPotatoes(it) }) makePotatoes(Potatoes(), { potatoes -> fryPotatoes(potatoes) })
  22. @TTGonda ERROR HANDLING ➤ Everything is a value or computation

    ➤ Avoiding unexpected states ➤ Errors are treated as values Photo by chuttersnap on Unsplash
  23. @TTGonda ERROR HANDLING try { deliver(burger) } catch (error: DroppedPlateException)

    { makeNew(burger) } try { deliver(pancakes) } catch (error: DroppedPlateException) { makeNew(pancakes) } try { deliver(fries) } catch (error: DroppedPlateException) { makeNew(fries) } try { deliver(hashbrowns) } catch (error: DroppedPlateException) { makeNew(hashbrowns) }
  24. @TTGonda TOOLS ➤ Kotlin programming language ➤ RxJava library ➤

    Λrrow library Photo by Leti Kugler on Unsplash
  25. @TTGonda { previousState, result -> when (result) { is FoldersResult.GetLastState

    -> previousState is FoldersResult.LoadFoldersTask -> { when { result.status == TaskStatus.SUCCESS -> FoldersUiModel.FoldersLoaded(result.folders) result.status == TaskStatus.FAILURE -> FoldersUiModel.Failed result.status == TaskStatus.IN_FLIGHT -> FoldersUiModel.InProgress else -> FoldersUiModel.Idle() } } } }
  26. @TTGonda { previousState, result -> when (result) { is FoldersResult.GetLastState

    -> previousState is FoldersResult.LoadFoldersTask -> { when { result.status == TaskStatus.SUCCESS -> FoldersUiModel.FoldersLoaded(result.folders) result.status == TaskStatus.FAILURE -> FoldersUiModel.Failed result.status == TaskStatus.IN_FLIGHT -> FoldersUiModel.InProgress else -> FoldersUiModel.Idle() } } } }
  27. @TTGonda { previousState, result -> when (result) { is FoldersResult.GetLastState

    -> previousState is FoldersResult.LoadFoldersTask -> { when { result.status == TaskStatus.SUCCESS -> FoldersUiModel.FoldersLoaded(result.folders) result.status == TaskStatus.FAILURE -> FoldersUiModel.Failed result.status == TaskStatus.IN_FLIGHT -> FoldersUiModel.InProgress else -> FoldersUiModel.Idle() } } } }
  28. @TTGonda { previousState, result -> when (result) { is FoldersResult.GetLastState

    -> previousState is FoldersResult.LoadFoldersTask -> { when { result.status == TaskStatus.SUCCESS -> FoldersUiModel.FoldersLoaded(result.folders) result.status == TaskStatus.FAILURE -> FoldersUiModel.Failed result.status == TaskStatus.IN_FLIGHT -> FoldersUiModel.InProgress else -> FoldersUiModel.Idle() } } } }
  29. @TTGonda { previousState, result -> when (result) { is FoldersResult.GetLastState

    -> previousState is FoldersResult.LoadFoldersTask -> { when { result.status == TaskStatus.SUCCESS -> FoldersUiModel.FoldersLoaded(result.folders) result.status == TaskStatus.FAILURE -> FoldersUiModel.Failed result.status == TaskStatus.IN_FLIGHT -> FoldersUiModel.InProgress else -> FoldersUiModel.Idle() } } } }
  30. @TTGonda RESOURCES ➤ Functional Programming for Android Developers by Anup

    Cowkur ➤ Functional Reactive Programming with RxJava by Francisco González ➤ Functional Programming in Kotlin with Arrow by Jorge Castillo on Caster.io