代码寓言:容错的哲学

寓言正文

第一章:完美主义的陷阱

从前有一个程序员,他追求完美的代码。

他的函数永远正确。 他的算法永远最优。 他的程序永远不报错。

直到有一天,用户的网络断了。

# 他的代码
def send_data(data):
    if network.is_connected():
        send(data)
    # else? 什么都没做

用户等了十分钟,发现什么都没发生。


第二章:老程序员的话

“年轻人,“老程序员说,“你知道为什么飞机能飞吗?”

“因为有引擎。”

“不对。是因为飞机能承受引擎的失效。”

老程序员展示了他们的系统:

func sendDataWithRetry(data []byte, maxRetries int) error {
    for i := 0; i <= maxRetries; i++ {
        err := send(data)
        if err == nil {
            return nil
        }
        log.Printf("Attempt %d failed: %v", i, err)
        if i < maxRetries {
            time.Sleep(time.Duration(i+1) * time.Second) // 指数退避
        }
    }
    return fmt.Errorf("failed after %d attempts", maxRetries)
}

容错不是容忍错误,而是允许错误存在而不崩溃。


第三章:错误的价值

有一天,年轻的程序员问:

“如果错误不可避免,为什么要写 try-catch?”

老程序员笑了:

“你知道为什么钻石珍贵吗?”

“因为稀有。”

“不。是因为在高温高压下,碳变成了钻石。”

# 错误不是敌人,是成长的机会
try:
    result = risky_operation()
except TransientError as e:
    # 暂时性错误 - 重试
    return retry_with_backoff()
except PermanentError as e:
    # 永久性错误 - 记录并优雅处理
    log.error(f"Permanent failure: {e}")
    return fallback_value()
except Exception as e:
    # 未知错误 - 捕获但不过度处理
    logger.exception("Unexpected error")
    raise  # 或者返回默认值

错误是系统进化的一部分。


第四章:断路器的智慧

老程序员指着远处说:

“看到那些摩天大楼了吗?”

“看到了。”

“你知道为什么要建防火门吗?”

“防止火势蔓延。”

老程序员点头:

type CircuitBreaker struct {
    failures    int
    threshold   int
    state       string // "closed", "open", "half-open"
    lastFailure time.Time
}

func (cb *CircuitBreaker) Call() error {
    switch cb.state {
    case "open":
        if time.Since(cb.lastFailure) > resetTimeout {
            cb.state = "half-open" // 尝试恢复
        }
        return errors.New("circuit open")
    case "half-open":
        // 允许有限请求
        err := doCall()
        if err != nil {
            cb.state = "open"
            return err
        }
        cb.state = "closed" // 恢复正常
        return nil
    default: // closed
        err := doCall()
        if err != nil {
            cb.failures++
            cb.lastFailure = time.Now()
            if cb.failures >= cb.threshold {
                cb.state = "open" // 熔断
            }
        } else {
            cb.failures = 0 // 成功,重置
        }
        return err
    }
}

断路器不是逃避错误,而是防止错误级联放大。


第五章:优雅降级

灾难来临的那天,整个系统几乎崩溃。

但老程序员的系统活了下来。

# 优雅降级 - 保住核心功能
def get_user_profile(user_id):
    try:
        # 尝试完整数据
        return full_profile_from_database(user_id)
    except DatabaseError:
        pass
    
    try:
        # 尝试缓存
        return cache.get(user_id)
    except CacheError:
        pass
    
    # 最后手段 - 返回基础信息
    return BasicProfile(user_id=user_id, 
                        name="User", 
                        status="degraded_mode")

完美是目标,优雅降级是智慧。


道德寓意

  1. 完美主义是陷阱 - 不可能永远不犯错,要学会与错误共处
  2. 错误是信息 - 每个错误都包含有价值的反馈
  3. 重试是智慧 - 暂时性错误可以通过重试解决
  4. 断路器防止崩溃 - 防止小错误变成大灾难
  5. 优雅降级是生存 - 保住核心功能,放弃华丽外表

代码实现

import logging
from functools import wraps
from time import sleep

def resilient(max_retries=3, backoff=1):
    """弹性装饰器"""
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            for attempt in range(max_retries):
                try:
                    return func(*args, **kwargs)
                except (ConnectionError, TimeoutError) as e:
                    if attempt < max_retries - 1:
                        sleep(backoff * (attempt + 1))
                        logging.warning(f"Retry {attempt+1}/{max_retries}")
                    else:
                        logging.error(f"All retries failed: {e}")
                        raise
            return None
        return wrapper
    return decorator

@resilient(max_retries=3)
def fetch_data(url):
    # 你的网络请求逻辑
    pass

结语

容错不是容忍错误, 而是在错误中保持运行,在失败中寻找成长。

真正的系统不是不犯错, 而是知道如何与错误相处,如何从错误中恢复。


明鉴 整理代码寓言集