Skip to content

Commit 563bbb1

Browse files
committed
adjust code churn rate from 4% to 2.29%
1 parent 9838cd3 commit 563bbb1

1 file changed

Lines changed: 38 additions & 20 deletions

File tree

pkg/cost/cost.go

Lines changed: 38 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,29 @@ type Config struct {
8686
// Modification is cheaper because architecture is established and patterns are known.
8787
ModificationCostFactor float64
8888

89+
// WeeklyChurnRate is the probability that code becomes stale per week (default: 0.0229 = 2.29%)
90+
// Used to calculate rework percentage for open PRs based on time since last commit.
91+
// Formula: rework = 1 - (1 - weekly_rate)^weeks
92+
//
93+
// Default of 2.29% per week is based on empirical analysis across organizations:
94+
// - 60% of analyzed organizations had churn rates of 2.29%/week or lower
95+
// - 40% had higher churn rates
96+
// - Younger companies tend to have higher churn rates
97+
// - Results in 70% annual churn, reasonable for active development
98+
//
99+
// Examples from empirical data:
100+
// - 0.0018 (0.18%/week) - Adobe (mature, stable codebase)
101+
// - 0.0229 (2.29%/week) - 60th percentile (default)
102+
// - 0.0831 (8.31%/week) - Chainguard (young company, fast-moving)
103+
//
104+
// Recommended values for different project types:
105+
// - 0.010 (1.0%/week) → 41% annual churn - stable projects, mature codebases
106+
// - 0.0229 (2.29%/week) → 70% annual churn - typical active development (default, 60th percentile)
107+
// - 0.030 (3.0%/week) → 78% annual churn - fast-moving projects
108+
// - 0.040 (4.0%/week) → 88% annual churn - very high churn
109+
// - 0.080+ (8%+/week) → 99%+ annual churn - extremely fast-moving, younger companies
110+
WeeklyChurnRate float64
111+
89112
// COCOMO configuration for estimating code writing effort
90113
COCOMO cocomo.Config
91114
}
@@ -108,6 +131,7 @@ func DefaultConfig() Config {
108131
MaxCodeDrift: 90 * 24 * time.Hour, // 90 days
109132
ReviewInspectionRate: 275.0, // 275 LOC/hour (average of optimal 150-400 range)
110133
ModificationCostFactor: 0.4, // Modified code costs 40% of new code
134+
WeeklyChurnRate: 0.0229, // 2.29% per week (70% annual, 60th percentile empirical)
111135
COCOMO: cocomo.DefaultConfig(),
112136
}
113137
}
@@ -347,29 +371,21 @@ func Calculate(data PRData, cfg Config) Breakdown {
347371
// 2. Code Churn (Rework): Probability-based drift formula
348372
// Only calculated for open PRs - closed PRs won't need future updates
349373
//
350-
// Research basis:
351-
// - Windows Vista: 4-8% weekly code churn (Nagappan et al., Microsoft Research, 2008)
352-
// - Using 4% weekly baseline for active repositories
353-
//
354374
// Formula: Probability that a line becomes stale over time
355375
// drift = 1 - (1 - weeklyChurn)^(weeks)
356-
// drift = 1 - (0.96)^(days/7)
376+
// Default: weeklyChurn = 2.29% (0.0229) - empirical 60th percentile
357377
//
358378
// This models the cumulative probability that any given line in the PR needs rework
359-
// due to codebase changes. Unlike compounding formulas, this accounts for the fact
360-
// that the same code areas often change multiple times.
361-
//
362-
// Expected drift percentages:
363-
// - 3 days: ~2% drift
364-
// - 7 days: ~4% drift (matches weekly churn)
365-
// - 14 days: ~8% drift
366-
// - 30 days: ~16% drift
367-
// - 60 days: ~29% drift
368-
// - 90 days: ~41% drift (days capped at 90)
379+
// due to codebase changes. The weekly churn rate is configurable to match project velocity.
369380
//
370-
// Reference:
371-
// Nagappan, N., Murphy, B., & Basili, V. (2008). The Influence of Organizational
372-
// Structure on Software Quality. ACM/IEEE ICSE. DOI: 10.1145/1368088.1368160
381+
// Default (2.29% per week) drift percentages:
382+
// - 1 week: ~2.3% drift
383+
// - 2 weeks: ~4.5% drift
384+
// - 3 weeks: ~6.7% drift
385+
// - 1 month: ~8.9% drift
386+
// - 2 months: ~16.9% drift
387+
// - 3 months: ~24.3% drift
388+
// - 1 year: ~70% annual churn (empirical data from org analysis)
373389

374390
var reworkLOC int
375391
var codeChurnHours float64
@@ -414,9 +430,11 @@ func Calculate(data PRData, cfg Config) Breakdown {
414430
cappedDriftDays = maxDriftDays
415431
}
416432

417-
// Probability-based drift: 1 - (1 - 0.04)^(days/7)
433+
// Probability-based drift using configurable weekly churn rate
434+
// Formula: rework = 1 - (1 - weekly_rate)^weeks
435+
// Default: 1% per week → 41% annual churn
418436
weeks := cappedDriftDays / 7.0
419-
reworkPercentage = 1.0 - math.Pow(0.96, weeks)
437+
reworkPercentage = 1.0 - math.Pow(1.0-cfg.WeeklyChurnRate, weeks)
420438

421439
reworkLOC = int(float64(data.LinesAdded) * reworkPercentage)
422440

0 commit comments

Comments
 (0)