# Sprouting in legacy code

## Sprouting in legacy code

### Sprout method

Sprout Method is a technique that one can use when one has to write a new feature in an existing code. The reason for Sprout method is that sometimes <mark style="background-color:blue;">you cannot write unit test for the code that you want to change but you can use TDD to write unit test for the new code</mark>, so that at least the new code would be tested!

#### Example

```csharp
public class TransactionGate{
    ...
    var orderItems = GetOrderItems();
    
    foreach(var orderItem in orderItems)
        transactionBundle.Add(orderItem);
    ...
}
```

**Now a new change is requested on the legacy code**

Now a new task demands to <mark style="background-color:blue;">filter out order items</mark> that are not already in the `TransactionBundle` object, we do it by **sprouting** out our code (function) from the existing code!

```csharp
public class TransactionGate{
  ...
  var orderItems = GetOrderItems();
  
  var uniqueOrderItems = GetUniqueOrderItems(orderItems);
  
  foreach(var orderItem in uniqueOrderItems)
    transactionBundle.Add(orderItem);     
}

public List<OrderItem> GetUniqueOrderItems(List<OrderItem> orderItems){
    ...
}
```

We created a method `GetUniqueOrderItems` with one parameter; a list of order items. Now we can initiate class and write tests for new code. It is recommended to use Test Driven Development to develop a Sprout method itself.

### Sprout Class

When you must extend a large method with a sequence of instructions and the class is heavily dependent on different objects, it can be better to extract the sequence of instructions into a new class method.

This is <mark style="background-color:blue;">more ideal when we want to make sure that Single Responsibility Principle</mark> is not violated anywhere

#### Example

Below we have an existing code/legacy code to create an order. Now we have a new requirement saying that when creating an order, <mark style="background-color:blue;">We also need to add a VAT amount</mark> (a type of tax) if the order is from a non-individual, a company.

**Existing code**

```csharp
public class OrdersFacade{
  private IExternalCustomerApiService customerApiService;
  private IOrderRepository orderRepository;
  ...
       
  public OrdersFacade(
    IExternalCustomerApiService customerApiService,
    IOrderRepository orderRepository,
    ...
    )
    {
    this.customerApiService = customerApiService;
    this.orderRepository = orderRepository;
    ...
    }
  
  public bool CreateOrder(){
    ...
     
    var customerInfoInJson = customerApiService.GetCustomerInfo(customerId);
    var customerInfo = JSonConvert.Serialize(customerInfoInJson);
    order.CustomerName = customerInfo.Name;
    
    orderRepository.Save(order);
    return true;
    }
}
```

**Step 1:** Let’s develop a completely separated class, preferably using TDD.

```csharp
public class OrderVatCalculator{
  public Order AddVatIfNotCompany(Order order, bool isCompany)
  {
    decimal vat = 1.21;
    if(!isCompany){
      order.Price = order.Price * vat;
    }
  }
}
```

**Step 2:** Let’s initialize an object of Sprout class in existing code, pass parameters into its method, and let a method do the required expression.

```csharp
public class OrdersFacade{
  private IExternalCustomerApiService customerApiService;
  private IOrderRepository orderRepository;
  ...
       
  public OrdersFacade(
    IExternalCustomerApiService customerApiService,
    IOrderRepository orderRepository,
    ...
    )
    {
    this.customerApiService = customerApiService;
    this.orderRepository = orderRepository;
    ...
    }
  
  public bool CreateOrder(){
    ...
     
    var customerInfoInJson = customerApiService.GetCustomerInfo(customerId);
    var customerInfo = JSonConvert.Serialize(customerInfoInJson);
    order.CustomerName = customerInfo.Name;
    
    var orderVatCalculator = new OrderVatCalculator();
    
    orderVatCalculator.AddVatIfCompany(order, customerInfo.IsCompany);
    
    orderRepository.Save(order);
    return true;
    }
}
```

{% hint style="info" %}
The new piece of instructions is covered by tests and has only one responsibility. It is very easy to read and maintain!
{% endhint %}

### A good reading resource:

Working Effectively with Legacy Code, by Michael Feathers, [EBook](https://www.oreilly.com/library/view/working-effectively-with/0131177052/)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://raviram.gitbook.io/tdd/legacy-code/sprouting-in-legacy-code.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
