摘要:首先把需求写下来:
1.【需求(因为原题的需求有点含糊,我在这里做了些简化)】反转一个句子:把一个句子里的以空格为间隔的英文单词,反向排列后以单个空格将其隔开后输出。(标点符号什么的先不考虑,就假设这些东西已经被另外的对象处理过了)
有人大概会说,有必要一本正经地把这么小的需求写下来么,有这功夫,他都能把整个程序写完了,而且这个程序满足所有的需求,包括各种边界条件等。对此,我只能说,你真棒!
对这样简单的东西大张旗鼓的,有些好笑。但我一般还是喜欢把需求按照自己的理解,自己的文字写下来,与客户(在这里,部分是gigix-因为需求是从他的测试方法里推出来的,部分是我-因为里面的有些东西需要最后认定)确认为好。
接下来,从哪里开始呢?
我们要开发什么?反转一个句子。我们这里准备使用.NET,需要把相应的功能放在一个类里,这个类取什么名字好?gigix用的是StringReverser作为类名,这个名字好像有点歧义,reverse string(反转字符串)?其涵义应该跟我们要满足的需求有点不同,我们需要的是reverse the order of the words in a sentence(把句子里的单词的次序倒转),但好像把这些词合起来变成类名有点过分,我们就简单一点,叫WordOrderReverser吧。
我们要写维护性好的程序,程序必须有很好的可读性(codebetter.com的Scott Bellware称之为Soluble Code ),对类,成员,方法的命名很重要,应该反映出它们所代表的东西。Pete Goodliffe在他的《Code Craft: The Practice of Writing Excellent Code》的第三章《What’s in a Name?》里详细讨论了取个有意义的名字的重要性。
因为我们要做TDD,先从测试类开始 (如果你要跟着做的话,在Visual Studio 2005里, 建立一个C#的类库方案,取名为JoyCodeTDDDemo,再往方案里加一个类库项目,取名为JoyCodeTDDDemoTest。在JoyCodeTDDDemoTest中,删除对System.Data和System.Xml的引用,删除系统自动生成的Class1.cs,添加对nunit.framework最新版本的程序集引用,以及对JoyCodeTDDDemo的项目引用。另外,不知道你用什么东西运行测试,我用的是TestDriven.NET的VS Add-in)。
在测试项目JoyCodeTDDDemoTest里,添加一个新的类文件,给新加的类文件命名为WordOrderReverserTest.cs,添加对NUnit.Framework的using,将其中的类设成public,并添加[TestFixture]:
using System;using NUnit.Framework;
namespace JoyCodeTDDDemoTest{[TestFixture]public class WordOrderReverserTest{
}}
编译一下,确认没问题。
让我们来写第一个测试方法,就象“抛出异常的爱”的做法一样,测试只有一个单词的情形:
[Test]public void TestOneWord(){String str = "abc";WordOrderReverser reverser = new WordOrderReverser();Assert.AreEqual("abc", reverser.Reverse(str));}
我们在上面决定把包含应用代码的类名取为WordOrderReverser,在这里我们预期它有一个叫Reverse的方法,实现我们用户的需求。在这里我们选择这个方法接受一个参数,但我们也可以把需要反转的字符串传入WordOrderReverser的构造器,譬如这样
String str = "abc";WordOrderReverser reverser = new WordOrderReverser(str);Assert.AreEqual("abc", reveser.Reverse());
哪个比较好?后面这个做法决定了我们的类只反转传入的字符串,不能反转其他的字符串。这样的做法也许在很多情形下比较合适,但我们这里是把某个算法(如果反转句子里的词也算什么算法的话)封装在这个类里,在实际情形中,也许需要同时反转多个句子,所以也许采用第一种做法比较好,因为第二种做法需要为每个句子生成一个相应的对象才能做反转操作。。。。【打住,打住,这是在做upfront design了,需求里有这么说么?没有。】,就按直觉吧。
很明显,现在无法编译。在JoyCodeTDDDemo项目里,删除系统自动生成的Class1.cs,添加一个名为WordOrderReverser.cs的文件,再加一个Reverse方法:
using System;
namespace JoyCodeTDDDemo{public class WordOrderReverser{public string Reverse(String str){return null;}}}
别忘了在WordOrderReverserTest.cs里加一个引用,
using JoyCodeTDDDemo;
编译通过,运行测试失败,出现红灯:
TestCase 'JoyCodeTDDDemoTest.WordOrderReverserTest.TestOneWord' failed: Expected: "abc"But was: nullD:\labs\JoyCodeTDDDemo\JoyCodeTDDDemoTest\WordOrderReverserTest.cs(15,0): at JoyCodeTDDDemoTest.WordOrderReverserTest.TestOneWord()
TestFixture failed: Child test......[
阅读全文]