💰 Developer Cookbook - FASE 7: Análisis de Impacto Financiero
Calcular ROI, optimizar costos y gestionar technical debt con criterio de negocio
📚 Tabla de Contenidos
- Receta 7.10: ROI de Decisiones Técnicas
- Receta 7.11: Cost Optimization en Cloud
- Receta 7.12: Technical Debt vs Velocidad
Receta 7.10: ROI de Decisiones Técnicas
¿Qué es? Calcular el Return on Investment de decisiones de ingeniería para justificar tiempo/recursos.
Formula básica:
ROI = (Beneficio - Costo) / Costo × 100%
Ejemplo práctico:
from dataclasses import dataclass
from typing import List, Optional
@dataclass
class TechnicalInvestment:
"""Modelo para calcular ROI de inversiones técnicas"""
name: str
one_time_cost: float # Costo inicial ($)
monthly_cost: float # Costo recurrente ($/mes)
time_to_implement: int # Horas
engineer_hourly_rate: float # $/hora
# Benefits
time_saved_per_month: float # Horas ahorradas/mes
revenue_impact: float # $ adicionales/mes
cost_reduction: float # $ ahorrados/mes
# Qualitative
risk_reduction: str # Low/Medium/High
developer_happiness: str # Low/Medium/High
def calculate_implementation_cost(self) -> float:
"""Costo total de implementación"""
labor_cost = self.time_to_implement * self.engineer_hourly_rate
return self.one_time_cost + labor_cost
def calculate_monthly_benefit(self) -> float:
"""Beneficio mensual total"""
# Time saved converted to $
time_benefit = self.time_saved_per_month * self.engineer_hourly_rate
return time_benefit + self.revenue_impact + self.cost_reduction
def calculate_monthly_net(self) -> float:
"""Beneficio neto mensual (benefit - monthly cost)"""
return self.calculate_monthly_benefit() - self.monthly_cost
def calculate_payback_period(self) -> float:
"""Meses hasta recuperar inversión"""
monthly_net = self.calculate_monthly_net()
if monthly_net <= 0:
return float('inf') # Nunca se paga
implementation_cost = self.calculate_implementation_cost()
return implementation_cost / monthly_net
def calculate_roi_1_year(self) -> float:
"""ROI after 1 año"""
implementation_cost = self.calculate_implementation_cost()
annual_benefit = self.calculate_monthly_net() * 12
if implementation_cost == 0:
return float('inf')
return ((annual_benefit - implementation_cost) / implementation_cost) * 100
def print_analysis(self):
"""Imprimir análisis completo"""
print("\n" + "=" * 70)
print(f"💰 ROI ANALYSIS: {self.name}")
print("=" * 70)
impl_cost = self.calculate_implementation_cost()
monthly_benefit = self.calculate_monthly_benefit()
monthly_net = self.calculate_monthly_net()
payback = self.calculate_payback_period()
roi_1y = self.calculate_roi_1_year()
print(f"\n📊 COSTS:")
print(f" Implementation: ${impl_cost:,.0f}")
print(f" - One-time costs: ${self.one_time_cost:,.0f}")
print(f" - Labor ({self.time_to_implement}h × ${self.engineer_hourly_rate}/h): "
f"${self.time_to_implement * self.engineer_hourly_rate:,.0f}")
print(f" Monthly recurring: ${self.monthly_cost:,.0f}/month")
print(f"\n📈 BENEFITS:")
print(f" Monthly benefit: ${monthly_benefit:,.0f}/month")
if self.time_saved_per_month > 0:
print(f" - Time saved: {self.time_saved_per_month}h × ${self.engineer_hourly_rate}/h "
f"= ${self.time_saved_per_month * self.engineer_hourly_rate:,.0f}")
if self.revenue_impact > 0:
print(f" - Revenue impact: ${self.revenue_impact:,.0f}")
if self.cost_reduction > 0:
print(f" - Cost reduction: ${self.cost_reduction:,.0f}")
print(f"\n💵 NET:")
print(f" Monthly net: ${monthly_net:,.0f}/month")
print(f" Annual net: ${monthly_net * 12:,.0f}/year")
print(f"\n⏱️ PAYBACK:")
if payback == float('inf'):
print(f" ❌ NEVER (monthly cost > benefits)")
elif payback < 1:
print(f" ✅ {payback:.1f} months (EXCELLENT)")
elif payback < 6:
print(f" ✅ {payback:.1f} months (GOOD)")
elif payback < 12:
print(f" ⚠️ {payback:.1f} months (OK)")
else:
print(f" ❌ {payback:.1f} months (TOO LONG)")
print(f"\n📊 ROI (1 year):")
if roi_1y == float('inf'):
print(f" ✅ ∞% (no implementation cost)")
elif roi_1y > 200:
print(f" ✅ {roi_1y:.0f}% (EXCELLENT)")
elif roi_1y > 100:
print(f" ✅ {roi_1y:.0f}% (GOOD)")
elif roi_1y > 0:
print(f" ⚠️ {roi_1y:.0f}% (MARGINAL)")
else:
print(f" ❌ {roi_1y:.0f}% (NEGATIVE)")
print(f"\n🎯 QUALITATIVE:")
print(f" Risk reduction: {self.risk_reduction}")
print(f" Developer happiness: {self.developer_happiness}")
print(f"\n🏆 RECOMMENDATION:")
if payback < 6 and roi_1y > 100:
print(f" ✅ STRONGLY RECOMMEND - Great financial return")
elif payback < 12 and roi_1y > 50:
print(f" ✅ RECOMMEND - Solid investment")
elif roi_1y > 0:
print(f" ⚠️ CONSIDER - Positive but marginal")
else:
print(f" ❌ DO NOT INVEST - Negative return")
print("=" * 70)
# Ejemplo 1: Implementar CI/CD pipeline
ci_cd = TechnicalInvestment(
name="CI/CD Pipeline (GitHub Actions)",
one_time_cost=0, # GitHub Actions es gratis para public repos
monthly_cost=50, # $50/mes for private repos
time_to_implement=40, # 1 semana de trabajo
engineer_hourly_rate=100,
# Benefits
time_saved_per_month=20, # 20h/mes que gastaban en deploys manuales
revenue_impact=0,
cost_reduction=0,
risk_reduction="High", # Menos bugs en producción
developer_happiness="High" # Developers felices con automation
)
ci_cd.print_analysis()
# Ejemplo 2: Migrate to serverless
serverless = TechnicalInvestment(
name="Migrate to AWS Lambda (Serverless)",
one_time_cost=0,
monthly_cost=200, # Lambda costs
time_to_implement=160, # 1 mes de migration
engineer_hourly_rate=100,
# Benefits
time_saved_per_month=5, # Menos time managing servers
revenue_impact=500, # Better performance → más conversiones
cost_reduction=1500, # Ahorro vs EC2 instances ($1700/mes → $200/mes)
risk_reduction="Medium",
developer_happiness="Medium"
)
serverless.print_analysis()
# Ejemplo 3: Refactor monolith to microservices
microservices = TechnicalInvestment(
name="Refactor to Microservices",
one_time_cost=10000, # Training, consulting
monthly_cost=500, # Extra infrastructure costs
time_to_implement=800, # 5 meses de trabajo (2 engineers)
engineer_hourly_rate=100,
# Benefits
time_saved_per_month=0, # Actually might be SLOWER initially
revenue_impact=0, # No direct revenue impact
cost_reduction=0, # Costs increase
risk_reduction="Low", # More complexity = more risk
developer_happiness="Medium" # Some like it, some don't
)
microservices.print_analysis()
Comparar múltiples opciones:
class InvestmentComparator:
"""Comparar múltiples inversiones"""
def __init__(self):
self.investments = []
def add_investment(self, investment: TechnicalInvestment):
self.investments.append(investment)
def compare(self):
"""Comparar y rankear inversiones"""
# Calcular métricas para cada inversión
results = []
for inv in self.investments:
results.append({
'name': inv.name,
'payback_months': inv.calculate_payback_period(),
'roi_1y': inv.calculate_roi_1_year(),
'monthly_net': inv.calculate_monthly_net(),
'impl_cost': inv.calculate_implementation_cost()
})
# Sort by ROI
results_sorted = sorted(results, key=lambda x: x['roi_1y'], reverse=True)
print("\n" + "=" * 100)
print("📊 INVESTMENT COMPARISON")
print("=" * 100)
print(f"\n{'Investment':<40} {'Impl Cost':<15} {'Monthly Net':<15} {'Payback':<15} {'ROI (1y)':<15}")
print("-" * 100)
for r in results_sorted:
payback_str = f"{r['payback_months']:.1f}m" if r['payback_months'] != float('inf') else "Never"
roi_str = f"{r['roi_1y']:.0f}%" if r['roi_1y'] != float('inf') else "∞%"
print(f"{r['name']:<40} ${r['impl_cost']:<14,.0f} ${r['monthly_net']:<14,.0f} {payback_str:<15} {roi_str:<15}")
print("\n" + "=" * 100)
# Recommendation
best = results_sorted[0]
print(f"\n🏆 BEST INVESTMENT: {best['name']}")
print(f" ROI: {best['roi_1y']:.0f}% | Payback: {best['payback_months']:.1f} months")
# Comparar las 3 opciones
comparator = InvestmentComparator()
comparator.add_investment(ci_cd)
comparator.add_investment(serverless)
comparator.add_investment(microservices)
comparator.compare()
Receta 7.11: Cost Optimization en Cloud
¿Qué es? Reducir costos de cloud sin sacrificar performance o reliability.
Estrategias de optimización:
class CloudCostOptimizer:
"""Framework para optimizar costos de AWS/GCP/Azure"""
@staticmethod
def compute_optimization():
"""Optimizar costos de compute (EC2, Compute Engine, VMs)"""
strategies = """
💻 COMPUTE OPTIMIZATION
=======================
1. RIGHT-SIZING
❌ Problema: Instances sobre-provisionadas
✅ Fix: Analyze CloudWatch metrics, downsize
💰 Savings: 20-40%
# AWS CLI para ver utilization
aws cloudwatch get-metric-statistics \\
--namespace AWS/EC2 \\
--metric-name CPUUtilization \\
--dimensions Name=InstanceId,Value=i-1234567890abcdef0 \\
--start-time 2024-01-01T00:00:00Z \\
--end-time 2024-01-07T23:59:59Z \\
--period 3600 \\
--statistics Average
2. SPOT INSTANCES
❌ Problema: On-demand instances 24/7
✅ Fix: Use Spot for batch jobs, dev/test
💰 Savings: 50-90% vs on-demand
When to use Spot:
• Batch processing
• Data analysis
• CI/CD jobs
• Stateless web servers (with auto-scaling)
When NOT to use Spot:
• Databases
• Stateful services
• Jobs that can't tolerate interruption
3. RESERVED INSTANCES / SAVINGS PLANS
❌ Problema: Paying on-demand for baseline capacity
✅ Fix: Commit to 1-3 years for predictable workloads
💰 Savings: 30-70% vs on-demand
Decision matrix:
• 1-year, no upfront: 20% discount, low commitment
• 1-year, all upfront: 30% discount, max savings
• 3-year, all upfront: 50-70% discount, long commitment
4. AUTO-SCALING
❌ Problema: Same capacity 24/7
✅ Fix: Scale down at night, weekends
💰 Savings: 30-50%
Example schedule:
• Mon-Fri 9am-6pm: 10 instances
• Mon-Fri 6pm-9am: 3 instances
• Weekends: 2 instances
5. SERVERLESS
❌ Problema: Servers idle 90% of time
✅ Fix: Lambda/Cloud Functions for sporadic workloads
💰 Savings: 70-90% for low traffic
Good candidates for serverless:
• APIs with <1000 req/day
• Cron jobs
• Event-driven processes
• Image processing
"""
print(strategies)
@staticmethod
def storage_optimization():
"""Optimizar costos de storage"""
strategies = """
💾 STORAGE OPTIMIZATION
=======================
1. S3 STORAGE CLASSES / LIFECYCLE POLICIES
❌ Problema: Todo en S3 Standard
✅ Fix: Move old data to cheaper tiers
💰 Savings: 40-95%
S3 Storage Class Pricing (per GB/month):
• S3 Standard: $0.023
• S3 Intelligent-Tiering: $0.023 (auto-moves)
• S3 Standard-IA: $0.0125 (50% cheaper)
• S3 Glacier Instant: $0.004 (83% cheaper)
• S3 Glacier Flexible: $0.0036 (84% cheaper)
• S3 Glacier Deep Archive: $0.00099 (96% cheaper)
Lifecycle policy example:
• Day 0-30: S3 Standard
• Day 31-90: S3 Standard-IA
• Day 91-365: S3 Glacier Instant
• Day 365+: S3 Glacier Deep Archive
2. DELETE UNUSED DATA
❌ Problema: Storing logs forever
✅ Fix: Retention policies
💰 Savings: 30-50%
What to delete:
• Logs >90 days (unless compliance requirement)
• Old backups (keep last 30 days)
• Test/dev data
• Orphaned snapshots
• Old AMIs/images
3. COMPRESS DATA
❌ Problema: Storing uncompressed files
✅ Fix: gzip/brotli compression
💰 Savings: 60-80% on storage
# Compress before upload
gzip large_file.json # Compresses to large_file.json.gz
aws s3 cp large_file.json.gz s3://bucket/ --content-encoding gzip
4. DEDUPLICATE
❌ Problema: Duplicate files across environments
✅ Fix: Use object hashing
💰 Savings: 20-40%
"""
print(strategies)
@staticmethod
def database_optimization():
"""Optimizar costos de databases"""
strategies = """
🗄️ DATABASE OPTIMIZATION
=========================
1. RIGHT-SIZE DB INSTANCES
❌ Problema: db.m5.4xlarge for 100 queries/day
✅ Fix: Start small, monitor, scale when needed
💰 Savings: 50-80%
RDS instance types:
• db.t3.micro: $0.017/hr ($12/month) - Dev/test
• db.t3.small: $0.034/hr ($25/month) - Small apps
• db.m5.large: $0.192/hr ($140/month) - Production
• db.m5.4xlarge: $1.536/hr ($1,120/month) - High traffic
2. RESERVED INSTANCES
❌ Problema: On-demand RDS 24/7
✅ Fix: 1-year reserved for prod databases
💰 Savings: 35-65%
3. AURORA SERVERLESS v2
❌ Problema: DB idle at night but paying for full capacity
✅ Fix: Aurora auto-scales to 0.5 ACU minimum
💰 Savings: 70-90% for variable workloads
Cost comparison (1 month):
• RDS MySQL db.r5.large: $243/month
• Aurora Serverless v2 (0.5-2 ACU avg): $50-80/month
4. READ REPLICAS vs CACHING
❌ Problema: Creating read replicas for everything
✅ Fix: Use Redis/ElastiCache first
💰 Savings: Read replica = $200/mo, Redis = $15/mo
5. QUERY OPTIMIZATION
❌ Problema: Slow queries → need bigger instance
✅ Fix: Add indexes, optimize queries
💰 Savings: Avoid scaling up (50-80%)
-- Find slow queries
SELECT query, calls, mean_exec_time
FROM pg_stat_statements
ORDER BY mean_exec_time DESC
LIMIT 10;
"""
print(strategies)
@staticmethod
def network_optimization():
"""Optimizar costos de networking"""
strategies = """
🌐 NETWORK OPTIMIZATION
=======================
1. DATA TRANSFER COSTS
❌ Problema: Transferring TBs between regions
✅ Fix: Keep data in same region
💰 Savings: $0.02-0.09/GB
AWS Data Transfer Pricing:
• Same AZ: FREE
• Between AZs (same region): $0.01/GB
• Between regions: $0.02/GB
• To internet: $0.09/GB (first 10TB)
2. CLOUDFRONT / CDN
❌ Problema: Serving static assets from origin
✅ Fix: Use CloudFront
💰 Savings: 40-60% on bandwidth
• S3 → Internet: $0.09/GB
• CloudFront → Internet: $0.085/GB + caching
Plus:
• Reduced origin load
• Faster for users
• Less bandwidth from origin
3. VPC ENDPOINTS
❌ Problema: Traffic to S3/DynamoDB via NAT Gateway
✅ Fix: VPC Endpoints (free!)
💰 Savings: $0.045/GB + $0.045/hr NAT cost
4. COMPRESSION
❌ Problema: Transferring uncompressed responses
✅ Fix: gzip compression
💰 Savings: 70-80% on bandwidth
# Enable in nginx
gzip on;
gzip_types text/plain text/css application/json;
"""
print(strategies)
@staticmethod
def print_all():
print("\n" + "💰 " * 20)
print("CLOUD COST OPTIMIZATION STRATEGIES")
print("💰 " * 20 + "\n")
CloudCostOptimizer.compute_optimization()
print("\n" + "-" * 80 + "\n")
CloudCostOptimizer.storage_optimization()
print("\n" + "-" * 80 + "\n")
CloudCostOptimizer.database_optimization()
print("\n" + "-" * 80 + "\n")
CloudCostOptimizer.network_optimization()
CloudCostOptimizer.print_all()
Cost Monitoring:
class CloudCostMonitor:
"""Monitorear y alertar sobre costos"""
def __init__(self, monthly_budget: float):
self.monthly_budget = monthly_budget
self.current_spend = 0
self.daily_average = 0
def check_burn_rate(self, days_in_month: int, current_day: int):
"""Verificar si estamos en budget"""
expected_spend = (self.monthly_budget / days_in_month) * current_day
projected_spend = (self.current_spend / current_day) * days_in_month
print("\n📊 BUDGET STATUS")
print("=" * 60)
print(f"Monthly Budget: ${self.monthly_budget:,.2f}")
print(f"Current Spend: ${self.current_spend:,.2f} (Day {current_day}/{days_in_month})")
print(f"Expected Spend: ${expected_spend:,.2f}")
print(f"Projected Month-End: ${projected_spend:,.2f}")
variance = projected_spend - self.monthly_budget
variance_pct = (variance / self.monthly_budget) * 100
if variance > 0:
print(f"\n⚠️ OVER BUDGET: ${variance:,.2f} ({variance_pct:+.1f}%)")
print(f" Action needed: Reduce daily spend to ${self.monthly_budget/days_in_month:.2f}")
else:
print(f"\n✅ ON TRACK: ${abs(variance):,.2f} under budget ({variance_pct:+.1f}%)")
print("=" * 60)
return projected_spend <= self.monthly_budget
def cost_anomaly_detection(self, historical_daily_costs: list):
"""Detectar anomalías en costos"""
import numpy as np
mean = np.mean(historical_daily_costs)
std = np.std(historical_daily_costs)
today_cost = historical_daily_costs[-1]
# Si hoy está >2 standard deviations, es anomalía
if abs(today_cost - mean) > 2 * std:
print(f"\n🚨 COST ANOMALY DETECTED!")
print(f" Today: ${today_cost:.2f}")
print(f" Historical average: ${mean:.2f}")
print(f" Deviation: {((today_cost - mean) / mean * 100):+.1f}%")
# Investigar
print(f"\n🔍 Investigate:")
print(f" • Check for new resources")
print(f" • Review data transfer spikes")
print(f" • Look for runaway processes")
return True
return False
# Ejemplo
monitor = CloudCostMonitor(monthly_budget=5000)
monitor.current_spend = 2100
monitor.check_burn_rate(days_in_month=30, current_day=15)
# Simular daily costs
daily_costs = [150, 160, 155, 158, 162, 157, 159, 161, 158, 160,
165, 163, 159, 161, 450] # Spike on day 15!
monitor.cost_anomaly_detection(daily_costs)
Receta 7.12: Technical Debt vs Velocidad
¿Qué es? Balance entre “ship fast” y “mantener código limpio”. Todo technical debt tiene un interés que pagas después.
Framework de decisión:
from enum import Enum
from dataclasses import dataclass
from typing import Optional
class DebtSeverity(Enum):
"""Severidad del technical debt"""
LOW = 1 # Cosmético, no afecta funcionalidad
MEDIUM = 2 # Afecta velocity del equipo
HIGH = 3 # Riesgo de bugs o seguridad
CRITICAL = 4 # Blocking, debe arreglarse YA
@dataclass
class TechnicalDebt:
"""Modelo de technical debt"""
name: str
description: str
severity: DebtSeverity
interest_rate: str # Cómo crece el costo over time
# Costs
time_to_fix_now: int # Horas para arreglar ahora
time_to_fix_later: int # Horas si esperamos (acumula interés)
velocity_impact: int # % de slowdown del equipo
bug_risk: str # Low/Medium/High
# Context
affected_features: list
workaround_exists: bool
blocking_new_work: bool
# Catálogo de technical debt común
debt_examples = [
TechnicalDebt(
name="No tests en payment service",
description="Payment service tiene 0% test coverage",
severity=DebtSeverity.HIGH,
interest_rate="Cada bug en prod = $10k+ lost revenue",
time_to_fix_now=40,
time_to_fix_later=80, # Harder to test legacy code
velocity_impact=0, # No slowdown... yet
bug_risk="High",
affected_features=["checkout", "subscriptions", "refunds"],
workaround_exists=False,
blocking_new_work=True # Can't add features without tests
),
TechnicalDebt(
name="Hardcoded config values",
description="DB credentials, API keys en código",
severity=DebtSeverity.CRITICAL,
interest_rate="Security incident could cost $100k+",
time_to_fix_now=8,
time_to_fix_later=8, # Same effort later
velocity_impact=5, # Small slowdown (cada deploy requiere edit)
bug_risk="High",
affected_features=["all"],
workaround_exists=False,
blocking_new_work=False
),
TechnicalDebt(
name="Inconsistent naming conventions",
description="snake_case, camelCase, PascalCase mezclados",
severity=DebtSeverity.LOW,
interest_rate="Minor confusion for new devs",
time_to_fix_now=20,
time_to_fix_later=40, # More code = more renaming
velocity_impact=5, # Small slowdown
bug_risk="Low",
affected_features=["all"],
workaround_exists=True, # Style guide helps
blocking_new_work=False
),
TechnicalDebt(
name="Monolithic codebase",
description="1 repo, 100k+ lines, 1 deployment",
severity=DebtSeverity.MEDIUM,
interest_rate="Slows down all feature development",
time_to_fix_now=800, # 5 months to split
time_to_fix_later=1600, # Harder cuando hay más code
velocity_impact=30, # Big slowdown
bug_risk="Medium",
affected_features=["all"],
workaround_exists=True, # Feature flags can help
blocking_new_work=False
)
]
class TechnicalDebtPrioritizer:
"""Priorizar qué debt atacar primero"""
@staticmethod
def calculate_priority_score(debt: TechnicalDebt) -> float:
"""Score = (Severity × Impact) / Cost"""
severity_score = debt.severity.value * 10
# Impact factors
impact_score = 0
impact_score += debt.velocity_impact # 0-100
impact_score += 20 if debt.bug_risk == "High" else 10 if debt.bug_risk == "Medium" else 0
impact_score += 30 if debt.blocking_new_work else 0
impact_score += 10 if not debt.workaround_exists else 0
# Cost (lower is better, so invert)
cost_score = debt.time_to_fix_now
# Priority = (Severity + Impact) / Cost
priority = (severity_score + impact_score) / cost_score
return priority
@staticmethod
def prioritize_debts(debts: list) -> list:
"""Ordenar debts por prioridad"""
# Calculate scores
debts_with_scores = []
for debt in debts:
score = TechnicalDebtPrioritizer.calculate_priority_score(debt)
debts_with_scores.append({
'debt': debt,
'score': score
})
# Sort by score (highest first)
sorted_debts = sorted(debts_with_scores, key=lambda x: x['score'], reverse=True)
return sorted_debts
@staticmethod
def print_debt_register(debts: list):
"""Imprimir registro de technical debt"""
sorted_debts = TechnicalDebtPrioritizer.prioritize_debts(debts)
print("\n" + "=" * 100)
print("🏗️ TECHNICAL DEBT REGISTER")
print("=" * 100)
print(f"\n{'Priority':<10} {'Name':<30} {'Severity':<12} {'Fix Now':<10} {'Impact':<10}")
print("-" * 100)
for item in sorted_debts:
debt = item['debt']
score = item['score']
severity_icon = "🔴" if debt.severity == DebtSeverity.CRITICAL else \
"🟠" if debt.severity == DebtSeverity.HIGH else \
"🟡" if debt.severity == DebtSeverity.MEDIUM else "🟢"
print(f"{score:<10.2f} {debt.name:<30} {severity_icon} {debt.severity.name:<10} "
f"{debt.time_to_fix_now}h{'':<7} {debt.velocity_impact}%{'':<7}")
print("\n" + "=" * 100)
# Recommendations
print("\n💡 RECOMMENDATIONS:\n")
top_3 = sorted_debts[:3]
print("🎯 Fix ASAP (highest priority):")
for i, item in enumerate(top_3, 1):
debt = item['debt']
print(f" {i}. {debt.name}")
print(f" Why: {debt.description}")
print(f" Effort: {debt.time_to_fix_now}h")
print(f" Impact: {debt.velocity_impact}% velocity hit")
if debt.blocking_new_work:
print(f" ⚠️ BLOCKING new features")
print()
bottom_3 = sorted_debts[-3:]
print("⏳ Can wait (low priority):")
for item in bottom_3:
debt = item['debt']
print(f" • {debt.name} (priority score: {item['score']:.2f})")
# Analizar technical debt
TechnicalDebtPrioritizer.print_debt_register(debt_examples)
Tomar decisiones:
class ShipOrFixDecision:
"""Framework para decidir: ship con debt o fix primero?"""
@staticmethod
def should_ship_with_debt(
debt_severity: DebtSeverity,
time_to_fix: int,
time_to_market_pressure: str, # Low/Medium/High
revenue_impact: float, # $ per day delayed
bug_probability: float # 0-1
) -> dict:
"""Decidir si ship con debt o fix primero"""
# Decision matrix
if debt_severity == DebtSeverity.CRITICAL:
return {
'decision': 'FIX FIRST',
'reason': 'Critical debt cannot ship',
'confidence': 'High'
}
if time_to_market_pressure == "High" and debt_severity == DebtSeverity.LOW:
# Expected cost of bug
expected_bug_cost = bug_probability * 10000 # $10k per bug
# Cost of delay
delay_cost = revenue_impact * (time_to_fix / 8) # Convert hours to days
if delay_cost > expected_bug_cost * 2:
return {
'decision': 'SHIP WITH DEBT',
'reason': f'Delay costs ${delay_cost:.0f} >> bug risk ${expected_bug_cost:.0f}',
'confidence': 'Medium',
'mitigation': [
'Add to technical debt register',
'Schedule fix for next sprint',
'Add monitoring for failure'
]
}
if debt_severity == DebtSeverity.HIGH:
return {
'decision': 'FIX FIRST',
'reason': 'High severity debt too risky',
'confidence': 'High'
}
# Default: Medium/Low debt with Medium pressure
return {
'decision': 'SHIP WITH DEBT',
'reason': 'Acceptable tradeoff',
'confidence': 'Low',
'mitigation': [
'Add to backlog',
'Review in 2 weeks'
]
}
# Ejemplo de uso
decision = ShipOrFixDecision.should_ship_with_debt(
debt_severity=DebtSeverity.MEDIUM,
time_to_fix=16, # 2 days
time_to_market_pressure="High", # Competitor launching similar feature
revenue_impact=5000, # $5k per day delayed
bug_probability=0.20 # 20% chance of bug
)
print("\n🤔 SHIP OR FIX DECISION")
print("=" * 60)
print(f"Decision: {decision['decision']}")
print(f"Reason: {decision['reason']}")
print(f"Confidence: {decision['confidence']}")
if 'mitigation' in decision:
print(f"Mitigation:")
for m in decision['mitigation']:
print(f" • {m}")
print("=" * 60)