Knowledge-base
  • Home
  • Samman Technical Coaching
  • Software craftsmanship
    • Practices
      • Pair Programming
      • Code Review
      • Co-designs
      • Design sessions
      • Interview Domain Experts
      • Dev ethics
    • The Software Craftsman
    • Egoless Crafting
    • Technical debt workshop
    • Functional Programming made easy in C# with Language-ext
    • F# for OO programmers
    • Domain Modeling Made Functional
    • Testing
      • Clean Tests
      • Improve the design and testing of your micro-services through CDC Tests
        • CDC testing made simple with Pact
        • Pact broker : the missing piece of your Consumer-Driven Contract approach
      • Improve your test quality with Mutation testing
      • How to name our Unit Tests
      • How to write better assertions
    • Katas
      • TDD
        • Stack kata
        • Fizzbuzz
        • Outside-in TDD (London Style)
      • Improve your software quality with Property-Based Testing
        • A journey to Property-Based Testing
      • Clean Code
      • Clean Architecture
      • Write S.O.L.I.D code
      • Mocking
      • Gilded Rose (Approval Testing)
      • Mikado method
        • Mikado kata
      • Pure functions
      • Theatrical players refactoring Kata
        • Let's refactor (OOP style)
        • Let's refactor (FP style)
      • Functional Programming made easy in Java & C#
      • Refactoring journey
      • Refactoring du Bouchonnois
        • 1) Se faire une idée du code
        • 2) "Treat warnings as errors"
        • 3) Let's kill some mutants
        • 4) Améliorer la lisibilité des tests
        • 5) "Approve Everything"
        • 6) Définir des propriétés
        • 7) Tests d'architecture
        • 8) Use Cases
        • 9) Tell Don't Ask
        • 10) "Avoid Primitives" - Commands
        • 11) "Avoid Exceptions"
        • 12) "Event Sourcing"
    • Software Design X-Rays
      • Workshop
    • The Programmer's Brain
      • How to read code better
  • Software Architecture
    • Fundamentals of Software Architecture
    • Aligning Product & Software Design
    • DDD re-distilled
    • Test your architecture with Archunit
    • NoSQL
  • Agile coaching
    • How to run a Community of Practices (COP)
    • The developers — the forgotten of agility
      • The secrets to re-on-board the devs in agility
    • Coaching toolbox
      • Echelle
      • Learning expedition
    • How to improve Team Decision making ?
      • Decision Making Principles and Practices
    • Learning 3.0
    • Retrospectives
      • Back to the Future
      • Mission Impossible
      • Movie themes
      • Rétro dont vous êtes le héros
      • Sad/Mad/Glad
      • Speed boat
      • Star wars theme
      • Story cubes
    • Technical Agile Coaching with the Samman Method
    • Xanpan - a team centric agile method story
    • XTREM WATCH — Découvrez la puissance de la veille collective
    • Become a better speaker through peer feedback
    • Project-to-Product Principles
  • Leadership
    • Bref. J'ai pris une tarte dans la gueule (et ça fait extrêmement de bien)
    • Forward Summit 2020
    • Learn leadership from the Navy SEALs
    • Learn to lead and help your team(s) to be successful
    • Towards a learning organization and beyond
    • Leadership is language
  • Serious games
    • My serious games
    • Libérez vos entretiens d’embauche avec la gamification
    • How to create a game
    • How to debrief a game ?
    • Lego Serious Play (LSP)
      • LSP in your job interviews
  • Xtrem Reading
    • Cultivate Team Learning with Xtrem Reading
    • My Book Infographics
    • How to make book infographics
    • En route vers l’apprenance avec Xtrem Reading
    • Resources
      • Book notes
        • Agile People: A Radical Approach for HR & Managers
        • Agile testing : A Practical Guide for Testers and Agile Teams
        • Boite à outils de l'intelligence émotionnelle
        • Building a better business using Lego Serious Play method
        • Building evolutionary architectures
        • Code that fits in your head
        • Culture Agile
        • Culture is everything
        • Domain-Driven Design: The First 15 Years
        • Dynamic Reteaming - The Art and Wisdom of Changing Teams
        • How to avoid a Climate Disaster
        • La liberté du commandement
        • Réaliser ses rêves, ça s'apprend
        • Refactoring at Scale
        • Succeeding with OKRs in Agile
        • Team Topologies
        • The Good Life
        • Tu fais quoi dans la vie
        • Who Does What By How Much?
  • My Activity
    • Retour sur mon année 2020
Powered by GitBook
On this page
  • Start by establishing our plan
  • 1) Extract the amount calculation
  • 2) Build a statement
  • 3) Run the pipeline
  • 4) Putting whole together

Was this helpful?

  1. Software craftsmanship
  2. Katas
  3. Theatrical players refactoring Kata

Let's refactor (FP style)

Theatrical players refactoring Kata in a Functional Programming style

PreviousLet's refactor (OOP style)NextFunctional Programming made easy in Java & C#

Last updated 4 years ago

Was this helpful?

Start by establishing our plan

We can use the to do so.

Here is mine :

1) Extract the amount calculation

PlayAmounts.java
@UtilityClass
class PlayAmounts {
    private static final NumberFormat FORMAT = NumberFormat.getCurrencyInstance(Locale.US);

    private static final IntUnaryOperator TRAGEDY =
            audience -> 40_000 + (audience > 30 ? 1_000 * (audience - 30) : 0);
    private static final IntUnaryOperator COMEDY =
            audience -> 30_000 + 300 * audience + (audience > 20 ? 10_000 + 500 * (audience - 20) : 0);

    private static final Map<String, IntUnaryOperator> TYPES =
            HashMap.of("tragedy", TRAGEDY, "comedy", COMEDY);

    static Integer forTypeAndAudience(String type, Integer audience) {
        return TYPES.get(type).map(f -> f.applyAsInt(audience))
                .getOrElseThrow(() -> new Error("Unknown type: " + type));
    }

    static String format(Integer amount) {
        return FORMAT.format(amount / 100);
    }
}

2) Build a statement

private String formatLine(String name, Integer amount, Integer audience) {
    return String.format("  %s: %s (%s seats)%n", name, format(amount), audience);
}

private String formatStatement(Invoice invoice, Statement pc) {
    return String.format("Statement for %s%n%sAmount owed is %s%nYou earned %s credits",
            invoice.customer, pc.line, format(pc.amount), pc.credits);
}

private Statement makeStatement(Performance perf, Play play) {
    int amount = PlayAmounts.forTypeAndAudience(play.type, perf.audience);
    int volumeCredits = computeCredits(play.type, perf.audience);
    String line = formatLine(play.name, amount, perf.audience);
    
    return new Statement(line, amount, volumeCredits);
}

3) Run the pipeline

public String print(Invoice invoice, java.util.Map<String, Play> plays) {
    return Vector.ofAll(invoice.performances)
            // for each performance make a statement
            .map(perf -> makeStatement(perf, plays.get(perf.playID)))
            // compute total amount and credit
            .reduceOption(Statement::add)
            // make the final statement to be printed
            .map(p -> formatStatement(invoice, p))
            .getOrElse("");
}

4) Putting whole together

StatementPrinter.java
public class StatementPrinter implements StatementPrinter {
    private String formatLine(String name, Integer amount, Integer audience) {
        return String.format("  %s: %s (%s seats)%n", name, format(amount), audience);
    }

    private String formatStatement(Invoice invoice, Statement pc) {
        return String.format("Statement for %s%n%sAmount owed is %s%nYou earned %s credits",
                invoice.customer, pc.line, format(pc.amount), pc.credits);
    }

    private Statement makeStatement(Performance perf, Play play) {
        int amount = PlayAmounts.forTypeAndAudience(play.type, perf.audience);
        int volumeCredits = computeCredits(play.type, perf.audience);
        String line = formatLine(play.name, amount, perf.audience);

        return new Statement(line, amount, volumeCredits);
    }

    private int computeCredits(String type, Integer audience) {
        return Math.max(audience - 30, 0)
                + ("comedy".equals(type) ? (audience / 5) : 0);
    }


    public String print(Invoice invoice, java.util.Map<String, Play> plays) {
        return Vector.ofAll(invoice.performances)
                // for each performance make a statement
                .map(perf -> makeStatement(perf, plays.get(perf.playID)))
                // compute total amount and credit
                .reduceOption(Statement::add)
                // make the final statement to be printed
                .map(p -> formatStatement(invoice, p))
                .getOrElse("");
    }
}

Our code is now ready to be extended with the new HTLM printer.

We will use to refactor this code in java.

vavr
mikado method