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

The Complexity Trap: Think Before You Leap

The Complexity Trap: Think Before You Leap

Recently, many people in the functional programming community, and specifically in the Scala community, seem to follow the trend of solving their programming problems with more and more fancy abstractions and techniques. If in doubt, we throw a monad at the problem, and if that’s not good enough, we’ll make it free. Naturally, to top it off, we have to sprinkle the whole thing with some type-level programming, because this is common courtesy these days.
LAMBDA WORLD 2018, Cádiz

In this talk I want to challenge some of the fundamental assumptions of how we think and work. With all our sophisticated engineering, are we actually solving the right problems? Are we rushing towards technologically exciting solutions too quickly? How much of the complexity in our software is inherent in the problem domain, and how much of it is of our own making? We may have honorable intentions, but do our solutions come at an acceptable price? Maybe it’s time to slow down, think about what the problems we have to solve actually are, and how to do so in the simplest way possible.

Daniel Westheide

October 26, 2018
Tweet

More Decks by Daniel Westheide

Other Decks in Programming

Transcript

  1. LAMBDA WORLD CADIZ 2018
    The Complexity
    Trap: Think
    Before You Leap
    Daniel Westheide
    @kaffeecoder

    View Slide

  2. What is this talk about?
    Photo by Domenico Gentile on Unsplash

    View Slide

  3. Agenda
    • What is complexity?
    • The complexity trap & how to escape it
    – Neglecting the costs
    – Embracing industry standards
    – Maximum zoom
    • Conclusions

    View Slide

  4. complex
    Photo by drmaket lab on Unsplash

    View Slide

  5. simple
    Photo by Johny Goerend on Unsplash

    View Slide

  6. Types of complexity
    • Essential complexity
    • Accidental complexity

    View Slide

  7. Metrics or it didn‘t happen!
    // Cyclomatic complexity = 1
    def squared(x: Int): Int = x * x
    // Cyclomatic complexity = 2
    def max(x: Int, y: Int): Int =
    if (x >= y) x
    else y

    View Slide

  8. Cognitive complexity
    public static int sumOfPrimes(int max) {
    int total = 0;
    OUT: for (int i = 1; i <= max; ++i) {
    for (int j = 2; j < i; ++j) {
    if (i % j == 0) {
    continue OUT;
    }
    }
    total += i;
    }
    return total;
    }
    def sumOfPrimes(max: Int): Int = Stream
    .range(1, max + 1)
    .filter(i => (2 until i).forall(j => i % j != 0))
    .sum
    Java version taken from:
    https://blog.sonarsource.com/cognitive-complexity-because-testability-understandability

    View Slide

  9. Miller‘s law
    Photo by juan pablo rodriguez on Unsplash

    View Slide

  10. Abstraction
    Photo by Jaciel Melnik on Unsplash

    View Slide

  11. The sound of poison has gone off
    Our traps aren't malleable, beware!
    No dogma or deterrent can dissuade us from our torment path
    Said path has run nigh on eight years
    Dark skills in trade, we hone and sharpen arrow blade
    The trap is laid
    While we await and wait and wait
    Laying Traps
    Crippled Black Phoenix
    2012
    Photo by Mario Azzi on Unsplash

    View Slide

  12. Neglecting the costs
    Photo by Marissa Rodriguez on Unsplash

    View Slide

  13. Example:
    Scrapping your boilerplate
    with too much passion

    View Slide

  14. Choose your poison
    Photo by Kylli Kittus on Unsplash

    View Slide

  15. Embracing industry standards
    Photo by Samuel Zeller on Unsplash

    View Slide

  16. Embracing industry standards the latest fad
    Photo by Shawn McKay on Unsplash

    View Slide

  17. Example:
    Abstracting over monads.
    Everywhere. All the time.

    View Slide

  18. Use cases
    • Library development
    • Need for multiple interpreters in your
    program

    View Slide

  19. Uses in application development
    def showArticlePage(id: Long): Task[ArticlePage] = for {
    article <- fetchArticle(id)
    comments <- if (article.commentingAllowed)
    fetchComments(id) else Task.now(Seq.empty)
    } yield ArticlePage(article, comments)
    def showArticlePage(id: Long): Free[Effect, ArticlePage] = for {
    article <- fetchArticle(id)
    comments <- if (article.commentingAllowed)
    fetchComments(id) else Free.pure[Effect, Seq[Comment]](Seq.empty)
    } yield ArticlePage(article, comments)

    View Slide

  20. The costs of abstraction

    View Slide

  21. Foregoing abstraction
    Photo by Markus Spiske on Unsplash

    View Slide

  22. Functional core, imperative shell
    Photo by Kelly Sikkema on Unsplash

    View Slide

  23. Functional core, imperative shell
    // imperative shell:
    def showArticlePage(id: Long): Task[ArticlePage] = for {
    article <- fetchArticle(id)
    comments <- commentingAllowed(article)
    .fold(_ => Task.now(Seq.empty), _ => fetchComments(id))
    } yield ArticlePage(article, comments)
    // functional core:
    def commentingAllowed(article: Article): Either[String, Unit] = {
    if (article.commentingAllowed) Right(())
    else Left("Commenting not allowed")
    }

    View Slide

  24. Discourse
    • Focuses on how instead of why (or why
    not)
    • Emphasis on more and more advanced
    techniques

    View Slide

  25. Let’s write more about
    trade-offs

    View Slide

  26. Let’s write more about
    boring solutions

    View Slide

  27. Maximum zoom
    Photo by Drew Graham on Unsplash

    View Slide

  28. Example:
    Microservices with
    frontend service

    View Slide

  29. We jump towards
    technological solutions
    too quickly

    View Slide

  30. aim42
    • Architecture improvement method
    • Iteratively in three phases:
    – Analyse
    – Evaluate
    – Improve
    • https://aim42.org/

    View Slide

  31. Root cause analysis

    View Slide

  32. … applied to the latency problem
    • Why is our overall request latency so
    high?
    • Why do we need to make so many
    requests?
    • Why are our microservices designed
    around a single entity?
    • What if … ?

    View Slide

  33. What if … ?

    View Slide

  34. … applied to the JSON codecs
    • Why do we provide a JSON API?
    • Why do we have a single page app?

    View Slide

  35. What if …
    • we did server-side rendering of HTML?
    – No JSON API
    – No duplicated business logic
    – Much simpler frontend JS code
    https://medium.com/@jmanrubia/escaping-the-spa-rabbit-hole-with-turbolinks-903f942bf52c

    View Slide

  36. We love (functional)
    programming too much

    View Slide

  37. Coding ~ Comfort zone
    Photo by Marcos Gabarda on Unsplash

    View Slide

  38. What does it mean to be a
    software developer?

    View Slide

  39. Conclusions
    • Leave your programmer comfort zone
    • Consider costs
    • Talk about trade-offs
    • Don’t ignore boring solutions
    • Slow down & stop meddling with
    symptoms

    View Slide

  40. Thanks for your attention!
    Questions?
    Daniel Westheide
    @kaffeecoder

    View Slide