Why Failing To Meet All Sprint Tasks Isn’T Necessarily Bad

The Pressure of Sprint Commitments

Software development teams often work in sprint cycles, committing to complete a certain set of tasks within the sprint timeframe, usually 2-4 weeks. However, unexpected obstacles frequently arise that prevent teams from meeting all sprint goals. This creates tension between the pressure to meet sprint commitments and the reality of unpredictable impediments.

Common sprint disruptions include:

  • Emergency production bugs needing immediate fixation
  • Sudden change in product requirements from stakeholders
  • Blockers within the codebase that only surface mid-sprint
  • Loss of team members due to illness or other obligations

While disruptions are understandable, they can demoralize teams who put forth best efforts but still fall short of sprint commitments. However, as explored in the next sections, missing some sprint tasks does not necessarily indicate failure.

Failing to Meet Commitments Isn’t Always Bad

At first glance, missed sprint tasks signal poor execution or planning. However, in many cases, missed sprint goals represent progress towards more important outcomes than simple task completion. As one example, consider a sprint task to add a new feature to an existing code module. While working on the code, the developer discovers better ways to structure the overall module to simplify future features. However, these structural improvements cause the initial feature task to spill out of the current sprint.

While the specific sprint commitment was missed, the time was well spent improving system architecture for the long-term. Had the developer stubbornly powered through and completed the feature without any refactoring, future features would become increasingly painful to add. Prioritizing code quality over sprint tasks can thus align with optimal outcomes.


// Code module before refactor

class PaymentProcessor {

  public function chargeCreditCard($amount) {
    // implementation
  }

  public function chargePaypal($amount) {
    // implementation
  }

}

// Mid-sprint rewrite to enable new features  

interface PaymentGateway {
  public function charge($amount);
}

class StripeGateway implements PaymentGateway {
  public function charge($amount) {
    // implementation
  } 
}

class PaypalGateway implements PaymentGateway  {
  public function charge($amount){
     // implementation
  }
}

class PaymentProcessor {

  protected $gateways = [];

  public function addGateway(PaymentGateway $gateway) {
    $this->gateways[] = $gateway;
  }

  public function charge($amount) {
    // delegate to added gateways
  }

}


In the above hypothetical example, rewriting the PaymentProcessor module from scratch enables easily adding new payment gateways without touching existing code. This positions the codebase for future features, but could mean descending unfinished stories in the current sprint.

Focusing on Value Over Task Completion

Rather than judging sprint success purely by completion of committed tasks, teams should prioritize delivering value and progress through working software. Missed sprint goals may be acceptable if they enable higher-value outcomes. Some indicators that teams are on the right track despite missed tasks:

  • Casting a wider technical vision via spikes/R&D
  • Paying off technical debt through fixes and refactors
  • Discovering smarter solutions through experimentation

For example, an ecommerce site sprint goal to launch a new checkout flow might spill over into the next sprint. However, the team realized a lighter-weight iteration of the current checkout would better validate assumptions before rebuilding from scratch. This sprint pivot delays the original task but pursues a smarter approach centered on value rather than speed.


// Mid-sprint change of course

// Original task 
class StripeCheckoutService {
  // complex logic around sessions, payment intent, etc
}

// Temporary iteration to validate assumptions
class BasicCheckoutService {

  public function createOrder($data) {
    
    $order = Order::create($data);

    return [
        'clientSecret' => $order->stripe_payment_intent_id
    ];
  }

}  

By staying grounded in delivering value over sprint task completion, teams give themselves space for crucial learning and adjustment.

Learning Key Lessons from Missed Sprints

While frequent missed sprints should trigger concerns, the occasional descend is expected and even beneficial. By reflecting on why sprint goals were missed and codifying takeaways, teams compound progress.

Some examples of key lessons teams can extract:

  • Technical Spikes: A mid-sprint spike on a new technology missed its delivery date but equipped the team to evaluate technology fit
  • Team Workflow Issues: Task dependencies and handoffs led to bottlenecks that stalled feature progress
  • Unforeseen Complexity: New insights into end-user needs requires more design iteration than expected

To prevent lessons learned from being forgotten, teams should memorialize major takeaways through team wiki pages, updated documentation, or append team process handbooks. This focuses the team to continuously self-reflect and get smarter.


// Example sprint retro action item

Title: Switch to Pull Request Reviews 

Type: Process Improvement

Description: 
By reviewing GitHub pull requests rather than local feature branches, we can catch integration issues earlier while better distributing knowledge across the team.  

Action Item:
- Adjust team working agreements 
- Set up GitHub branch protections
- Schedule pull request training session

While failing to fully complete committed sprint tasks is always disappointing, perfect execution is an unrealistic goal given shifting priorities and unknowns. Rather than obsessing over sprint failure, teams should view missed goals as opportunities to build shared knowledge.

Leave a Reply

Your email address will not be published. Required fields are marked *