Posted by Zach Scott | February 29th, 2008
Overview
Extract method is probably the refactoring I use most frequently. It is covered in detail in The Refactoring Book, so I’ll leave out many of the details here that the book covers. I strongly encourage anyone interested in refactoring to read this book and keep it close by as a reference. The intent of this post and of this series of daily refactorings is to introduce a set of commonly used refactorings and to spark discussion about concrete real-world experience with them.
I want to get people thinking about the importance of refactoring and how it impacts how we think about upfront design vs just-in-time design and the ways in which refactoring can help us avoid over engineering.
What is Extract Method?
A refactoring that moves code out of a method by creating a new method and delegating to it.
To illustrate, let’s start with some code that could benefit from applying extract method:
public BigDecimal calculateTotal(List<item> items) {
// calculate sub total
BigDecimal subTotal = new BigDecimal("0.00");
for (Item i : items) {
subTotal.add(i.getAmount());
}
// calculate tax
BigDecimal taxRate = TaxRateHelper.getTaxRateForState(_user.getState());
BigDecimal taxAmount = subTotal.multiply(taxRate);
BigDecimal total = taxRate + taxAmount;
total.setScale(2, BigDecimal.ROUND_HALF_EVEN);
return total;
}
This code isn’t terrible by any stretch but it could be cleaned up by applying extract method. It’s easy to see that more than one thing is being done in this method. It is calculating a sub-total, tax amount, and total. Let’s extract these out as separate methods:
public BigDecimal calculateTotal(List<item> items) {
BigDecimal subTotal = calculateSubTotal(items);
BigDecimal taxAmount = calculateTaxAmount(subTotal);
BigDecimal total = taxRate + taxAmount;
total.setScale(2, BigDecimal.ROUND_HALF_EVEN);
return total;
}
public BigDecimal calculateSubTotal(List<item> items) {
BigDecimal subTotal = new BigDecimal("0.00");
for (Item i : items) {
subTotal.add(i.getAmount());
}
return subTotal;
}
public BigDecimal calculateTaxAmount(BigDecimal amount) {
BigDecimal taxRate = TaxRateHelper.getTaxRateForState(_customer.getState());
BigDecimal taxAmount = subTotal.multiply(taxRate);
return taxAmount;
}
What impact did this refactoring have? What were some of the benefits?
- The original calculateTotal method is more cohesive and sticks to doing one thing.
- The comments that described what the different sections of code were doing are no longer required because the method name clearly documents what the code does.
- Each of the methods calculateTaxAmount and calculateSubTotal are no longer tightly coupled to calculateTotal and can be called independently.
Of all the benefits provided perhaps the one that I think has the most impact is that extract method increases cohesiveness and decreases coupling. The benefits of having a loosely coupled, highly cohesive system are well-worth the effort it takes to perform extract method, especially considering most modern development tools (such as ReSharper, IntelliJ, and Eclipse) support this refactoring.
Can you see any other refactorings that this code could benefit from?
Tags: extract method, refactoring
Posted by Zach Scott | February 22nd, 2008
We just finished the series of planning sessions for Sprint2 which began on Feb 19th and runs for 4 weeks. We prioritized, decomposed, and estimated the work to be done and estimated how much could be accomplished in the 4 week period.
Planning
The planning sessions which include the scrum masters, product owners, and developers started after each of the product owners had their respective product backlogs prioritized. The team spent hours together decomposing the items on the product backlog into bite-sized, testable pieces that could be estimated. It was a challenging learning experience for everyone, mostly around effectively time-boxing discussions and knowing what to discuss and what can wait, however we came out of it relatively unscathed, and definitely wiser and more cohesive for the experience.
Estimating
After we had enough tasks broken down we gather the team of developers together to estimate each of the tasks. The purpose of this is to know how much the development team can be expected to produce in a sprint. The development team must be comfortable with the commitment and the product owners must be confident that the team will deliver on that commitment. We always plan more tasks than we think we can develop in one sprint so we don’t exhaust the available pool of work if the team performs better than anticipated.
The estimates are given in jellybeans rather than days or hours to avoid the myth that we can give such precise predictions about the work to be done. This is a myth that has been hurting development teams for far too long. Some things can be predicted very accurately such as, “How long does a direct flight from Saskatoon to San Francisco on a 737 take ( if such a flight existed)?” Others like, “How long with this football game take?”, can’t be predicted as easily. But it can be estimated.
What the heck is a jellybean?
A jellybean is an abstract measure of the size of a development task. To give the football analogy, we might consider that 1 quarter of a football game takes 1 jellybean. That means a whole football game takes 4 jellybeans. Although we don’t know exactly how long this is, it’s usefull nonetheless. For example we may want to know how long it will take to play a football game that consists of 10 quarters. That’s easy: 10 jellybeans.
Velocity is important when considering how much time it will take a team to produce one jellybean worth of work.
Velocity
Velocity is the measurement of how many jellybeans a team can accomplish in one sprint. It’s not something we can determine ahead of time with any confidence or accuracy, but rather something that is measured over time. I’m sure you have experienced being on a development project where you we’re given a task AND told how long it must take.
“Please have this TPS report generator completed by Friday.”
In football, the health of the team, injuries, penalties, weather, commercials, etc. all contribute to the velocity of the game. It may take 1 hour to accomplish 1 jellybean (1 quarter or 15 perfect minutes) of football. This is something we all understand and accept.
With a measured (and therefore predictable) velocity of 100 jellybeans, we would know that the team of developers has demonstrated over an extended period of time that it can accomplish 100 jellybeans worth of work in one 4 week sprint. Changes to the team size, nature of work, distractions in the office, advances in technology, professional development, etc. will all have an effect on this velocity.
Ideal Developer Days
There are several techniques available for estimating the size of each task, the least abstract being ideal developer days which is exactly how we did our estimation.
The team is asked to arrive at an agreement about the number of ideal developer daysa task will take by getting together in a room and playing estimation poker. Each team member comes up with an independent estimate. We all share our estimate with the team (on a card) at the same time, then we discuss discrepancies in estimates until the majority agree. At first it was uncomfortable for me, and I sensed for some other people as well, to look around at the number of people in the “meeting” and think about how much time we were wasting. However it became obvious that the benefits were outweighing the cost. The team left these estimating sessions with a shared commitment to these estimates and a better shared understanding of what work needed to be done.
Relative Task Size
An alternative to the ideal developer days technique is relative task size. This technique still uses estimation poker, but instead the team is asked to arrive at an agreement about the size of a new task relative to the size of some tasks that have already been accomplished.
Let’s return to the football analogy. Suppose the team is asked to estimate how big a period of NHL hockey is. Well they know that 1 quarter of football has been estimated at 1 jellybean and they have the option of estimating 1, 2, 3, 5, 8, 13 (you may have noticed that these are numbers in the Fibonacci sequence) There might be a debate about whether a quarter of hockey is 1 or 2 jellybeans, but the team eventually arrives at 1. This means that relatively speaking a quarter of football is about the same size as a period of hockey.
Summary
Although ideal developer days are more concrete and easy to understand than relative task size there are a number of drawbacks to the approach. I favor relative task size because improvements in the team dynamics, technologies, and practices are be reflected in velocity. With ideal developer days velocity does not reflect these improvements and we can mistakenly believe that the team is not getting better.
How does relative task size reflect technology and team improvements in velocity? Let’s look at a simple example:
Using ideal developer days we estimate the following: TASK1 - 1 jellybean, TASK2 - 4 jellybeans, TASK3 - 3 jellybeans. The total is 8 jellybeans. Let’s assume that we’ve measured the teams velocity over time and the team can accomplish 8 jellybeans of work in one sprint.
Now let’s step one year into the future. We have some new technology available that makes the same type of work very easy. Using ideal developer days as our estimation technique we estimate 3 similar tasks (these are not the same, but they are similar to TAKS1-3): TASK237 - 1, TASK238 - 1, TASK239 - 2. If the teams velocity hasn’t changed we will obviously have to add a few more tasks to top it up to 8 jellybeans. The problem with this is that it can appear that the team is holding at a velocity of 8 jellybeans, which does not account for the increase in performance. Had we used relative task size to estimate these instead, we would have seen that TASK238-239 receiving similar estimates to TASK1-2 regardless of the technology improvement and the additional tasks the team is able to accomplish would cause the measured velocity to increase.
Posted by Zach Scott | February 19th, 2008
Today marked the first day in a journey that is sure to take the Point2 Real Estate team to new heights. It was the first day that the entire real estate development team started sprinting. At 9:15 this morning we gathered as a team for our first kick-off meeting and listened as product owners described the vision and direction for each of their products and contextualized the work that is to be done over the next 4 weeks. It was a very exciting moment that was met with much anticipation. One in which we all took the first leap in our trek from where we are today towards the future Point2, a company that will no doubt be a force to reckon with. Although we have a clear idea about where we’re going and how to get there, we all know the course will change along the way, and so will the tools and practices, but we have to get started now and be ready for change. I call it Ready-Fire-Aim, Aim, Aim, Aim…
Much work has gone into planning for this first sprint. I especially want to thank the product owners that put so much time and energy into the monumental task of organizing and prioritizing all the features, tasks, bugs, and dreams that Point2 has ever had for it’s Real Estate products. Your efforts are greatly appreciated! I especially want to thank James Townley who went above and beyond and impressed us all. You inspire me with your tremendous work ethic and dedication.
Tags: NLS, Point2, real estate, scrum
Posted by Zach Scott | February 9th, 2008
I just added the OpenID plugin to my wordpress blog and set up an account at myopenid.com. It was very easy to setup and now I can login from my laptop using the client ssl certificate installed by myopenid.com. That means I never have to enter a password. This is very convenient. If I lose my laptop I just have to remember to go to myopenid.com and revoke the certificate.
Also, anybody with an OpenID account can post comments without first creating a username and password.
Tags: certificate, myopenid, openid, plugins, ssl
Posted by Zach Scott | February 3rd, 2008
It’s been a while since my last post. I’ve been super busy with all the changes happening around here, but things are settling down now. What’s new you ask? Scrum is rolling and it’s as great now as it was every other time I’ve been part of a true Agile/Scrum environment.We are just wrapping up a pilot sprint that was run for one of the products with a smaller team. They hit their jellybean targets — jellybeans are used to estimate how much work a team can accomplish — and are wrapping things up with a full integration and regression test cycle and preparing for the next sprint. The development team, which comprises the gamut of skill sets that are required to make a truly cross functional team, are crazy excited about this new way of working. For the first time they are involved in every step of the process from planning to QA and development and are encouraged to find ways to continuously improve. We’re all embracing change.We will be starting our first official sprint on Feb 19th which will include all Point2 NLS related products. The scrum area where our daily stand-ups happen is in the final stages of construction. By the 5th we will have 25 feet of whiteboard and cork-board space for collaborating and tracking the project, bookshelves for our technical library, and several tables on top of which will be the planned tasks and story cards. I’ll post pictures.
Tags: agile, change, NLS, Point2, scrum