<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Behind the Code &#187; 极限编程</title>
	<atom:link href="http://yinwm.com/tag/%e6%9e%81%e9%99%90%e7%bc%96%e7%a8%8b/feed/" rel="self" type="application/rss+xml" />
	<link>http://yinwm.com</link>
	<description>Just Do It</description>
	<lastBuildDate>Wed, 04 Jan 2012 03:54:33 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3</generator>
		<item>
		<title>初涉敏捷编程</title>
		<link>http://yinwm.com/2008/04/%e5%88%9d%e6%b6%89%e6%95%8f%e6%8d%b7%e7%bc%96%e7%a8%8b/</link>
		<comments>http://yinwm.com/2008/04/%e5%88%9d%e6%b6%89%e6%95%8f%e6%8d%b7%e7%bc%96%e7%a8%8b/#comments</comments>
		<pubDate>Wed, 30 Apr 2008 23:42:40 +0000</pubDate>
		<dc:creator>yinwm</dc:creator>
				<category><![CDATA[程序设计]]></category>
		<category><![CDATA[agile]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[TDD]]></category>
		<category><![CDATA[极限编程]]></category>

		<guid isPermaLink="false">http://yinwm.cn/wordpress/?p=47</guid>
		<description><![CDATA[我们都知道一个设计良好的程序是优雅的，我们也知道单元测试是很重要的，有充足的单元测试就可以尽可能的保证一个程序模块的正确性。这两部分是一直困扰我的部分，如何保证一个设计是尽可能的优雅的，还有就是让单元测试测试到尽可能多的测试点。以前的做法都是提前对程序进行设计，然后进行编码，然后编写单元测试代码，再根据觉得哪里不妥修改代码，修改测试用例。 这里我遇到的问题是 设计阶段不能设计的足够精细这一点非常令我恼火，有的想要给别人看的代码，比如开源，要求你的API设计来不得半点马虎，要设计的很合理。前期的脑纸笔的设计方式，会让细节偏差很大。而合理的API基本上都是通过不断的编码得到的。 单元测试用例并不能覆盖几乎100%的代码当你写好了代码之后，你就懒得写测试用例了，尤其是针对一些不总用到的功能。而写出的用例大多都是一个非常完整的场景，而不是针对某一个小模块的测试。针对性不强。 针对这两个让我极其愤恨的问题，我决定使用敏捷编程，测试先行。 我对测试的看法一直是测试（我承认这是一句废话），我以前都是写了代码（也就过了设计阶段）再写用例，这样程序的API设计大都是凭借对代码的理解捏造出来的，理解的深，功力深，API设计的就相对好一些，理解的不够深，捏造的成分就大，后期自己看着都恶心。但是Kent Beck和Uncle Bob告诉我们测试用例就是在进行程序的设计。其实，一个好用的API，都是经过实践检验的，这样自然要不断的编写和修改代码，而我们把这个过程提前，放在最初要设计的测试用例里面。一个测试用例，就是对一组API的调用的描述，也就是场景重现，这阶段已经就是在使用自己的API，也就是检验自己的API。当然，最初的这部分编码连编译都无法通过，因为你要求的所有东西都没有，但也正因为如此，你才能按照你最舒服的调用方式调用API，而不是受到什么限制。 例如 Query query = xxDAO.createQuery(&#8220;Target&#8221;); query.addExpression(Expression.eq(&#8220;name&#8221;, &#8220;Testing&#8221;); List l = xxDAO.doQuery(query) 这时候，我们没有Query，没有addExpression，没有Expression，什么都没有，但是这代码看着很自然。这就说明如果我们这样设计API就还算不差。下一步很自然的，我们要让这部分代码编译通过，增加Query这个interface[1]，然后完成编译。 我认为，到了这个阶段，程序的设计已经完成了80%了，剩下的就是看哪里能够变得更加合理，让臭味更小了。至于所有的实现类的编码，我觉得就是体力劳动了，虽然体力劳动也很累很耗时，但毕竟能够找到解决方法。这时候剩下的事情就简单多了，编写真正的实现类代码，让单元测试通过。 我们应该在编写真正的代码的时候，都是针对测试用例里面使用的API进行编码。这句话的意思就是，我们编写出的方法，应该是测试用例用到的，而不是额外的编写一些暂时没有用到的代码。如果这些将要编写的类/方法没有被测试用例覆盖到，那么要么是这些类/方法暂时没有需求，要么就是测试用例覆盖度不够。哪怕是一个简单的setter/getter，也要有测试用例直接或者间接覆盖到。之所以这样，只是为了避免破窗原理，一个没写，就会有第二个，就会有第n个。 [1]：之所以增加的是interface，就是因为增加的interface更加抽象，行为更加的单纯，并且在测试的时候，可以充分的使用Mock。但是这不是绝对的，在一些纯粹的逻辑的东西，就完全是一个class就能代替的，而无需interface，比如例子中的Expression，用class就比interface好很多]]></description>
			<content:encoded><![CDATA[<p><meta http-equiv="CONTENT-TYPE" content="text/html; charset=utf-8"><title></title><meta name="GENERATOR" content="OpenOffice.org 2.4  (Win32)"><br />
<style type="text/css">
<!--
@page { size: 21cm 29.7cm; margin: 2cm }
P { margin-bottom: 0.21cm }
-->
</style>
<p style="margin-bottom: 0cm;">
<p style="margin-bottom: 0cm;">我们都知道一个设计良好的程序是优雅的，我们也知道单元测试是很重要的，有充足的单元测试就可以尽可能的保证一个程序模块的正确性。这两部分是一直困扰我的部分，如何保证一个设计是尽可能的优雅的，还有就是让单元测试测试到尽可能多的测试点。以前的做法都是提前对程序进行设计，然后进行编码，然后编写单元测试代码，再根据觉得哪里不妥修改代码，修改测试用例。</p>
<p style="margin-bottom: 0cm;">这里我遇到的问题是</p>
<ol>
<li>
<p style="margin-bottom: 0cm;">设计阶段不能设计的足够精细<font face="Times New Roman, serif"><br /></font>这一点非常令我恼火，有的想要给别人看的代码，比如开源，要求你的<font face="Times New Roman, serif">API</font>设计来不得半点马虎，要设计的很合理。前期的脑纸笔的设计方式，会让细节偏差很大。而合理的<font face="Times New Roman, serif">API</font>基本上都是通过不断的编码得到的。</p>
</li>
<li>
<p style="margin-bottom: 0cm;">单元测试用例并不能覆盖几乎<font face="Times New Roman, serif">100%</font>的代码<font face="Times New Roman, serif"><br /></font>当你写好了代码之后，你就懒得写测试用例了，尤其是针对一些不总用到的功能。而写出的用例大多都是一个非常完整的场景，而不是针对某一个小模块的测试。针对性不强。</p>
</li>
</ol>
<p style="margin-bottom: 0cm;">针对这两个让我极其愤恨的问题，我决定使用敏捷编程，测试先行。</p>
<p style="margin-bottom: 0cm;">我对测试的看法一直是测试（我承认这是一句废话），我以前都是写了代码（也就过了设计阶段）再写用例，这样程序的<font face="Times New Roman, serif">API</font>设计大都是凭借对代码的理解捏造出来的，理解的深，功力深，<font face="Times New Roman, serif">API</font>设计的就相对好一些，理解的不够深，捏造的成分就大，后期自己看着都恶心。但是<font face="Times New Roman, serif">Kent<br />
Beck</font>和<font face="Times New Roman, serif">Uncle<br />
Bob</font>告诉我们测试用例就是在进行程序的设计。其实，一个好用的<font face="Times New Roman, serif">API</font>，都是经过实践检验的，这样自然要不断的编写和修改代码，而我们把这个过程提前，放在最初要设计的测试用例里面。一个测试用例，就是对一组<font face="Times New Roman, serif">API</font>的调用的描述，也就是场景重现，这阶段已经就是在使用自己的<font face="Times New Roman, serif">API</font>，也就是检验自己的<font face="Times New Roman, serif">API</font>。当然，最初的这部分编码连编译都无法通过，因为你要求的所有东西都没有，但也正因为如此，你才能按照你最舒服的调用方式调用<font face="Times New Roman, serif">API</font>，而不是受到什么限制。</p>
<p style="margin-bottom: 0cm;">例如</p>
<p style="margin-bottom: 0cm;"><font face="Times New Roman, serif">Query<br />
query = xxDAO.createQuery(&#8220;Target&#8221;);</font></p>
<p style="margin-bottom: 0cm;"><font face="Times New Roman, serif">query.addExpression(Expression.eq(&#8220;name&#8221;,<br />
&#8220;Testing&#8221;);</font></p>
<p style="margin-bottom: 0cm;"><font face="Times New Roman, serif">List<br />
l = xxDAO.doQuery(query)</font></p>
<p style="margin-bottom: 0cm;">这时候，我们没有<font face="Times New Roman, serif">Query</font>，没有<font face="Times New Roman, serif">addExpression</font>，没有<font face="Times New Roman, serif">Expression</font>，什么都没有，但是这代码看着很自然。这就说明如果我们这样设计<font face="Times New Roman, serif">API</font>就还算不差。下一步很自然的，我们要让这部分代码编译通过，增加<font face="Times New Roman, serif">Query</font>这个<font face="Times New Roman, serif">interface[1]</font>，然后完成编译。</p>
<p style="margin-bottom: 0cm;">我认为，到了这个阶段，程序的设计已经完成了<font face="Times New Roman, serif">80%</font>了，剩下的就是看哪里能够变得更加合理，让臭味更小了。至于所有的实现类的编码，我觉得就是体力劳动了，虽然体力劳动也很累很耗时，但毕竟能够找到解决方法。这时候剩下的事情就简单多了，编写真正的实现类代码，让单元测试通过。</p>
<p style="margin-bottom: 0cm;">我们应该在编写真正的代码的时候，都是针对测试用例里面使用的<font face="Times New Roman, serif">API</font>进行编码。这句话的意思就是，我们编写出的方法，应该是测试用例用到的，而不是额外的编写一些暂时没有用到的代码。如果这些将要编写的类<font face="Times New Roman, serif">/</font>方法没有被测试用例覆盖到，那么要么是这些类<font face="Times New Roman, serif">/</font>方法暂时没有需求，要么就是测试用例覆盖度不够。哪怕是一个简单的<font face="Times New Roman, serif">setter/getter</font>，也要有测试用例直接或者间接覆盖到。之所以这样，只是为了避免破窗原理，一个没写，就会有第二个，就会有第<font face="Times New Roman, serif">n</font>个。</p>
<p style="margin-bottom: 0cm;">
</p>
<p style="margin-bottom: 0cm;">
</p>
<p style="margin-bottom: 0cm;">
</p>
<p style="margin-bottom: 0cm;"><font face="Times New Roman, serif">[1]</font>：之所以增加的是<font face="Times New Roman, serif">interface</font>，就是因为增加的<font face="Times New Roman, serif">interface</font>更加抽象，行为更加的单纯，并且在测试的时候，可以充分的使用<font face="Times New Roman, serif">Mock</font>。但是这不是绝对的，在一些纯粹的逻辑的东西，就完全是一个<font face="Times New Roman, serif">class</font>就能代替的，而无需<font face="Times New Roman, serif">interface</font>，比如例子中的<font face="Times New Roman, serif">Expression</font>，用<font face="Times New Roman, serif">class</font>就比<font face="Times New Roman, serif">interface</font>好很多</p>
<p style="margin-bottom: 0cm;"></p>
]]></content:encoded>
			<wfw:commentRss>http://yinwm.com/2008/04/%e5%88%9d%e6%b6%89%e6%95%8f%e6%8d%b7%e7%bc%96%e7%a8%8b/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

