1. Single Responsibility

[THEORY]

[PREDICT]

Read the code carefully before you run it.

prediction.kt
class User(private val firstName: String, private val lastName: String) {
    fun fullName(): String = firstName + " " + lastName

    fun saveToDatabase() {
        println("INSERT INTO users (name) VALUES ('" + fullName() + "')")
    }
}

fun main() {
    val user = User("Lena", "Fischer")
    println(user.fullName())
    user.saveToDatabase()
}

What does this print? The class holds user data: which of the two methods introduces a second reason to change, and why?

[TASK]

The function printOrderSummary does two jobs: it calculates the order total and it formats the output. Extract the calculation into a top-level function orderTotal(lines: List<OrderLine>): Double so the pricing rule has its own reason to change, and make printOrderSummary call it. The total is the sum of unitPrice * quantity; if that sum is greater than 100.0, apply a 5% discount. The printed output must stay exactly the same. Then call printOrderSummary with two lines in main.

task.kt
// TODO: extract the total calculation into a top-level function // `orderTotal(lines: List<OrderLine>): Double`, then let printOrderSummary use it. // The printed output must not change. data class OrderLine(val name: String, val unitPrice: Double, val quantity: Int) fun printOrderSummary(lines: List<OrderLine>) { var total = 0.0 for (line in lines) { total += line.unitPrice * line.quantity } if (total > 100.0) { total *= 0.95 } println("Order total: " + total + " EUR") for (line in lines) { println(line.name + " x" + line.quantity) } } fun main() { // TODO: call printOrderSummary with two lines and run the program. }

Before you get a hint: what have you tried, and where exactly are you stuck?

[COMPREHENSION CHECK]

1. What does the single-responsibility principle say a class should have?

2. A class both calculates a price and renders a PDF invoice. Why is that a problem?

3. Which question best helps you find responsibilities to separate?