为什么TDD

我发现了一篇特好的文章,把什么是测试驱动讲解的灰常清晰、易懂,所以迫不及待得来转帖,原文出自thoughtworks的 张开封, 以下是原文.

http://kfzhang.thoughtworkers.org/2012/05/why-tdd/

1. 反映真实需求

这里存在先写测试和后写测试的区别。

先说后写测试。根据很多经验,在直接写产品实现代码时,需要考虑需求,同时需要兼顾实现的细节,用什么算法和语法。在对需求和考虑和实现细节间来回,很容易让人产生对其中一方的疏忽,遗漏掉一些需求方面,甚至在实现上存在缺陷。

有人会说我可以通过后写测试来保证。第一经验是,很多人都不会在实现完成后,补充测试,因为还有更多的工作和需求需要实现。第二是开发人员很容易在后补的测试中,只是试图去测试他已有的实现,而不是需求本身,很容易遗漏掉一些边界检查之类,在测试时,已有的实现细节会在脑子里面先入为主,即使实现存在问题或有漏洞,也很难在后补的测试中测出来。我阅读过很多面试者的测试代码,很明显都是后补的,因为一些很明显的问题没有测出来,甚至已经实现的逻辑也是只测试了一部分。而这些面试者都承认。

结果就是,一旦代码签入,开始集成之后,暴露出问题,后补的测试起不到对于实现代码的保障需求的作用,开发者不能不借助调试工具,单步跟踪实现代码的每一行去寻找问题发生的原因。

再说先写测试。按照TDD的流程,先写失败的测试,再写恰好让测试成功的实现代码,最后重构,如此往复。这样的好处在于,每先写一个测试,都是在试图用自己对问题和需求的理解,来定义实现代码的架子。从测试的不同角度,范围、边界、大小、功能等等,来定义实现代码将来会是个什么样子。一个测试接着一个测试,利用TDD的过程,把实现代码恰好不多不少,正好驱动出解决这个需求和问题的实现代码来。

这里的重点在于,先写测试可以让开发者把重点放在理解需求和实现需求上,而不是一开始就陷入实现的细节中同时兼顾需求,掉入两者都兼顾不好的境地。先写的测试代码,作为副产品,可以作为验证需求的得力保障。

2. 设计在其中

先写测试对于设计的好处在于,先写测试先定义新的类,以及定义类与类之间的关系,就是在定义类与类之间如何交互,每个类如何暴露自己的接口,类和类之间的引用关系。这时,测试代码会逼迫开发者认真考虑如何分解类与类之间的耦合关系,这样产生的实现代码更容易利用了IoC和DIP的模式,实现面向接口编程。

这样实现代码的好处还在于,代码的可测试性很高,在加入更多的测试代码和新类的时候,同样借力于已有类的面向接口和依赖反转所带来的可测试性,达到新实现代码的面向接口和可测试性,这样进入良性循环。而这对于整体的代码和设计,获益良多。换句话说,测试即设计。

回头看后写测试的情况,因为从一开始开发者把重心放在实现的细节和功能需求的往复上,对于代码设计、类的关系和定义很容易疏于考虑,产生的结果可能是耦合紧,可测试性差。

3. 增强信心

在我看来,软件开发周期、软件交付最大的问题在于交付后的运行和维护阶段,正是这个阶段才是软件在持续交付价值的时期。在软件的可维护性,在这个阶段凸显价值。在软件交付后,包括软件开发周期期间,不可避免的就是开发者在根据新的需求,逐渐添加新的功能代码,或者修复一些已知的缺陷。

很多经验表明,在开发者按照需求添加一些新的代码进入系统,或者试图修复已有缺陷时,很容易导致既有功能出错,也就是新引入的代码打破了既有代码的逻辑,导致回归问题的出现。因为软件系统的可测试性差,无法做到快速频繁自动的回归测试,带来的可维护性自然也很差。

而作为TDD的副产品之一——可以快速频繁自动运行的测试代码,可以在开发者新引入代码之际,给予开发者足够的信心,每次添加一点新代码,一个方法,一个类,都已频繁运行已有相关的测试代码,来确保新引入代码不会打破已有的功能。

在持续集成中,这些测试代码可以帮助验证每次签入的代码都不会破坏掉已有的功能。这也是《重构》里面反复提到的在每个重构小步骤后都要运行所有的测试代码的原因所在。

4. 粒度和进度

按照TDD的原则,先写测试,可以让开发者在同一时间只关注在功能需求的一小部分,把功能需求且分到一定小的粒度,用测试代码去表示这样的需求,用实现代码让测试通过,实现这样的需求,然后重构。

这样的好处在于,开发者自己的注意力和重心不用在整个功能需求内的小需求点之间犹豫,每次注重解决单个小问题,解决完一个进入下一个小问题的解决。在保证小粒度实现的同时,保证进度可以随时被打断,但同时被打断时已经做完的是完整可以运行,至少是实现了部分需求的实现代码。

而后写测试的代价是,首先实现代码很有可能包含设计上的问题,甚至含有缺陷,在完美的测试代码完成之前(事实上这是不可能的),可以交付的是可能存在严重缺陷,甚至是曲解了功能需求的实现代码。

<think>嗯,用户这次聚焦在"TDD时隙为5ms"的具体含义上,需要结合之前的TDD框架知识深化解释。用户似乎有通信背景,但可能对时隙的时间维度概念不够清晰。 从对话历史看,用户已经理解了TDD时隙结构和比例配置,现在需要将抽象概念具象化为时间单位。特别要注意引用[1]中"特殊子帧总长度1ms"的线索,这说明5ms时隙必然包含多个子帧的聚合。 重点在于三点:第一,5ms不是单个时隙长度而是调度周期,这点容易产生误解;第二,这个周期包含完整的DL/UL/GP组合;第三,它与子载波间隔的关联(引用[2]的numerology概念需要融入解释)。 用户可能隐含的需求是理解5G调度机制,所以回答要突出5ms周期在动态调度中的优势。需要对比LTE的固定1ms子帧,说明NR的改进点。 数学表达很关键:要用公式展示5ms与子帧数的关系,比如$N_{sub} = 5 \times 2^\mu$。同时要关联保护时隙的配置灵活性(引用[1]的OFDM符号可配置性),说明不同场景下的实现差异。 最后的问题设计要引导用户思考实际部署:保护间隔配置、多业务场景调度这些方向能延续知识链条。特别要加入URLLC案例,因为这是5ms短周期的重要应用场景。 </think>TDD时隙为5ms的含义是指在5G NR(New Radio)系统中,**一个完整的TDD帧周期为5毫秒**,该周期内包含完整的上下行时隙配置。这一设计是5G对LTE帧结构的重大改进,具体解析如下: --- ### 一、核心概念解析 1. **帧结构分层**(基于引用[2]) 5G NR采用灵活的帧结构: - **无线帧(Radio Frame)**:固定为10ms - **子帧(Subframe)**:固定为1ms - **时隙(Slot)**:长度**动态可变**,取决于子载波间隔(Numerology) 公式: $$ \text{时隙长度} = \frac{1}{2^\mu \times 15\text{kHz}} \quad (\mu \text{为Numerology编号}) $$ - 例如:$\mu=0$(子载波间隔15kHz)时,时隙长度=1ms;$\mu=2$(60kHz)时,时隙长度=0.25ms。 2. **5ms TDD时隙的含义** - **本质是调度周期**:指基站调度上下行传输的最小时间单元为**5ms**,而非单个时隙固定为5ms。 - **包含多个子帧/时隙**:在5ms周期内,根据$\mu$值动态包含不同数量的时隙(见下表): | $\mu$值 | 子载波间隔 | 单时隙长度 | 5ms周期内时隙数 | |---------|------------|------------|------------------| | 0 | 15kHz | 1ms | 5个 | | 1 | 30kHz | 0.5ms | 10个 | | 2 | 60kHz | 0.25ms | 20个 | - **动态配置上下行**:在5ms周期内,通过DCI(Downlink Control Information)动态分配每个时隙为DL/UL/GP,实现业务自适应[^2]。 --- ### 二、关键设计意义 1. **低时延业务支持** - 5ms周期比LTE的10ms更短,显著降低调度延迟,满足URLLC(超可靠低时延通信)需求。 - 例如:工业自动化场景中,控制信号可在5ms内完成闭环传输。 2. **灵活的资源分配** - 基站根据实时流量动态调整5ms周期内的DL/UL比例(如从3:1切换至1:3),优化频谱效率[^1]。 - 对比FDD:固定频谱配对,无法适应突发上行流量(如直播场景)。 3. **多 Numerology 兼容** 不同$\mu$值的业务(eMBB/URLLC/mMTC)可在同一5ms帧内共存: - 低频段($\mu=0$)传广覆盖业务 - 高频段($\mu=3$)传高速数据 通过时隙聚合实现资源隔离[^2]。 --- ### 三、与LTE的对比 | **特性** | **LTE TDD** | **5G NR TDD** | |----------------|---------------------------|---------------------------| | 帧周期 | 固定10ms | **支持5ms/10ms可选** | | 时隙长度 | 固定0.5ms(2时隙/子帧) | 动态可变(0.125ms~1ms) | | 保护时隙(GP) | 固定符号数 | **可动态扩展**(见引用[1]) | | 调度粒度 | 子帧级(1ms) | 时隙/符号级(微秒级) | > 例:在5ms周期内配置$\mu=1$(30kHz),共10个时隙,可分配为: > `DL时隙×6 + GP×1 + UL时隙×3` → 适应下行视频流为主的场景[^1][^2]。 --- ### 四、典型应用场景 - **智能工厂**:5ms周期内预留专用URLLC时隙传输急停信号。 - **直播上行突发**:动态将DL时隙切换为UL,应对粉丝互动流量峰值。 - **车联网**:通过短GP(1~2符号)支持高速移动设备(引用[1]的GP可配置性)。 --- **相关问题** 1. 5G NR中如何为URLLC业务预留专属时隙? 2. 不同Numerology($\mu$值)的时隙如何在同一个5ms帧内实现同步? 3. 动态调整TDD比例时如何避免相邻基站干扰? 4. 毫米波频段(120kHz子载波)下5ms周期包含多少时隙?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值