Changing Software : Sprout Method
Tags: tdd, legacycode, software
Published: 2021-12-09 10:18:42


Hello Everybody :smile:
It is me again ; we continue talking about legacy code .
Today we are going to talk about the question _I Don't have much time and I have to Change It_ when working with legacy.
Let's go  :stuck_out_tongue_winking_eye:



## What it costs us 
We are not gonna lie , with testing developers are going to write much more additional code , yes with tests. Laura comes and say _i do not have much time and i have to write it_ :unamused: , and Paul responds I understand you but think about it , if you do not write it now and say **i will come later** , we all know that once the feature has been added no one is going to look back to that mess in the code . 

:wink:
Look at what M. Feathers says:
>The truth is, the work that you do to break dependencies and write tests for your changes is going to take some time, but in most cases, you are going to end up saving time—and a lot of frustration. When? Well, it depends on the project. In some cases, you might write tests for some code that you need to change, and it takes you two hours to do that. The change that you make afterward might take 15 minutes. When you look back on the experience, you might say, “I just wasted two hours—was it worth it?” It depends. You don’t know how long that work might have taken you if you hadn’t written the tests.


Paul : we can go now Laura ? :eyes:
Laura : Yes show me how to introduce this feature by being clean and cover it with test. :unamused:

![Let's go ](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0wmsbptrag5bv5ld1p16.gif)



Paul : I will introduce to you the **Sprout Method**
let's start :innocent:

Paul : small example , look here Laura 
```
public void postEntries(List entries) {
   for (Iterator it = entries.iterator(); it.hasNext(); ) {
     Entry entry = (Entry)it.next();
     entry.postDate();
   }
   transactionBundle.getListManager().add(entries);
}
```

Paul : If the next feature is **verify that none of the new entries are already in transactionBundle before we post their dates and add them**
I know you Laura :joy: , the most easy solution will be to write this 

Bad :broken_heart:
```
public void postEntries(List entries) {
    List entriesToAdd = new LinkedList();
    for (Iterator it = entries.iterator(); it.hasNext(); ) {
     Entry entry = (Entry)it.next();
     if (!transactionBundle.getListManager().hasEntry(entry) 
     {
        entry.postDate();
     entriesToAdd.add(entry);
     }
  }
  transactionBundle.getListManager().add(entriesToAdd);
}
```

Paul : But Laura why not cover your new code with test and make a separation with the old code and the new one ?

Laura : How ? show me :expressionless: 

Paul : The process is simple :innocent:


1. Identify where you need to make your code change.

2. If the change can be formulated as a single sequence of statements in one place in a method, write down a call for a new method that will do the work involved and then comment it out.

3. Determine what local variables you need from the source method, and make them arguments to the call.

4. Determine whether the sprouted method will need to return values to source method. If so, change the call so that its return value is assigned to a variable.

5. Develop the sprout method using test-driven development


Paul : i know it can be hard the first time , but look at how the code looks like when we follow this process

Paul : First we know we can create a new method for the requested feature and why not doing it with Test Driven Development .

Paul : So the result is like below , our new code for the new requested feature , and developed with TDD.


```
List uniqueEntries(List entries) {
   List result = new ArrayList();
   for (Iterator it = entries.iterator(); it.hasNext(); ) {
     Entry entry = (Entry)it.next();
     if (!transactionBundle.getListManager().hasEntry(entry) 
       {
            result.add(entry);
       }
   }
   return result;
}

```


Laura : But it is without value Here  :sleepy:

Paul : Yes , the interesting part is here , we can now use our newly created method in the place where we need it , in the old code .


```

public void postEntries(List entries) {
   List entriesToAdd = uniqueEntries(entries);
   for (Iterator it = entriesToAdd.iterator(); it.hasNext(); 
    ) {
        Entry entry = (Entry)it.next();
        entry.postDate();
     }
    transactionBundle.getListManager().add(entriesToAdd);
}

```


Laura : Hum , it seems pretty clean , and i can reuse the **uniqueEntries** method if there is a new feature that needs it :smirk: .

Paul : You start to understand :heart_eyes:

Paul : This is the Sprout Method.

Laura : Really , Thanks Paul . 

Paul : you're welcome but do not thank me . All this is from the book of Michael Feathers [Working Effectively With Legacy Code](https://www.amazon.fr/FEATHERS-WORK-EFFECT-LEG-CODE/dp/0131177052).



## Sprout Method : Disadvantages 
Like you have seen we separate the old from the new one , and here only the new code is under test , and this is the downside of the __Sprout Method__ . 

## Sprout Method : Advantages
What M. Feathers says :
>When you use Sprout Method, you are clearly separating new code from old code. Even if you can’t get the old code under test immediately, you can at least see your changes separately and have a clean interface between the new
code and the old code. You see all of the variables affected, and this can make it easier to determine whether the code is right in context.



Thanks for Reading :smiley:
[Email Me](devbyjesus@gmail.com)
[YouTube Channel](https://www.youtube.com/channel/UCVY7rjrKyh0j632okuSZXyg)
[Twitter](https://twitter.com/DevbyJesus)
[Instagram](https://www.instagram.com/devbyjesus/)

JESUS loves you :heart: