background-image: url(../img/fp-tower/website-background.svg) class: center, middle, white .title[Refactoring] ---
.ninety-seven-right[ # Which is more difficult? ## 1. Updating an existing program ## 2. Creating one from scratch ] --- # New application
.fifty-seven-left[ ## 1. Comfortable with the tech stack ## 2. Understand the business requirements ## 3. No users! ] --- # Existing application
.fifty-two-left[ ## 1. Poorly documented ## 2. Limited test coverage ## 3. Original developers and business
     users have left the organization ] --- class: medium-code # Refactoring: reorder variables .forty-seven-left[ ```scala def helloV1(user: User) = { val res1 = funA(user) val res2 = funB(user) // ... } ``` ] --- class: medium-code # Refactoring: reorder variables .forty-seven-left[ ```scala def helloV1(`user: User`) = { val res1 = funA(user) val res2 = funB(user) // ... } ``` ] --- class: medium-code # Refactoring: reorder variables .forty-seven-left[ ```scala def helloV1(user: User) = { val res1 = `funA(user)` val res2 = `funB(user)` // ... } ``` ] --- class: medium-code # Refactoring: reorder variables .forty-seven-left[ ```scala def helloV1(user: User) = { val `res1` = funA(user) val `res2` = funB(user) // ... } ``` ] --- class: medium-code # Refactoring: reorder variables .forty-seven-left[ ```scala def helloV1(user: User) = { val res1 = funA(user) val res2 = funB(user) // `...` } ``` ] --- class: medium-code # Refactoring: reorder variables .forty-seven-left[ ```scala def helloV1(user: User) = { `val res1 = funA(user)` val res2 = funB(user) // ... } ``` ### Is helloV1 equivalent to helloV2? ```scala def helloV2(user: User) = { val res2 = funB(user) `val res1 = funA(user)` // ... } ``` ] --- class: medium-code # Refactoring: reorder variables .forty-seven-left[ ```scala def helloV1(user: User) = { `val res1 = 10` val res2 = "" // ... } ``` ### Is helloV1 equivalent to helloV2? ```scala def helloV2(user: User) = { val res2 = "" `val res1 = 10` // ... } ``` ] .forty-seven-right[.center[ ### Yes, if they are FP functions ]] --- class: medium-code # Refactoring: reorder variables .forty-seven-left[ ```scala def helloV1(user: User) = { val res1 = db.delete(user.id) val res2 = db.insert(user) // ... } ``` ### Is helloV1 equivalent to helloV2? ```scala def helloV2(user: User) = { val res2 = db.insert(user) val res1 = db.delete(user.id) // ... } ``` ] .forty-seven-right[.center[ ### Yes, if they are FP functions
No, otherwise ]] .forty-seven-right[ ```scala helloV1(user) // user saved in db helloV2(user) // user deleted from db ``` ] --- class: medium-code # Refactoring: remove unused code .forty-seven-left[ ```scala def helloV1(user: User) = { funA(user) val res1 = funB(user) val res2 = funC(user) res1 } ``` ] --- class: medium-code # Refactoring: remove unused code .forty-seven-left[ ```scala def helloV1(user: User) = { `funA(user)` val res1 = funB(user) val res2 = funC(user) res1 } ``` ] --- class: medium-code # Refactoring: remove unused code .forty-seven-left[ ```scala def helloV1(user: User) = { funA(user) `val res1 = funB(user)` `val res2 = funC(user)` res1 } ``` ] --- class: medium-code # Refactoring: remove unused code .forty-seven-left[ ```scala def helloV1(user: User) = { funA(user) val res1 = funB(user) val res2 = funC(user) `res1` } ``` ] --- class: medium-code # Refactoring: remove unused code .forty-seven-left[ ```scala def helloV1(user: User) = { funA(user) val res1 = funB(user) val `res2` = funC(user) res1 } ``` ] --- class: medium-code # Refactoring: remove unused code .forty-seven-left[ ```scala def helloV1(user: User) = { `funA(user)` val res1 = funB(user) `val res2 = funC(user)` res1 } ``` ### Is helloV1 equivalent to helloV2? ```scala def helloV2(user: User) = funB(user) ``` ] --- class: medium-code # Refactoring: remove unused code .forty-seven-left[ ```scala def helloV1(user: User) = { funA(user) val res1 = funB(user) val res2 = funC(user) res1 } ``` ### Is helloV1 equivalent to helloV2? ```scala def helloV2(user: User) = funB(user) ``` ] .forty-seven-right[.center[ ### Yes, if they are FP functions ]] --- class: medium-code # Refactoring: remove unused code .sixty-two-left[ ```scala def helloV1(user: User) = { if(user.email.isEmpty) throw new InvalidUser("No email") val res1 = funB(user) val res2 = sendEmail(user) res1 } ``` ### Is helloV1 equivalent to helloV2? ```scala def helloV2(user: User) = funB(user) ``` ] .thirty-seven-right[.center[ ### Yes, if they are FP functions
No, otherwise ]] --- class: medium-code # Refactoring: remove unused code .sixty-two-left[ ```scala def helloV1(user: User) = { `if(user.email.isEmpty) throw new InvalidUser("No email")` val res1 = funB(user) val res2 = sendEmail(user) res1 } ``` ### Is helloV1 equivalent to helloV2? ```scala def helloV2(user: User) = funB(user) ``` ] .thirty-seven-right[.center[ ### Yes, if they are FP functions
No, otherwise ]] --- class: medium-code # Refactoring: remove unused code .sixty-two-left[ ```scala def helloV1(user: User) = { if(user.email.isEmpty) throw new InvalidUser("No email") val res1 = funB(user) val res2 = `sendEmail(user)` res1 } ``` ### Is helloV1 equivalent to helloV2? ```scala def helloV2(user: User) = funB(user) ``` ] .thirty-seven-right[.center[ ### Yes, if they are FP functions
No, otherwise ]] --- class: medium-code # Refactoring: de-duplicate .forty-seven-left[ ```scala def helloV1(user: User) = { val res1 = funA(user) // .. val res2 = funA(user) funB(res1, res2) } ``` ] --- class: medium-code # Refactoring: de-duplicate .forty-seven-left[ ```scala def helloV1(user: User) = { val res1 = `funA(user)` // .. val res2 = `funA(user)` funB(res1, res2) } ``` ] --- class: medium-code # Refactoring: de-duplicate .forty-seven-left[ ```scala def helloV1(user: User) = { val res1 = funA(user) // .. val res2 = funA(user) funB(res1, `res2`) } ``` ### Is helloV1 equivalent to helloV2? ```scala def helloV2(user: User) = { val res1 = funA(user) // .. funB(res1, `res1`) } ``` ] --- class: medium-code # Refactoring: de-duplicate .forty-seven-left[ ```scala def helloV1(user: User) = { val res1 = funA(user) // .. val res2 = funA(user) funB(res1, res2) } ``` ### Is helloV1 equivalent to helloV2? ```scala def helloV2(user: User) = { val res1 = funA(user) // .. funB(res1, res1) } ``` ] .forty-seven-right[.center[ ### Yes, if they are FP functions ]] --- class: medium-code # Refactoring: de-duplicate .forty-seven-left[ ```scala def helloV1(user: User) = { val res1 = funA(user) // .. val res2 = funA(user) funB(res1, res2) } ``` ### Is helloV1 equivalent to helloV2? ```scala def helloV2(user: User) = { val res1 = funA(user) // .. funB(res1, res1) } ``` ] .forty-seven-right[.center[ ### Yes, if they are FP functions
No, otherwise ]] .forty-seven-right[ ```scala def funA(user: User): BlogPost = BlogPost( id = `UUID.randomUUID()`, author = user.name, content = "", createdAt = `Instant.now()`, ) ``` ] --- class: medium-code # Refactoring: de-duplicate .forty-seven-left[ ```scala def helloV1(user: User) = { val res1 = funA(user) // .. val res2 = funA(user) funB(res1, res2) } ``` ### Is helloV1 equivalent to helloV2? ```scala def helloV2(user: User) = { val res1 = funA(user) // .. funB(res1, res1) } ``` ] .forty-seven-right[.center[ ### Yes, if they are FP functions
No, otherwise ]] .forty-seven-right[ ```scala def funA(user: User): Unit = charge(user.debitCard, 100) helloV1(user) // charge `$200` helloV2(user) // charge `$100` ``` ] --- class: medium-code # Refactoring: extract - inline .forty-seven-left[ ```scala def helloV1(user: User) = { funA(funB(user), funC(user)) } ``` ] --- class: medium-code # Refactoring: extract - inline .forty-seven-left[ ```scala def helloV1(user: User) = { `funA`(funB(user), funC(user)) } ``` ] --- class: medium-code # Refactoring: extract - inline .forty-seven-left[ ```scala def helloV1(user: User) = { funA(`funB(user)`, `funC(user)`) } ``` ] --- class: medium-code # Refactoring: extract - inline .forty-seven-left[ ```scala def helloV1(user: User) = { funA(`funB(user)`, `funC(user)`) } ``` ### Is helloV1 equivalent to helloV2? ```scala def helloV2(user: User) = { val res1 = `funB(user)` val res2 = `funC(user)` funA(res1, res2) } ``` ] --- class: medium-code # Refactoring: extract - inline .forty-seven-left[ ```scala def helloV1(user: User) = { funA(funB(user), funC(user)) } ``` ### Is helloV1 equivalent to helloV2? ```scala def helloV2(user: User) = { val res1 = funB(user) val res2 = funC(user) funA(res1, res2) } ``` ] -- .forty-seven-right[.center[ ### Yes, if they are FP functions
No, otherwise ]] --- class: medium-code # Refactoring: extract - inline .fifty-two-left[ ```scala import scala.concurrent.Future def createUser(email: String): Future[User] = httpClient.post("/user", email) def sendActivationLink(email: String):Future[Unit] = emailClient.send(email, generateLink(email)) ``` ] -- .fifty-two-left[ ```scala def newUserWorkflow(email: String): Future[Unit] = for { user <- createUser(email) _ <- sendActivationLink(email) } println(s"User created: $user") ``` ] --- class: medium-code # Refactoring: extract - inline .fifty-two-left[
```scala def newUserWorkflow(email: String): Future[Unit] = for { user <- createUser(email) _ <- sendActivationLink(email) } println(s"User created: $user") ``` ] .forty-seven-right[.center[
]] --- class: medium-code # Refactoring: extract - inline .fifty-two-left[
```scala def newUserWorkflow(email: String): Future[Unit] = for { user <- `createUser`(email) _ <- sendActivationLink(email) } println(s"User created: $user") ``` ] .forty-seven-right[.center[
]] --- class: medium-code # Refactoring: extract - inline .fifty-two-left[
```scala def newUserWorkflow(email: String): Future[Unit] = { val futureUser = createUser(email) val futureEmail = sendActivationLink(email) for { user <- futureUser _ <- futureEmail } println(s"User created: $user") } ``` ] --- class: medium-code # Refactoring: extract - inline .fifty-two-left[
```scala def newUserWorkflow(email: String): Future[Unit] = { val futureUser = `createUser`(email) val futureEmail = `sendActivationLink`(email) for { user <- futureUser _ <- futureEmail } println(s"User created: $user") } ``` ] --- class: medium-code # Refactoring: extract - inline .fifty-two-left[
```scala def newUserWorkflow(email: String): Future[Unit] = { val futureUser = `createUser`(email) val futureEmail = `sendActivationLink`(email) for { user <- futureUser _ <- futureEmail } println(s"User created: $user") } ``` ] .forty-seven-right[.center[
]] --- class: medium-code # Refactoring: extract - inline .fifty-two-left[
```scala def newUserWorkflow(email: String): Future[Unit] = { val futureUser = createUser(email) val futureEmail = sendActivationLink(email) for { user <- `futureUser` _ <- `futureEmail` } println(s"User created: $user") } ``` ] .forty-seven-right[.center[
]] --- class: medium-code # Refactoring: extract - inline .fifty-two-left[
```scala def newUserWorkflow(email: String): Future[Unit] = { val futureUser = createUser(email) val futureEmail = sendActivationLink(email) for { user <- `futureUser` _ <- `futureEmail` } println(s"User created: $user") } ``` ] .forty-seven-right[.center[
]] --- class: medium-code # Refactoring: extract - inline .fifty-two-left[
```scala def newUserWorkflow(email: String): Future[Unit] = { val futureUser = createUser(email) val futureEmail = sendActivationLink(email) for { user <- futureUser _ <- futureEmail } `println`(s"User created: $user") } ``` ] .forty-seven-right[.center[
]] --- class: medium-code # Refactoring: extract - inline .fifty-two-left[
```scala def newUserWorkflow(email: String): Future[Unit] = { val futureUser = createUser(email) val futureEmail = sendActivationLink(email) for { user <- `futureUser` _ <- futureEmail } println(s"User created: $user") } ``` ] .forty-seven-right[.center[
]] --- class: medium-code # Refactoring: extract - inline .fifty-two-left[
```scala def newUserWorkflow(email: String): Future[Unit] = { val futureUser = createUser(email) val futureEmail = sendActivationLink(email) for { user <- futureUser _ <- futureEmail } println(s"User created: $user") } ``` ] .forty-seven-right[.center[
]] --- class: medium-code # Refactoring: extract - inline .fifty-two-left[
```scala def newUserWorkflow(email: String): Future[Unit] = { val futureUser = createUser(email) val futureEmail = sendActivationLink(email) for { user <- futureUser _ <- futureEmail } println(s"User created: $user") } ``` ] .forty-seven-right[.center[
]] --- class: white background-image: url(../img/fp-tower/website-background.svg)
# .white[Summary]
## .white[Faster response to business requests] ## .white[Fewer bugs when releasing new features]