Introduction

Welcome to this course. The focus will be "Using Sprout and Wrap Techniques for Refactoring and to Expand Capabilities"! To start off, we will explore the sprout method, a technique that can, among other things, help us safely add new features to existing codebases.

This method is particularly useful when working with established codebases, where the risk of breaking existing functionality is high. By the end of this lesson, we'll understand how to use the sprout method to enhance our code's modularity and testability.

The Sprout Method Explained

The sprout method is a refactoring technique that involves creating new methods or classes to encapsulate additional functionality. This approach allows us to introduce new features without altering existing code, thereby minimizing the risk of breaking it.

By isolating new behavior in separate methods, we can improve the modularity of our code, making it easier to understand and maintain. The sprout method is particularly effective in scenarios where we need to expand capabilities while preserving the original behavior.

Step-by-Step Implementation

Let's walk through a step-by-step guide on how to apply the sprout method to add new features. We'll use a simple example to illustrate the process:

Scala
1import model.{Order, OrderItem} 2import java.time.LocalDateTime 3 4class OrderProcessor: 5 def processOrder(order: Order): (Boolean, Order) = 6 val totalAmount = order.items.map(item => item.price * item.quantity).sum 7 8 (true, order.copy( 9 processedAt = Some(LocalDateTime.now), 10 orderTotal = totalAmount 11 ))

Suppose we want to add a surcharge to the order total. Instead of modifying the existing processOrder method, we can create a new method called processOrderWithSurcharge:

Scala
1 def processOrderWithSurcharge(order: Order, surchargePercentage: BigDecimal): (Boolean, Order) = 2 if surchargePercentage < 0 then 3 throw IllegalArgumentException("Surcharge percentage cannot be negative") 4 5 val (_, processedOrder) = processOrder(order) 6 val surchargeAmount = processedOrder.orderTotal * (surchargePercentage / 100) 7 8 (true, processedOrder.copy( 9 processedAt = Some(LocalDateTime.now), 10 orderTotal = processedOrder.orderTotal + surchargeAmount, 11 surchargeAmount = surchargeAmount 12 ))

By creating a new method, we encapsulate the additional functionality without altering the existing processOrder method. This approach reduces the risk of introducing bugs into the original code.

Independent Testing of New Functionality

By isolating new features in separate methods, we can write targeted tests that focus solely on the new functionality.

Here's an example of how we might test the new surcharge functionality using ScalaTest:

Scala
1class OrderProcessorSpec extends AnyFunSpec: 2 describe("OrderProcessor"): 3 val processor = OrderProcessor() 4 5 it("should calculate total with surcharge correctly"): 6 // Arrange 7 val order = Order( 8 items = List( 9 OrderItem(price = BigDecimal(100.00), quantity = 1) 10 ) 11 ) 12 val surchargePercentage = BigDecimal(10) 13 14 // Act 15 val (success, processedOrder) = processor.processOrderWithSurcharge(order, surchargePercentage) 16 17 // Assert 18 assert(success) 19 assert(processedOrder.orderTotal == BigDecimal(110.00)) 20 assert(processedOrder.surchargeAmount == BigDecimal(10.00)) 21 assert(processedOrder.processedAt.isDefined)

This test verifies that the new surcharge functionality correctly calculates both the total amount and the surcharge, demonstrating how we can independently test sprouted functionality.

Key Takeaways and Preparation for Practice

In this lesson, we've explored the sprout method, a powerful technique for safely adding new features to existing codebases. By creating new methods to encapsulate additional functionality, we can minimize the risk of breaking existing code and improve modularity. We've also seen how to test new functionality independently to ensure its correctness.

As we move on to the practice exercises, we'll have the opportunity to apply these concepts and reinforce our understanding of the sprout method. Good luck, and enjoy the journey of enhancing your coding skills!

Sign up
Join the 1M+ learners on CodeSignal
Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal