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

Immutability Against The Machine

Immutability Against The Machine

Immutability has taken over the software world. Programmers are using immutable values to make their products more maintainable. They are able to focus on higher-level architectural problems instead of hard-to-debug accidental mutations.

However, the software we write often needs to run on a real machine. It needs state, it needs to do many things at once using multiple threads, and it needs to acquire some resources like sockets or files. Moreover, it needs to clean after itself in any condition, even when things go awry, making sure it never leaks memory or resources. We may be tempted to say that solving these concerns requires some old-school mutations. But it doesn’t!

In this talk we will show a real-world application that uses state, multiple threads, and resources. We will use real data from an external Wikidata service, make sure we conform to the API limits, implement a cache, and make sure we release all unneeded connections along the way. Most importantly, all this is going to be modeled as immutable values!

B03c3172ab0b44d369f1c57dad7b7de6?s=128

Michał Płachta

June 24, 2022
Tweet

More Decks by Michał Płachta

Other Decks in Programming

Transcript

  1. @miciek Michał Płachta www.michalplachta.com IMMUTABILITY AGAINST THE MACHINE

  2. @miciek Back to 2001

  3. @miciek 2001 Let’s replace Haskel l with Java University of

    Texas
  4. @miciek 2001 Let’s replace Haskel l with Java University of

    Texas
  5. @miciek Dijkstra writes to University of Texas https://www.cs.utexas.edu/users/EWD/transcriptions/OtherDocs/Haskell.html Facing students

    with the novelty of functional program m ing im m ediately drives home the mes s age that there is more to program m ing than they thought. “ ”
  6. @miciek Dijkstra writes to University of Texas https://www.cs.utexas.edu/users/EWD/transcriptions/OtherDocs/Haskell.html Facing students

    with the novelty of functional program m ing im m ediately drives home the mes s age that there is more to program m ing than they thought. “ ”
  7. @miciek - declarative, functional - relationships between values - rigorous

    reasoning - imperative - step-by-step statements - operational reasoning Learning from other paradigms Our Paradigm Other Paradigms
  8. @miciek DEMO: printing stuff in the REPL

  9. @miciek What is it? vs What does it do? declarative

    vs imperative The tools we use shape our thinking!
  10. @miciek The tools we use shape our thinking What is

    it? An immutable value! What does it do? Eeee… It prints ‘4’.
  11. @miciek - declarative, functional - relationships between values - rigorous

    reasoning - imperative - step-by-step statements - operational reasoning Learning from other paradigms What Does It Do? What is It? We can learn a lot from there!
  12. @miciek What does it do? List<Integer> xs = Arrays.asList(1, 2,

    3, 4, 5); List<Integer> result = new ArrayList < > (); // empty for (Integer x: xs) { result.add(x * 2); } // now result is a list [2, 4, 6, 8, 10] Java
  13. @miciek What is it? val numbers = List(1, 2, 3,

    4, 5) val doubles = numbers.map(i => i * 2) / / List(2, 4, 6, 8, 10)
  14. @miciek What is it? val numbers = List(1, 2, 3,

    4, 5) val doubles = numbers.map(i => i * 2) / / List(2, 4, 6, 8, 10) Scala numbers List[Int] doubles List[Int] .map
  15. @miciek What does it do? String tvShow = "The Wire

    (2002-2008)"; int extractYearStart(String show) throws Exception {…} int extractYearEnd(String show) throws Exception {…} int start = extractYearStart(tvShow); / / 2002 int end = extractYearEnd(tvShow); // 2008 Java
  16. @miciek What does it do? String tvShow = "The Wire

    (2002-2008)"; int extractYearStart(String show) throws Exception {…} int extractYearEnd(String show) throws Exception {…} int start = extractYearStart(tvShow); / / 2002 int end = extractYearEnd(tvShow); // 2008 extractYearStart("Chernobyl (2019)"); / / ??? Java
  17. @miciek What does it do? String tvShow = "The Wire

    (2002-2008)"; int extractYearStart(String show) throws Exception {…} int extractYearEnd(String show) throws Exception {…} int start = extractYearStart(tvShow); / / 2002 int end = extractYearEnd(tvShow); // 2008 extractYearStart("Chernobyl (2019)"); / / ??? Java
  18. @miciek What does it do? int extractYearStart(String show) throws Exception

    {…} int extractYearEnd(String show) throws Exception {…} int extractSingleYear(String show) throws Exception {…} Integer year = null; try { year = extractYearStart(tvShow); } catch(Exception e) { year = extractSingleYear(tvShow); } Java
  19. @miciek What is it? def extractYearStart(show: String): Option[Int] = ???

    def extractYearEnd(show: String): Option[Int] = ??? def extractSingleYear(show: String): Option[Int] = ??? Scala None Option[A] Some[A] val value: A
  20. @miciek What is it? def extractYearStart(show: String): Option[Int] = ???

    def extractYearEnd(show: String): Option[Int] = ??? def extractSingleYear(show: String): Option[Int] = ??? val year = extractYearStart(tvShow).orElse(extractSingleYear(tvShow)) Scala extractYearStart Option[Int] extractSingleYear Option[Int] year Option[Int] .orElse
  21. @miciek - declarative, functional - relationships between values - rigorous

    reasoning - what is it? - imperative - step-by-step statements - operational reasoning - what does it do? We don’t have to think like a machine The Machine Immutability
  22. @miciek Shaping our thinking habits It is not only the

    violin that shapes the violinist, we are al l shaped by the to o ls we train ourselves to use… “ ” https://www.cs.utexas.edu/users/EWD/transcriptions/OtherDocs/Haskell.html
  23. @miciek Plus… FP ideas aren’t going away https://www.infoq.com/articles/data-oriented-programming-java/

  24. @miciek Passing immutable values around numbers List[Int] extractYearStart Option[Int] extractSingleYear

    Option[Int] doubles List[Int] year Option[Int] .map .orElse
  25. @miciek What about talking to the outside world?

  26. @miciek IMMUTABILITY AGAINST THE MACHINE Using S tri n g

    s, L i s t s, Op ti ons Talking to the outside world Threads, resource safety, and state
  27. @miciek -User can search for an attraction name -The app

    finds the attraction and its location -It returns movies that are set in this location A peculiar travel guide
  28. @miciek A peculiar travel guide > “Bridge of Sighs” You

    searched for “Bridge of Sighs”, which is located in Venice. Before visiting, you can watch: Casino Royale
  29. @miciek The model case class LocationId(value: String) case class Location(id:

    LocationId, name: String) case class Attraction(name: String, location: Location) case class Movie(name: String, boxOffice: Long) case class TravelGuide(attraction: Attraction, movies: List[Movie])
  30. @miciek We will use Wikidata https://query.wikidata.org/

  31. @miciek Thinking Like A Machine https://jena.apache.org/

  32. @miciek String query = "SELECT DISTINCT ?attraction ?attractionLabel \n" +

    " ?location ?locationLabel WHERE {\n" + " ?attraction wdt:P31 wd:Q570116;\n" + " rdfs:label ?attractionLabel;\n" + " wdt:P131 ?location.\n" + "} LIMIT 3"; RDFConnection connection = RDFConnectionRemote.create() .destination("https: // query.wikidata.org/") .queryEndpoint("sparql") .build(); QueryExecution execution = connection.query(QueryFactory.create(query)); Java Thinking Like A Machine https://jena.apache.org/
  33. @miciek Iterator<QuerySolution> solutions = execution.execSelect(); while(solutions.hasNext()) { QuerySolution solution =

    solutions.next(); String id = solution.getResource("attraction").getLocalName(); String label = solution.getLiteral("label").getString(); System.out.printf("Got attraction %s (id = %s)%n", label, id); } Java Thinking Like A Machine Got attraction Yellowstone National Park (id = Q351) Got attraction Eiffel Tower (id = Q243) Got attraction Table Mountain (id = Q213360) Output
  34. @miciek def execQuery(query: String): IO[List[QuerySolution]] = { … } Scala

    Immutability https://typelevel.org/cats-effect/
  35. @miciek def execQuery(query: String): IO[List[QuerySolution]] = { … } Scala

    Immutability https://typelevel.org/cats-effect/ IO[List[QuerySolution]] Immutable value representing a potentially side-effectful program that, once executed successfully, will produce a list of query solutions.
  36. @miciek def execQuery(query: String): IO[List[QuerySolution]] = { IO.delay(connection.query(QueryFactory.create(query)).execSelect()) } Scala

    Immutability IO.delay( … ) Creates an immutable value representing a potentially side-effectful program that will execute the given block of code and return the result.
  37. @miciek def execQuery(query: String): IO[List[QuerySolution]] = { IO.delay(connection.query(QueryFactory.create(query)).execSelect()) } val

    solutionsProgram: IO[List[QuerySolution]] = execQuery(query) println(solutionsProgram) Scala Immutability
  38. @miciek def execQuery(query: String): IO[List[QuerySolution]] = { IO.delay(connection.query(QueryFactory.create(query)).execSelect()) } val

    solutionsProgram: IO[List[QuerySolution]] = execQuery(query) println(solutionsProgram) // IO( .. . ) Scala Immutability
  39. @miciek def execQuery(query: String): IO[List[QuerySolution]] = { IO.delay(connection.query(QueryFactory.create(query)).execSelect()) } val

    solutionsProgram: IO[List[QuerySolution]] = execQuery(query) val attractionsProgram: IO[List[Attraction]] = Scala Immutability We don’t have to run anything, let’s work with values first!
  40. @miciek def execQuery(query: String): IO[List[QuerySolution]] = { IO.delay(connection.query(QueryFactory.create(query)).execSelect()) } val

    solutionsProgram: IO[List[QuerySolution]] = execQuery(query) def parseAttraction(s: QuerySolution): Option[Attraction] = { … } val attractionsProgram: IO[List[Attraction]] = solutionsProgram.map(solutions = > solutions.flatMap(parseAttraction)) Scala Immutability
  41. @miciek val solutionsProgram: IO[List[QuerySolution]] = execQuery(query) val attractionsProgram: IO[List[Attraction]] =

    solutionsProgram.map(solutions = > solutions.flatMap(parseAttraction)) Scala Immutability List[QuerySolution] => List[Attraction] We transformed results without having them!
  42. @miciek Immutability def execQuery(query: String): IO[List[QuerySolution]] = { IO.delay(connection.query(QueryFactory.create(query)).execSelect()) }

    val solutionsProgram: IO[List[QuerySolution]] = execQuery(query) def parseAttraction(s: QuerySolution): Option[Attraction] = { … } val attractionsProgram: IO[List[Attraction]] = solutionsProgram.map(solutions = > solutions.flatMap(parseAttraction)) Scala solutionsProgram IO[List[QuerySolution]] attractionsProgram IO[List[Attraction]] .map
  43. @miciek DEMO: Let’s code the travel guide! > “Bridge of

    Sighs” You searched for “Bridge of Sighs”, which is located in Venice. Before visiting, you can watch: Casino Royale
  44. @miciek IMMUTABILITY AGAINST THE MACHINE Using S tri n g

    s, L i s t s, Op ti ons Talking to the outside world Threads, resource safety, and state
  45. @miciek - declarative, functional - relationships between values - rigorous

    reasoning - what is it? - imperative - step-by-step statements - operational reasoning - what does it do? We don’t have to think like a machine The Machine Immutability
  46. @miciek Shaping our thinking habits It is not only the

    violin that shapes the violinist, we are al l shaped by the to o ls we train ourselves to use… “ ” https://www.cs.utexas.edu/users/EWD/transcriptions/OtherDocs/Haskell.html
  47. @miciek Let’s go back to 2022

  48. @miciek Java (will) have it, too! FP Future Java

  49. @miciek https://www.manning.com/plachta Use code watchplachta40 www.michalplachta.com

  50. @miciek Michał Płachta www.michalplachta.com IMMUTABILITY AGAINST THE MACHINE code, links,

    slides, bo o k info