💰 Developer Cookbook - FASE 7: Análisis de Impacto Financiero

Calcular ROI, optimizar costos y gestionar technical debt con criterio de negocio


📚 Tabla de Contenidos

  1. Receta 7.10: ROI de Decisiones Técnicas
  2. Receta 7.11: Cost Optimization en Cloud
  3. 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)