3Growing Object-Oriented Software, Guided by Tests

拍卖应用

项目启动

领域建模XMPP协议事件驱动系统架构

🎯 AI 时代的学习建议:不要只读理论。理解这一章的设计动机(为什么需要这个概念?)和边界条件(什么情况下会失效?)。当 AI 生成的代码涉及这些概念时,你能判断它是否用对了场景。AI 能帮你总结内容,但无法替代你亲手阅读、思考、建立直觉的过程。

第3章:拍卖应用(The Auction Application)

一、导读

1.1 本章学习目标

第3章以一个在线拍卖应用为主线,展示如何用 TDD 的方式从零开始构建一个真实的系统。

1.2 为什么第三章如此重要

理论需要实践来验证。通过一个完整的实战案例,你可以看到 TDD 如何在真实项目中发挥作用。

1.3 核心问题引导

如何从零开始用 TDD 构建一个系统?

领域模型如何驱动设计?

事件驱动架构如何在 TDD 中体现?

如何处理外部依赖?


二、核心概念详解

3.1 拍卖系统概述

核心领域:
- 拍卖品(Item):被拍卖的物品
- 出价(Bid):竞拍者的出价
- 竞拍者(Bidder):参与竞拍的人
- 拍卖行(AuctionHouse):管理拍卖

事件流:
- 拍卖开始 → 出价 → 出价被接受/拒绝 → 拍卖结束

3.2 TDD 驱动设计

java
// 第1步:写验收测试
@Test
public void bidderReceivesNotificationWhenOutbid() {
    // 设置拍卖环境
    // 竞拍者出价
    // 另一个竞拍者出价更高
    // 验证第一个竞拍者收到通知
}

// 第2步:写单元测试
@Test
public void shouldNotifyWhenOutbid() {
    Auction auction = mock(Auction.class);
    AuctionSniper sniper = new AuctionSniper(auction);
    
    sniper.currentPrice(100);
    sniper.bid(110);
    
    verify(auction).bid(110);
}

3.3 事件驱动

java
// 事件定义
public interface AuctionEvent {
    String itemId();
}

public class PriceChanged implements AuctionEvent {
    private final String itemId;
    private final int price;
    // ...
}

// 事件处理
public class AuctionSniper implements AuctionEventListener {
    @Override
    public void priceChanged(int newPrice) {
        if (shouldBid(newPrice)) {
            auction.bid(newPrice + increment);
        }
    }
}

三、实战案例

3.1 完整的 TDD 循环

java
// 红灯
@Test
public void sniperBidsWhenPriceIsBelowStopPrice() {
    Auction auction = mock(Auction.class);
    AuctionSniper sniper = new AuctionSniper(auction, 200);
    
    sniper.priceChanged(100);
    
    verify(auction).bid(110);
}

// 绿灯
public class AuctionSniper implements AuctionEventListener {
    private final Auction auction;
    private final int stopPrice;
    
    public AuctionSniper(Auction auction, int stopPrice) {
        this.auction = auction;
        this.stopPrice = stopPrice;
    }
    
    @Override
    public void priceChanged(int newPrice) {
        if (newPrice < stopPrice) {
            auction.bid(newPrice + 10);
        }
    }
}

// 重构
// 提取常量、改善命名、简化逻辑

四、本章小结

通过拍卖应用案例,展示了 TDD 如何在真实项目中驱动设计。从验收测试到单元测试,从领域模型到事件驱动,TDD 贯穿整个开发过程。


五、思考与练习

如何确定第一个测试?

如何处理外部依赖(如 XMPP 协议)?

如何从测试中提取领域模型?

TDD 如何帮助发现设计问题?

如何平衡测试数量和开发速度?


3/7拍卖应用
0%