4/30/2008

My heart is yours

你想流星
划出了美丽的曲线
你的魅力
在我的贪恋中流连
我用心曲
去试着把你催眠
你却逃避
拒绝我超越界限
我确信对你一见如故
却担心是个美丽错误
心非所属承认自己心非所属
心非所属害怕自己心非所属
你的影子躲在我的心深处
梦醒后忽然感觉百般的无助
心非所属承认自己心非所属
心非所属害怕自己心非所属
不想欺骗自己对你不在乎
我真的愿你过的比我更幸福
(music)
你很明白
我们的爱情会搁浅
你怕迷路
在爱与痛的边缘
我已为爱
约定了一个誓言
只能把你
当成是过眼云烟
我确信对你一见如故
却担心是个美丽错误
心非所属承认自己心非所属
心非所属害怕自己心非所属
你的影子躲在我的心深处
梦醒后忽然感觉百般的无助
心非所属承认自己心非所属
心非所属害怕自己心非所属
不想欺骗自己对你不在乎
我真的愿你过的比我更幸福
心非所属承认自己心非所属
心非所属害怕自己心非所属
你的影子躲在我的心深处
梦醒后忽然感觉百般的无助
心非所属承认自己心非所属
心非所属害怕自己心非所属
不想欺骗自己对你不在乎
我真的愿你过的比我更幸福
心非所属承认自己心非所属
心非所属害怕自己心非所属
你的影子躲在我的心深处
梦醒后忽然感觉百般的无助
心非所属承认自己心非所属
心非所属害怕自己心非所属
不想欺骗自己对你不在乎
我真的愿你过的比我更幸福

PHP and MySQL, the future

Written by Brian Moon, dealnews.com developer, on June 27, 2006

The tried and true MySQL extension (mysql) has been around in PHP for years. Lately, there has been a lot of buzz in the PHP world about the new "MySQL Improved Extension" (mysqli) and "PHP Data Objects" (PDO). When I work on Phorum or for dealnews.com, I am always concerned with performance. So, I thought I would give these new methods a try.

What is mysqli?

The PHP manual says

"The mysqli extension allows you to access the functionality provided by MySQL 4.1 and above."

That is as far as it goes, so I am not sure which exact features we are talking about. Looking through the function list, I see things about charsets, encoding, transactions and prepared statements.

Another plus of mysqli is that it includes an OOP interface for those that like OOP. Although, after using it and looking at the docs, I was disappointed that all the work could not be done in 100% OOP. There are several times when calling a function is needed to check for errors and the like. At least, that is how the examples in the manual do it. Because I am not a big OOP user, I decided to stick with the procedural usage in my tests.

(After some hunting, I found an article at Zend.com that discusses mysqli and its improvements.)

What is PDO?

The PHP manual says

"The PHP Data Objects (PDO) extension defines a lightweight, consistent interface for accessing databases in PHP. Each database driver that implements the PDO interface can expose database-specific features as regular extension functions."

Like mysqli, it also supports prepared statements. However, for MySQL, it does not support everything that mysqli does. The most noticable is charset and encoding functionality. However, for new users (especially those from Perl, ASP, etc.) it is probably a good starting point.

Prepared statements

The MySQL manual says this about prepared statements:

"The MySQL client/server protocol provides for the use of prepared statements. This capability uses the MYSQL_STMT statement handler data structure returned by the mysql_stmt_init() initialization function. Prepared execution is an efficient way to execute a statement more than once. The statement is first parsed to prepare it for execution. Then it is executed one or more times at a later time, using the statement handle returned by the initialization function."

On of the big pluses I have heard about prepared statements is that it reduces (according to some, eliminates) sql injection flaws. So, I additionally tested mysqli and PDO in the select tests with prepared statements for that reason.

The nitty gritty tests

I ran two different tests. In all cases, test runs were made several times. The best score for each extension was recorded. No odd spikes or dips occured. Each extension stayed within a 10% range on each run.

Select Speed

The first was selecting 100 rows from a table. For this test, I used a query from the Phorum source code that is used on every message list page.

select
phorum_messages.author, phorum_messages.datestamp, phorum_messages.email,
phorum_messages.message_id, phorum_messages.meta, phorum_messages.moderator_post,
phorum_messages.modifystamp, phorum_messages.parent_id, phorum_messages.sort,
phorum_messages.status, phorum_messages.subject, phorum_messages.thread,
phorum_messages.thread_count, phorum_messages.user_id, phorum_messages.viewcount,
phorum_messages.closed
from
phorum_messages use index (list_page_float)
where
modifystamp > 0 and forum_id = 12 and status = 2 and parent_id = 0 and sort > 1
order by
modifystamp desc
limit 0, 100

Because I work on Phorum and other web based applications, I used openload to test these scripts on a web server. Timing a single query would not yield as much useful data. All the raw data is in raw_selects.txt.

extension req/s
------------------------
mysqli 164
mysql 162
PDO 88
mysqli (prepared) 86
PDO (prepared) 81

I was very disappointed in PDO's speed. However, I was glad to see that mysqli was basically identical to mysql (both varied from the 150's to 160's). It is clear however, that selects using prepared statements is not fast at all. I also found the syntax for using mysqli prepared statements to be cumbersome for selecting data.

Insert Speed

The next test was to insert 10,000 rows into a table. Each insert inserted a random amount of data into the char field and the text field. The table was built as such:

CREATE TABLE `testing_mysql` (
`id` int(10) unsigned NOT NULL auto_increment,
`char_field` varchar(255) NOT NULL default '',
`text_field` text NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM

MySQL supports what it calls extended inserts. Basically, you can send one query with multiple values sets. If you use --opt with mysqldump, it creates dumps using this format. I decided to test using this method and normal methods of all 3 extensions. In addition I tested prepared statements for mysqli and PDO.

extension time
--------------------------
pdo (extended) 18.17s
mysqli (extended) 18.40s
mysql (extended) 18.46s
pdo (prepared) 25.04s
mysqli (prepared) 36.93s
mysqli 50.43s
mysql 53.09s
pdo 59.96s

This was pretty much what I expected. Using extended inserts puts all the pressure on the database server. As you can see, using that format is fastest and basically the same across all extenstions. If you don't want to use that method, then prepared inserts are a sure fire winner. PDO was the clear winner for prepared inserts. That is a little surprising. I would expect the mysqli extension to be a port of the C mysql api and therefore have the least overhead.

Conclusion

Performance

For all around best performance, you could use either mysql or mysqli. Given they are so close, I consider mysqli the better choice. It gives you the best options on top of the speed. In my opinion, PDO is not for use on systems where mysql performance is a top goal. The only reason I would have for ever using PDO would be to write a generic ANSI-SQL standard driver for Phorum.

Features

For features, I think mysqli is the clear winner. With the ability to set connection preferences and other new features, it is much better than the mysql extension. The only thing PDO offers over mysqli is a more complete OOP interface. However, it lacks some database interaction features that mysqli includes.

Ease of use

The mysql extension is tried and true. There are lots of books and docs out there about it. That makes it still attractive for some. Also, many ISPs will not have support for mysqli or PDO as of yet. The good news is that the mysqli extension looks very much like the mysql extension. Just a little rework of parameters is all that is needed to convert from one to the other.

PDO is great for new users coming from ASP, Perl or any other language that has a single unified system for database interaction. It is simple to use and the syntax is quite logical and sensible. OOP users will love it as it is a 100% OOP interface. I would not recommend it however for power users or applications where high performance is a must.

Disappointment

One disappointment in this test was prepared statements and SQL injection. I had never used prepared statements or read the specifics about them. MySQL (and I assume other database servers) limits what can be prepared and substituted in a query. You can only substitute for things like the values of WHERE clauses and VALUES sets. Unfortunately, for PHP applications, that is not always the only places you need variable data. LIMIT clauses often change from one page to another for paging applications. This variable data must still be set using a string concatenation. So, while prepared statements can help with SQL injection, it is not the end all be all of SQL injection prevention. Its uses is really limited to insert statements only.

And the winner is...

In closing, I am very impressed with mysqli. It lived up to its name. It truly is mysql - improved. Its as fast as the mysql extension ever was and offers more features than PDO. Its OO interface is not as complete as PDO, but the bulk of interaction is there for those that like OOP. If you don't care about OOP, then there is absolutly no down side.

4/29/2008

Becoming a Master Designer Rule Two: Limit Your Colors

Rule Two: Limit Your Colors. Sounds a lot like the last rule of limiting your fonts right? Exactly! We want to limit our colors for the same reason we want to limit our fonts. Reducing the number of colors we use in our design will make the piece feel consistent. Basically, everything will look like it goes together. Just like a sports team’s uniform or a company’s branding - we want a uniform over-all look to the colors.
As with the font selection, limiting the number of your colors is just a guide not a rule. You could very well have a rainbow of colors in your design and it will look great. But you need to start with a coloring strategy and stick with it. Use your color consistently throughout your design.
For starters lets talk about color values. A color’s value is how bright or dark the color is. A yellow for instance is fairly bright. A purple is fairly dark. Of course, a color can have a range of values. Purple for instance is a color that most of us think of as relatively dark, but you can also have a very light purple. Here is an example of some colors and their relative value. Then next to that you can see a range of values for one color.
So here is one rule I use when picking my color scheme: make sure you have a range of values in your color scheme. In any design you’re going to need some light colors and some dark colors to produce contrast. If for instance, the background of your design is dark, you’ll need a light color so that the copy can be easily read. Or conversely, if you have a bright background you’ll need a dark color for your art or text or whatever.
I will also typically only pick 2-5 colors to make up my color schemes. Reduce the number of options and you’ll typically have good results in the design. Here is a sample of a color scheme I put together. As you’ll see I picked One dark color, one middle-valued color and one bright color. Just to the right, I also set up a value range for each of these colors. It’s this collection of colors that I will use on my project as my palette. Once I have this color palette set up I will try my best to only use these color.
Ok, so now that we’ve addressed some technical color picking issues like how many colors to pick and what values they should be; what’s next? I’ll tell you what’s next, the hardest part; deciding what those 2-5 colors should be! I personally find this to be a somewhat difficult task at times. Here is a list of techniques I’ll use to help me pick my color schemes:
• Stick to a temperature range. As in… pick all warm colors or pick all cool colors. Warm colors are reds, oranges, yellows, browns, etc. Cool colors are blues and purples. I consider greens to be fairly neutral. If you pick all of your colors in one temperature range, they will probably go together fairly well.
• Use a website like www.colourlovers.com for inspiration. This wonderful site is all about picking color schemes. You can just click through page after page of color schemes.
• Keep an eye out. There are color schemes all around you. Look at packaging in the grocery store, look at the paint colors in your local Starbucks, look at Mother Nature! If you see something with a pleasing set of colors, just take a mental note and see if you can replicate it on your computer.
• Pay attention to pre-existing company colors. Frequently I am playing off of some pre-existing brand colors. I’ll look at their logo, color scheme and use that as my starting point. Then maybe just add a color or two.
Here are a finished design that I’ve done which show fairly restricted color schemes.
As you can see, the tight color scheme and limiting my fonts really pulls everything together.
I know these lessons are the basics… …but these remain cornerstones of design. So, it never hurts for a little refresher. 5 more rules to come. I promise the next 5 are a bit more interesting. Thanks for your time!

Become a Master Designer - Rule One: Limit your fonts

Part One of Seven Easy Principles to Becoming a Master Designer.
Ok, “master designer” might be a bit of a stretch – but you can at least become a “proficient designer” by following 7 easy principles. This will be the shortest, most informative series of blog posts you’ve ever read on how to become a better designer. Please note: these principles CAN be broken… these are not laws, they’re just general guides that I typically follow when putting together a design.Follow these simple design principles and you’ll be on your way to artistic excellence.Principle One: Limit Your fonts. A big part of putting together a good design, as you’ll see, is making sure the over-all look is consistent. The best way to accomplish a consistent look to your design is limiting the number of artistic motifs (themes) that you use. The fonts you select are the first variable you want to limit. I typically like to pick just 2 fonts per design.The first font can be fancy or artistic. This font will be used to give your design some flair, character and personality. It’s this font that sets the mood for the piece. Is it a fun font with swirls for a girl’s party, or is it a grungy evil font for a rock band? I would use this fancy font for the header copy – anywhere it’s big, I’ll use this font. The fancy font will be the focal point of the piece. You will usually have less copy in this fancy font, but it will be much bigger – so that’s what people will see and focus on.
The second font should be very basic. The audience shouldn’t take notice of this secondary font at all. This secondary font needs to be very easily legible. It’s this basic font that will be used for large bodies of copy. Obviously, it’s very hard to read large bodies of copy that are in some extravagantly artistic font. So, this second font is all about functionality.Here is an example of proper use of fonts in a design. As you can see, there is only two fonts used here. The fancy font is used as the headers and the basic font is used for the copy. It looks clean and consistent.Here is a Bad use of fonts. In this case I used too many fancy fonts. It just makes the piece look inconsistent. The sub sections don’t seem like they match with the main header.Having too many fonts in a design is the biggest mistake. Nothing looks worse than someone who has used 8 different fonts on their flyer. Even worse than that is using a very fancy font for your body copy. Here is a sample of font use at it’s worst:One last thought before I let you go. If your fancy font looks modern or contemporary, then your basic font should be a san-serif font. If your fancy font looks old fashioned, then use a serif font for your secondary font.

科学设计你的网站网页

在网络设计领域关于Eye-Tracking的研究十分火爆,但是如何把这些研究结果转变为具体可行的设计来运作依旧是个难点。以下就是一些来自于Eye-Tracking研究结果的窍门,可以为改进你的网站设计提供些意见:
1.对比图像,文字更具吸引力
与你所认为的相反,在浏览一个网站的时候,能够直接吸引用户目光的并不是图像。大多数通过偶然点击进入你的网站的用户,他们是来寻觅信息的而不是图像。因此,保证你的网站设计凸现出最重要的信息板块,这才是设计的首要原则。
2.眼球的第一运动聚焦于网页的左上角
用户浏览网页的这一习惯应该在意料之中,毕竟左上部为主要操作中心这一点为大多数重要的计算机应用程序的设计所采用。在你构建网站考虑网站设计时,应该尽量保持这一格式。要知道,如果你希望保持个人特色,搭建一个成功的网站,你就必须尊重用户们的习惯。
3.用户浏览网页时,首先观察网页的左上部和上层部分,之后再往下阅读,浏览右边的内容
用户普遍的浏览方式呈现出“F”的形状 。保证网站内容的重要要素集中于这些关键区域,以此确保读者的参与。在此放置头条,副题,热点以及重要文章,这样可以吸引到读者进行阅读。
4.读者会忽视横幅广告
研究表明,读者常忽视大部分的横幅广告——尽管你以此维持网站生计——视线往往只停留几分之一秒。如果你想通过广告挣钱,那么必须创新你的广告位以及合理配置网站广告形式。
5.花哨的字体和格式被忽视
为什么呢?那是因为用户会认为这些是广告,并非他们所需要的信息。事实上,研究表明用户很难在充满大量颜色的花哨字体格式里寻找到所需的信息,因为视觉线索告诉他们把这些忽略吧。保持网站的清爽,不要因为华而不实的表面,让重要的信息被忽略。
6.用数词来代替数字
如果使用数词取代数字的罗列,读者会发现在你的网站可以很容易地发现真实的资料。要知道,你是写给那些将第一次浏览你的网站的读者,所以,让他们容易发现他们所需的信息,让他们感兴趣。
7.字体大小影响浏览行为
想改变人们对你的网页的看法吗?改变网页字体的大小。大的字体刺激浏览,而小一些的字体则提高焦点阅读量。根据你的需要,合理配置两者的比例。
8.遇到感兴趣的内容,用户仅会多看一眼副标题
不要过分坚持副标题固定的格式——保证他们的相关性和兴趣。你也可以让副标题包含关键词,这样可以有效利用搜索引擎,让它带来读者。
9.人们大都只浏览网页的小部分内容
如果在用户浏览的时候提供信息使他们尽快锁定目标,就可以把这一点发展成为你的优势。突出某些部分或者创建项目列表使网页信息容易找到和阅读。
10.简短的段落相对于长段落来说有更好的表现力
网页信息是为大多数强调快速浏览的无联网用户提供的。除非上下文的衔接要求,保持信息由简短的段落和句式组成,例如 这个电子商务网站 的产品介绍。
11.根据视觉锁定,一栏格式比多栏格式拥有更好的表现力
别让过多的信息把网站来访者淹没。大多数情况下,简洁更具力量。多栏内容容易被用户忽视,我们需要消除这些干扰。
12.网页顶部和左边的广告更能吸引眼球
如需要在网站植入广告,试图使他们融入网页的左上部,这样他们才能吸引到最大的视觉注意力。当然,用户仅仅会注意到这些广告,这并不意味着他们会用鼠标点击。所以不要为了提高广告的注意力而牺牲原有的网站设计。
13.将广告放置与最佳内容一旁也可以提升注意力
如果想要提升广告的可视性和点击率,可以将其设置于最能引起人兴趣的内容一旁,整合进网页的设计里。这样,用户既可以找到所需的内容,你也能提升广告的效益。
14.在各种测试中,人们阅读文字广告最为专心。
正如上面提到的,一般的互联网用户不会花费太多时间用于查看那些一眼就能看出是广告的内容。这就是文字广告表现出众的原因。他们并没有分散注意力,而是与网页的其它部分内容融为一体,这让他们减少了对读者的视觉刺激,也使这一广告形式获得成功的阅读率。
15.越大的图像吸引越多的注意力
如果要在网页中使用图片,那越大越好。人们更倾向于查看那些能够清楚地看到细节和获取信息的图像。要保证你所用的图片与文章内容相关,否则它更容易被忽视。大多数读者都拥有高速的连接速度,所以请放心在你的网站上使用那些较大体积的图片。
16.干净、清晰的特写图片能吸引更多的视觉注意
可能那些抽象的艺术图片会让你的网站看起来很有味道,但是他们并不会吸引多少读者的注意力。如果你需要使用到这些图片,请确保所用图片的清晰以及其表达内容的简单可读性。必须注意的是,那些与真实的“人”相关的图片比所谓的模特图片更为“优秀”。
17.标题能吸引眼球
浏览网页时,读者能发现的第一内容是标题。确保网页的所有相关链接畅通和有效,以让读者顺利的通过网站进一步搜索。
18.用户花费大量时间察看按钮和菜单
所以,你需要花费额外的时间维护你的精心设计。毕竟,他们不仅吸引了读者的眼球,更是网站设计的重要组成要素。
19.表单格式可以延长读者的注意时间
分解内容和段落,大量使用表单形式来表现你的文章,可以保证读者的浏览率。使用数字和其它标记符号来突出文章的重要内容,会让网站更容易浏览,用户更快的找到所需的信息。
20.避免呈现大块的文本
研究显示,一般的网络浏览者不会花费时间去阅读大块的文本,无论他们有多重要或写得多好。因此,必须把这些大文本分解为若干小段落。突出重要的地方,放置点击的按钮也可以提高用户的注意力。
21.格式可以吸引注意力
在文中使用粗体、大写、彩体、下划线可以帮助用户获取正文所表达的最主要的信息。使用时需要谨慎,因为过多的使用会使你的网页难以阅读,把读者吓跑。
22.利用好空白
尽管把网页的每寸空间都填满这个想法十分诱人,但事实上让网站留出部分剩余更为不错。网站的过量信息会把用户淹没,同时他们也会忘记所提供的大部分的内容。所以保持网页的简洁,给读者预留出一些视觉空间来供读者休息。
23.放置于网页顶部,导航工具的作用将更好的发挥
理想情况下,你不会满足于当读者打开你的网站时仅浏览初始页,而是希望他们浏览翻阅,察看其它感兴趣的内容。将导航器置于网页顶部,就可以让用户通过使用这个工具轻松的找到所需的目标内容。

网站的视觉路径和版式设计

cooper谈到用户的视觉路径一般是:从上到下,从左到右。好的视觉设计路径应该是顺应这样的用户习惯,糟糕的设计会让用户无所适从,焦点到处都是。当然,上图的视觉路径图并非绝对的,浏览习惯因人而异。

网站中方块
因为人们从接触信息以来,信息的呈现就是以方块式存在:报纸、书,单个字成点,一行字成线,一段字成面,而这个面当然是以方形呈现的效率最高。网站的视觉设计大部分其实都是在拼方块。网站中的方块能很好地引导用户的视觉路径,用户可以通过区块来分辨这个区域的信息是否是自己需要的,从而可以迅速缩小范围细致寻找或者浏览下一个区块,比如yahoo的首页,从大块上来看,用户很容易分辨出4个大区块,每个区块里面又有小的区块。
方块感越强越能给用户方向感。
方块越少越好。
尽量用留白做视觉区分。


对齐和间距
视觉设计最简单,也是最容易忽略的就是对齐。检查的方法就是查看每个方块中的边线,方块与方块之间的边线,尤其是纵向维度。间距的一般规律:字距小于行距,行距小于段距,段距小于块距。检查的方法可以尝试将网站的背景图案、线条全部去掉,看是否还能保持想要的区块感。
拿淘宝的新首页举个细节的例子(右边是我调整后的)。有时候我们不需要花心思做多么漂亮的图标和颜色搭配,用心地调整好网站的每一个像素或许也能让它焕然一新。

主次关系
怎么对用户引导的关键就在于怎么处理主次关系。说白了就是对比,从视觉的角度上看:形状的大小,颜色,摆放的位置都会影响信息的重要与否。从大的区块来看,不要平均分割页面,三栏的设计应该让其中一栏明显短一些。从局部来看,也要把握信息呈现的节奏,比如yahoo中间新闻栏的设计,大图带大标题是第一要点,小图带字是第二要点,纯文本第三,节奏感、主次关系非常强。
常见问题
视觉设计师不懂代码,前端设计师在视觉方面又不专业。常常是实现出来的产品跟视觉设计出来的图片有所偏差。建议视觉设计师跟进调整。
广告图片破坏视觉效果。如果网站足够牛的话,可以让广告方遵循视觉规范。如果不行的话,起码设计师还能决定广告的尺寸,位置等等。
写这篇文章刚刚赶上4月份新浪、腾讯、淘宝的首页改版。单纯从视觉设计的角度上看,腾讯非常清爽,很用心。

Zend Studio does not contain PDO extensions

I've just installed Zend Studio 6 and Zend ZendFramework-1.5 onto my Ubuntu 8. It already has Apache 2.0 and MySQL 5.0 and PHP 5.2.1 running.

I used PHPunit to test My class extended from Zend_db_Table, but I can not run it normally!

Result :
when I tried to run the script inside the Zend Studio. It gave me this error
"Debug Error: /media/sda5/workspace/library/Zend/Db/Adapter/Pdo/Abstract.php line 104 - Uncaught exception 'Zend_Db_Adapter_Exception' with message 'The mysql driver is not currently installed' in /media/sda5/workspace/library/Zend/Db/Adapter/Pdo/Abstract.php:104
Stack trace:
#0 /media/sda5/workspace/library/Zend/Db/Adapter/Abstract.php(390): Zend_Db_Adapter_Pdo_Abstract->_connect()
#1 /media/sda5/workspace/library/Zend/Db/Adapter/Pdo/Abstract.php(206): Zend_Db_Adapter_Abstract->query('SET NAMES utf8', Array)
#2 /media/sda5/workspace/coojs/test/DataAdapter.php(7): Zend_Db_Adapter_Pdo_Abstract->query('SET NAMES utf8')
#3 /media/sda5/workspace/coojs/test/models/User/Data/User_Data_TableTest.php(6): require_once('/media/sda5/wor...')
#4 /usr/local/Zend/ZendStudioForEclipse-6.0.0/plugins/com.zend.php.phpunit_6.0.0.v20080107/resources/ZendPHPUnit.php(65): require_once('/media/sda5/wor...')
#5 {main}
thrown
Well ,this is the problem! how to resolve this problem?


the resolving method is:

1 set the adapter type to phpmysqli

[code]

/** * This is the PHP (No pdo) way. Please notice the PHP_MYSQL */

require_once 'Zend.php';

require_once 'Zend/Db.php';

$config = array( 'host'
=> 'localhost', 'username' => 'sqluser', 'password' => 'sqlpass',
'dbname' => 'databasename',);

$db = Zend_Db::factory('Mysqli', $config); //Is the adapter be PHP_Mysql?

2 To add a PHP executable to the list in IDE: I used the PHP CGI in ZendCore

3 Anything will oK! the test is run successful!



4/28/2008

《测试驱动开发》读书笔记

测试驱动开发的具体过程
测试驱动开发大体上可以归纳为以下几个步骤:
列出测试清单
编写测试程序:测试处于不可运行状态,包括不能通过编译
使测试通过:测试处于可运行状态,包括编译通过和测试通过
重构代码以消除重复,优化设计结构
测试驱动开发的一个基本的原则就是,测试无法通过运行和重复设计是编写代码的仅有的两个理由和前提;如果测试可以通过运行且没有重复设计,就绝不可以编写代码。

4/27/2008

测试驱动开发全功略

{TDD的目标}

Clean Code That Works

这句话的含义是,事实上我们只做两件事情:让代码奏效(Work)和让代码洁净(Clean),前者是把事情做对,后者是把事情做好。想想看,其实 我们平时所做的所有工作,除去无用的工作和错误的工作以外,真正正确的工作,并且是真正有意义的工作,其实也就只有两大类:增加功能和提升设计,而TDD 正是在这个原则上产生的。如果您的工作并非我们想象的这样,(这意味着您还存在第三类正确有意义的工作,或者您所要做的根本和我们在说的是两回事),那么 这告诉我们您并不需要TDD,或者不适用TDD。而如果我们偶然猜对(这对于我来说是偶然,而对于Kent Beck和Martin Fowler这样的大师来说则是辛勤工作的成果),那么恭喜您,TDD有可能成为您显著提升工作效率的一件法宝。请不要将信将疑,若即若离,因为任何一项 新的技术——只要是从根本上改变人的行为方式的技术——就必然使得相信它的人越来越相信,不信的人越来越不信。这就好比学游泳,唯一能学会游泳的途径就是 亲自下去游,除此之外别无他法。这也好比成功学,即使把卡耐基或希尔博士的书倒背如流也不能拥有积极的心态,可当你以积极的心态去成就了一番事业之后,你 就再也离不开它了。相信我,TDD也是这样!想试用TDD的人们,请遵循下面的步骤:

编写TestCase --> 实现TestCase --> 重构
(确定范围和目标) (增加功能) (提升设计)

[友情提示:敏捷建模中的一个相当重要的实践被称为:Prove it With Code,这种想法和TDD不谋而合。]

{TDD的优点}

    『充满吸引力的优点』

  1. 完工时完工。表明我可以很清楚的看到自己的这段工作已经结束了,而传统的方式很难知道什么时候编码工作结束了。
  2. 全面正确的认识代码和利用代码,而传统的方式没有这个机会。
  3. 为利用你成果的人提供Sample,无论它是要利用你的源代码,还是直接重用你提供的组件。
  4. 开发小组间降低了交流成本,提高了相互信赖程度。
  5. 避免了过渡设计。
  6. 系统可以与详尽的测试集一起发布,从而对程序的将来版本的修改和扩展提供方便。
  7. TDD给了我们自信,让我们今天的问题今天解决,明天的问题明天解决,今天不能解决明天的问题,因为明天的问题还没有出现(没有TestCase),除非有TestCase否则我决不写任何代码;明天也不必担心今天的问题,只要我亮了绿灯。

    『不显而易见的优点』

  8. 逃避了设计角色。对于一个敏捷的开发小组,每个人都在做设计。
  9. 大部分时间代码处在高质量状态,100%的时间里成果是可见的。
  10. 由于可以保证编写测试和编写代码的是相同的程序员,降低了理解代码所花费的成本。
  11. 为减少文档和代码之间存在的细微的差别和由这种差别所引入的Bug作出杰出贡献。
  12. 在预先设计和紧急设计之间建立一种平衡点,为你区分哪些设计该事先做、哪些设计该迭代时做提供了一个可靠的判断依据。

    『有争议的优点』

  13. 事实上提高了开发效率。每一个正在使用TDD并相信TDD的人都会相信这一点,但观望者则不同,不相信TDD的人甚至坚决反对这一点,这很正常,世界总是这样。
  14. 发现比传统测试方式更多的Bug。
  15. 使IDE的调试功能失去意义,或者应该说,避免了令人头痛的调试和节约了调试的时间。
  16. 总是处在要么编程要么重构的状态下,不会使人抓狂。(两顶帽子)
  17. 单元测试非常有趣。
{TDD的步骤}
编写TestCase --> 实现TestCase --> 重构
(不可运行) (可运行) (重构)
步骤 制品
(1)快速新增一个测试用例 新的TestCase
(2)编译所有代码,刚刚写的那个测试很可能编译不通过 原始的TODO List
(3)做尽可能少的改动,让编译通过 Interface
(4)运行所有的测试,发现最新的测试不能编译通过 -(Red Bar)
(5)做尽可能少的改动,让测试通过 Implementation
(6)运行所有的测试,保证每个都能通过 -(Green Bar)
(7)重构代码,以消除重复设计 Clean Code That Works

{FAQ}

[什么时候重构?]
如果您在软件公司工作,就意味着您成天都会和想通过重构改善代码质量的想法打交道,不仅您如此,您的大部 分同事也都如此。可是,究竟什么时候该重构,什么情况下应该重构呢?我相信您和您的同事可能有很多不同的看法,最常见的答案是“该重构时重构”,“写不下 去的时候重构”,和“下一次迭代开始之前重构”,或者干脆就是“最近没时间,就不重构了,下次有时间的时候重构吧”。正如您已经预见到我想说的——这些想 法都是对重构的误解。重构不是一种构建软件的工具,不是一种设计软件的模式,也不是一个软件开发过程中的环节,正确理解重构的人应该把重构看成一种书写代 码的方式,或习惯,重构时时刻刻有可能发生。在TDD中,除去编写测试用例和实现测试用例之外的所有工作都是重构,所以,没有重构任何设计都不能实现。至 于什么时候重构嘛,还要分开看,有三句话是我的经验:实现测试用例时重构代码,完成某个特性时重构设计,产品的重构完成后还要记得重构一下测试用例哦。

[什么时候设计?]
这个问题比前面一个要难回答的多,实话实说,本人在依照TDD开发软件的时候也常常被这个问题困扰,总是 觉得有些问题应该在写测试用例之前定下来,而有些问题应该在新增一个一个测试用例的过程中自然出现,水到渠成。所以,我的建议是,设计的时机应该由开发者 自己把握,不要受到TDD方式的限制,但是,不需要事先确定的事一定不能事先确定,免得捆住了自己的手脚。

[什么时候增加新的TestCase?]
没事做的时候。通常我们认为,如果你要增加一个新的功能,那么先写一个不能通过的 TestCase;如果你发现了一个bug,那么先写一个不能通过的TestCase;如果你现在什么都没有,从0开始,请先写一个不能通过的 TestCase。所有的工作都是从一个TestCase开始。此外,还要注意的是,一些大师要求我们每次只允许有一个TestCase亮红灯,在这个 TestCase没有Green之前不可以写别的TestCase,这种要求可以适当考虑,但即使有多个TestCase亮红灯也不要紧,并未违反TDD 的主要精神。

[TestCase该怎么写?]
测试用例的编写实际上就是两个过程:使用尚不存在的代码和定义这些代码的执行结果。所以一个 TestCase也就应该包括两个部分——场景和断言。第一次写TestCase的人会有很大的不适应的感觉,因为你之前所写的所有东西都是在解决问题, 现在要你提出问题确实不大习惯,不过不用担心,你正在做正确的事情,而这个世界上最难的事情也不在于如何解决问题,而在于ask the right question!

[TDD能帮助我消除Bug吗?]
答:不能!千万不要把“测试”和“除虫”混为一谈!“除虫”是指程序员通过自己的努力来减 少bug的数量(消除bug这样的字眼我们还是不要讲为好^_^),而“测试”是指程序员书写产品以外的一段代码来确保产品能有效工作。虽然TDD所编写 的测试用例在一定程度上为寻找bug提供了依据,但事实上,按照TDD的方式进行的软件开发是不可能通过TDD再找到bug的(想想我们前面说的“完工时 完工”),你想啊,当我们的代码完成的时候,所有的测试用例都亮了绿灯,这时隐藏在代码中的bug一个都不会露出马脚来。

但是,如果要问“测试”和“除虫”之间有什么联系,我相信还是有很多话可以讲的,比如TDD事实上减少了bug的数量,把查找bug战役的关注点从 全线战场提升到代码战场以上。还有,bug的最可怕之处不在于隐藏之深,而在于满天遍野。如果你发现了一个用户很不容易才能发现的bug,那么不一定对工 作做出了什么杰出贡献,但是如果你发现一段代码中,bug的密度或离散程度过高,那么恭喜你,你应该抛弃并重写这段代码了。TDD避免了这种情况,所以将 寻找bug的工作降低到了一个新的低度。

[我该为一个Feature编写TestCase还是为一个类编写TestCase?]
初学者常问的问题。虽然我们从TDD 的说明书上看到应该为一个特性编写相应的TestCase,但为什么著名的TDD大师所写的TestCase都是和类/方法一一对应的呢?为了解释这个问 题,我和我的同事们都做了很多试验,最后我们得到了一个结论,虽然我不知道是否正确,但是如果您没有答案,可以姑且相信我们。

我们的研究结果表明,通常在一个特性的开发开始时,我们针对特性编写测试用例,如果您发现这个特性无法用TestCase表达,那么请将这个特性细 分,直至您可以为手上的特性写出TestCase为止。从这里开始是最安全的,它不会导致任何设计上重大的失误。但是,随着您不断的重构代码,不断的重构 TestCase,不断的依据TDD的思想做下去,最后当产品伴随测试用例集一起发布的时候,您就会不经意的发现经过重构以后的测试用例很可能是和产品中 的类/方法一一对应的。

[什么时候应该将全部测试都运行一遍?]
Good Question!大师们要求我们每次重构之后都要完整的运行一遍测试用例。这个要求可以理解,因为重构很可能会改变整个代码的结构或设计,从而导致不可 预见的后果,但是如果我正在开发的是一个ERP怎么办?运行一遍完整的测试用例可能将花费数个小时,况且现在很多重构都是由工具做到的,这个要求的可行性 和前提条件都有所动摇。所以我认为原则上你可以挑几个你觉得可能受到本次重构影响的TestCase去run,但是如果运行整个测试包只要花费数秒的时 间,那么不介意你按大师的要求去做。

[什么时候改进一个TestCase?]
增加的测试用例或重构以后的代码导致了原来的TestCase的失去了效果,变得无 意义,甚至可能导致错误的结果,这时是改进TestCase的最好时机。但是有时你会发现,这样做仅仅导致了原来的TestCase在设计上是臃肿的,或 者是冗余的,这都不要紧,只要它没有失效,你仍然不用去改进它。记住,TestCase不是你的产品,它不要好看,也不要怎么太科学,甚至没有性能要求, 它只要能完成它的使命就可以了——这也证明了我们后面所说的“用Ctrl-C/Ctrl-V编写测试用例”的可行性。

但是,美国人的想法其实跟我们还是不太一样,拿托尼巴赞的MindMap来说吧,其实画MindMap只是为了表现自己的思路,或记忆某些重要的事 情,但托尼却建议大家把MindMap画成一件艺术品,甚至还有很多艺术家把自己画的抽象派MindMap拿出来帮助托尼做宣传。同样,大师们也要求我们 把TestCase写的跟代码一样质量精良,可我想说的是,现在国内有几个公司能把产品的代码写的精良??还是一步一步慢慢来吧。

[为什么原来通过的测试用例现在不能通过了?]
这是一个警报,Red Alert!它可能表达了两层意思——都不是什么好意思——1)你刚刚进行的重构可能失败了,或存在一些错误未被发现,至少重构的结果和原来的代码不等价 了。2)你刚刚增加的TestCase所表达的意思跟前面已经有的TestCase相冲突,也就是说,新增的功能违背了已有的设计,这种情况大部分可能是 之前的设计错了。但无论哪错了,无论是那层意思,想找到这个问题的根源都比TDD的正常工作要难。

[我怎么知道那里该有一个方法还是该有一个类?]
这个问题也是常常出现在我的脑海中,无论你是第一次接触TDD或者已经成为 TDD专家,这个问题都会缠绕着你不放。不过问题的答案可以参考前面的“什么时候设计”一节,答案不是唯一的。其实多数时候你不必考虑未来,今天只做今天 的事,只要有重构工具,从方法到类和从类到方法都很容易。

[我要写一个TestCase,可是不知道从哪里开始?]
从最重要的事开始,what matters most?从脚下开始,从手头上的工作开始,从眼前的事开始。从一个没有UI的核心特性开始,从算法开始,或者从最有可能耽误时间的模块开始,从一个最严 重的bug开始。这是TDD主义者和鼠目寸光者的一个共同点,不同点是前者早已成竹在胸。

[为什么我的测试总是看起来有点愚蠢?]
哦?是吗?来,握个手,我的也是!不必担心这一点,事实上,大师们给的例子也相当愚 蠢,比如一个极端的例子是要写一个两个int变量相加的方法,大师先断言2+3=5,再断言5+5=10,难道这些代码不是很愚蠢吗?其实这只是一个极端 的例子,当你初次接触TDD时,写这样的代码没什么不好,以后当你熟练时就会发现这样写没必要了,要记住,谦虚是通往TDD的必经之路!从经典开发方法转 向TDD就像从面向过程转向面向对象一样困难,你可能什么都懂,但你写出来的类没有一个纯OO的!我的同事还告诉我真正的太极拳,其速度是很快的,不比任 何一个快拳要慢,但是初学者(通常是指学习太极拳的前10年)太不容易把每个姿势都做对,所以只能慢慢来。

[什么场合不适用TDD?]
问的好,确实有很多场合不适合使用TDD。比如对软件质量要求极高的军事或科研产品——神州六号,人命关天的软件——医疗设备,等等,再比如设计很重要必须提前做好的软件,这些都不适合TDD,但是不适合TDD不代表不能写TestCase,只是作用不同,地位不同罢了。

{Best Practise}

[微笑面对编译错误]
学生时代最害怕的就是编译错误,编译错误可能会被老师视为上课不认真听课的证据,或者同学间相互嘲笑的 砝码。甚至离开学校很多年的老程序员依然害怕它就像害怕迟到一样,潜意识里似乎编译错误极有可能和工资挂钩(或者和智商挂钩,反正都不是什么好事)。其 实,只要提交到版本管理的代码没有编译错误就可以了,不要担心自己手上的代码的编译错误,通常,编译错误都集中在下面三个方面:
(1)你的代码存在低级错误
(2)由于某些Interface的实现尚不存在,所以被测试代码无法编译
(3)由于某些代码尚不存在,所以测试代码无法编译
请注意第二点与第三点完全不同,前者表明设计已存在,而实现不存在导致的编译错误;后者则指仅有TestCase而其它什么都没有的情况,设计和实现都不存在,没有Interface也没有Implementation。

另外,编译器还有一个优点,那就是以最敏捷的身手告诉你,你的代码中有那些错误。当然如果你拥有Eclipse这样可以及时提示编译错误的IDE,就不需要这样的功能了。

[重视你的计划清单]
在非TDD的情况下,尤其是传统的瀑布模型的情况下,程序员不会不知道该做什么,事实上,总是有设计或 者别的什么制品在引导程序员开发。但是在TDD的情况下,这种优势没有了,所以一个计划清单对你来说十分重要,因为你必须自己发现该做什么。不同性格的人 对于这一点会有不同的反应,我相信平时做事没什么计划要依靠别人安排的人(所谓将才)可能略有不适应,不过不要紧,Tasks和Calendar(又称效 率手册)早已成为现代上班族的必备工具了;而平时工作生活就很有计划性的人,比如我:),就会更喜欢这种自己可以掌控Plan的方式了。

[废黜每日代码质量检查]
如果我没有记错的话,PSP对于个人代码检查的要求是蛮严格的,而同样是在针对个人的问题上, TDD却建议你废黜每日代码质量检查,别起疑心,因为你总是在做TestCase要求你做的事情,并且总是有办法(自动的)检查代码有没有做到这些事情 ——红灯停绿灯行,所以每日代码检查的时间可能被节省,对于一个严格的PSP实践者来说,这个成本还是很可观的!

此外,对于每日代码质量检查的另一个好处,就是帮助你认识自己的代码,全面的从宏观、微观、各个角度审视自己的成果,现在,当你依照TDD做事时,这个优点也不需要了,还记得前面说的TDD的第二个优点吗,因为你已经全面的使用了一遍你的代码,这完全可以达到目的。

但是,问题往往也并不那么简单,现在有没有人能告诉我,我如何全面审视我所写的测试用例呢?别忘了,它们也是以代码的形式存在的哦。呵呵,但愿这个 问题没有把你吓到,因为我相信到目前为止,它还不是瓶颈问题,况且在编写产品代码的时候你还是会自主的发现很多测试代码上的没考虑到的地方,可以就此修改 一下。道理就是如此,世界上没有任何方法能代替你思考的过程,所以也没有任何方法能阻止你犯错误,TDD仅能让你更容易发现这些错误而已。

[如果无法完成一个大的测试,就从最小的开始]
如果我无法开始怎么办,教科书上有个很好的例子:我要写一个电影列表的类,我 不知道如何下手,如何写测试用例,不要紧,首先想象静态的结果,如果我的电影列表刚刚建立呢,那么它应该是空的,OK,就写这个断言吧,断言一个刚刚初始 化的电影列表是空的。这不是愚蠢,这是细节,奥运会五项全能的金牌得主玛丽莲·金是这样说的:“成功人士的共同点在于……如果目标不够清晰,他们会首先做 通往成功道路上的每一个细小步骤……”。

[尝试编写自己的xUnit]
Kent Beck建议大家每当接触一个新的语言或开发平台的时候,就自己写这个语言或平台的xUnit,其实几乎所有常用的语言和平台都已经有了自己的 xUnit,而且都是大同小异,但是为什么大师给出了这样的建议呢。其实Kent Beck的意思是说通过这样的方式你可以很快的了解这个语言或平台的特性,而且xUnit确实很简单,只要知道原理很快就能写出来。这对于那些喜欢自己写 底层代码的人,或者喜欢控制力的人而言是个好消息。

[善于使用Ctrl-C/Ctrl-V来编写TestCase]
不必担心TestCase会有代码冗余的问题,让它冗余好了。

[永远都是功能First,改进可以稍后进行]
上面这个标题还可以改成另外一句话:避免过渡设计!

[淘汰陈旧的用例]
舍不得孩子套不着狼。不要可惜陈旧的用例,因为它们可能从概念上已经是错误的了,或仅仅会得出错误的结果,或者在某次重构之后失去了意义。当然也不一定非要删除它们,从TestSuite中除去(JUnit)或加上Ignored(NUnit)标签也是一个好办法。

[用TestCase做试验]
如果你在开始某个特性或产品的开发之前对某个领域不太熟悉或一无所知,或者对自己在该领域里的 能力一无所知,那么你一定会选择做试验,在有单元测试作工具的情况下,建议你用TestCase做试验,这看起来就像你在写一个验证功能是否实现的 TestCase一样,而事实上也一样,只不过你所验证的不是代码本身,而是这些代码所依赖的环境。

[TestCase之间应该尽量独立]
保证单独运行一个TestCase是有意义的。

[不仅测试必须要通过的代码,还要测试必须不能通过的代码]
这是一个小技巧,也是不同于设计思路的东西。像越界的值或者乱 码,或者类型不符的变量,这些输入都可能会导致某个异常的抛出,或者导致一个标示“illegal parameters”的返回值,这两种情况你都应该测试。当然我们无法枚举所有错误的输入或外部环境,这就像我们无法枚举所有正确的输入和外部环境一 样,只要TestCase能说明问题就可以了。

[编写代码的第一步,是在TestCase中用Ctrl-C]
这是一个高级技巧,呃,是的,我是这个意思,我不是说这个技巧 难以掌握,而是说这个技巧当且仅当你已经是一个TDD高手时,你才能体会到它的魅力。多次使用TDD的人都有这样的体会,既然我的TestCase已经写 的很好了,很能说明问题,为什么我的代码不能从TestCase拷贝一些东西来呢。当然,这要求你的TestCase已经具有很好的表达能力,比如断言f (5)=125的方式显然没有断言f(5)=5^(5-2)表达更多的内容。

[测试用例包应该尽量设计成可以自动运行的]
如果产品是需要交付源代码的,那我们应该允许用户对代码进行修改或扩充后在自己 的环境下run整个测试用例包。既然通常情况下的产品是可以自动运行的,那为什么同样作为交付用户的制品,测试用例包就不是自动运行的呢?即使产品不需要 交付源代码,测试用例包也应该设计成可以自动运行的,这为测试部门或下一版本的开发人员提供了极大的便利。

[只亮一盏红灯]
大师的建议,前面已经提到了,仅仅是建议。

[用TestCase描述你发现的bug]
如果你在另一个部门的同事使用了你的代码,并且,他发现了一个bug,你猜他会怎 么做?他会立即走到你的工位边上,大声斥责说:“你有bug!”吗?如果他胆敢这样对你,对不起,你一定要冷静下来,不要当面回骂他,相反你可以微微一 笑,然后心平气和的对他说:“哦,是吗?那么好吧,给我一个TestCase证明一下。”现在局势已经倒向你这一边了,如果他还没有准备好回答你这致命的 一击,我猜他会感到非常羞愧,并在内心责怪自己太莽撞。事实上,如果他的TestCase没有过多的要求你的代码(而是按你们事前的契约),并且亮了红 灯,那么就可以确定是你的bug,反之,对方则无理了。用TestCase描述bug的另一个好处是,不会因为以后的修改而再次暴露这个bug,它已经成 为你发布每一个版本之前所必须检查的内容了。

{关于单元测试}

单元测试的目标是

Keep the bar green to keep the code clean

这句话的含义是,事实上我们只做两件事情:让代码奏效(Keep the bar green)和让代码洁净(Keep the code clean),前者是把事情做对,后者是把事情做好,两者既是TDD中的两顶帽子,又是xUnit架构中的因果关系。

单元测试作为软件测试的一个类别,并非是xUnit架构创造的,而是很早就有了。但是xUnit架构使得单元测试变得直接、简单、高效和规范,这也 是单元测试最近几年飞速发展成为衡量一个开发工具和环境的主要指标之一的原因。正如Martin Fowler所说:“软件工程有史以来从没有如此众多的人大大收益于如此简单的代码!”而且多数语言和平台的xUnit架构都是大同小异,有的仅是语言不 同,其中最有代表性的是JUnit和NUnit,后者是前者的创新和扩展。一个单元测试框架xUnit应该:1)使每个TestCase独立运行;2)使 每个TestCase可以独立检测和报告错误;3)易于在每次运行之前选择TestCase。下面是我枚举出的xUnit框架的概念,这些概念构成了当前 业界单元测试理论和工具的核心:

[测试方法/TestMethod]
测试的最小单位,直接表示为代码。

[测试用例/TestCase]
由多个测试方法组成,是一个完整的对象,是很多TestRunner执行的最小单位。

[测试容器/TestSuite]
由多个测试用例构成,意在把相同含义的测试用例手动安排在一起,TestSuite可以呈树状结构因而便于管理。在实现时,TestSuite形式上往往也是一个TestCase或TestFixture。

[断言/Assertion]
断言一般有三类,分别是比较断言(如assertEquals),条件断言(如isTrue),和断言工具(如fail)。

[测试设备/TestFixture]
为每个测试用例安排一个SetUp方法和一个TearDown方法,前者用于在执行该测试用例或该用例中的每个测试方法前调用以初始化某些内容,后者在执行该测试用例或该用例中的每个方法之后调用,通常用来消除测试对系统所做的修改。

[期望异常/Expected Exception]
期望该测试方法抛出某种指定的异常,作为一个“断言”内容,同时也防止因为合情合理的异常而意外的终止了测试过程。

[种类/Category]
为测试用例分类,实际使用时一般有TestSuite就不再使用Category,有Category就不再使用TestSuite。

[忽略/Ignored]
设定该测试用例或测试方法被忽略,也就是不执行的意思。有些被抛弃的TestCase不愿删除,可以定为Ignored。

[测试执行器/TestRunner]
执行测试的工具,表示以何种方式执行测试,别误会,这可不是在代码中规定的,完全是与测试内容无关的行为。比如文本方式,AWT方式,swing方式,或者Eclipse的一个视图等等。

{实例:Fibonacci数列}

下面的Sample展示TDDer是如何编写一个旨在产生Fibonacci数列的方法。
(1)首先写一个TC,断言fib(1) = 1;fib(2) = 1;这表示该数列的第一个元素和第二个元素都是1。

public void testFab() {
assertEquals(
1, fib(1));
assertEquals(
1, fib(2));
}

(2)上面这段代码不能编译通过,Great!——是的,我是说Great!当然,如果你正在用的是Eclipse那你不需要编译,Eclipse 会告诉你不存在fib方法,单击mark会问你要不要新建一个fib方法,Oh,当然!为了让上面那个TC能通过,我们这样写:

public int fib( int n ) {
return 1;
}

(3)现在那个TC亮了绿灯,wow!应该庆祝一下了。接下来要增加TC的难度了,测第三个元素。

public void testFab() {
assertEquals(
1, fib(1));
assertEquals(
1, fib(2));
assertEquals(
2, fib(3));
}

不过这样写还不太好看,不如这样写:

public void testFab() {
assertEquals(
1, fib(1));
assertEquals(
1, fib(2));
assertEquals(fib(
1)+fib(2), fib(3));
}

(4)新增加的断言导致了红灯,为了扭转这一局势我们这样修改fib方法,其中部分代码是从上面的代码中Ctrl-C/Ctrl-V来的:

public int fib( int n ) {
if ( n == 3 ) return fib(1)+fib(2);
return 1;
}

(5)天哪,这真是个贱人写的代码!是啊,不是吗?因为TC就是产品的蓝本,产品只要恰好满足TC就ok。所以事情发展到这个地步不是fib方法的错,而是TC的错,于是TC还要进一步要求:

public void testFab() {
assertEquals(
1, fib(1));
assertEquals(
1, fib(2));
assertEquals(fib(
1)+fib(2), fib(3));
assertEquals(fib(
2)+fib(3), fib(4));
}

(6)上有政策下有对策。

public int fib( int n ) {
if ( n == 3 ) return fib(1)+fib(2);
if ( n == 4 ) return fib(2)+fib(3);
return 1;
}

(7)好了,不玩了。现在已经不是贱不贱的问题了,现在的问题是代码出现了冗余,所以我们要做的是——重构:

public int fib( int n ) {
if ( n == 1 || n == 2return 1;
else return fib( n - 1 ) + fib( n - 2 );
}

(8)好,现在你已经fib方法已经写完了吗?错了,一个危险的错误,你忘了错误的输入了。我们令0表示Fibonacci中没有这一项。

public void testFab() {
assertEquals(
1, fib(1));
assertEquals(
1, fib(2));
assertEquals(fib(
1)+fib(2), fib(3));
assertEquals(fib(
2)+fib(3), fib(4));
assertEquals(
0, fib(0));
assertEquals(
0, fib(-1));
}

then change the method fib to make the bar grean:

public int fib( int n ) {
if ( n <= 0 ) return 0;
if ( n == 1 || n == 2return 1;
else return fib( n - 1 ) + fib( n - 2 );
}

(9)下班前最后一件事情,把TC也重构一下:

public void testFab() {
int cases[][] = {
{
0, 0}, {-1, 0}, //the wrong parameters
{1, 1}, {2, 1}}; //the first 2 elements

for (int i = 0; i < cases.length; i++)
assertEquals( cases[i][
1], fib(cases[i][0]) );

//the rest elements
for (int i = 3; i < 20; i++)
assertEquals(fib(i
-1)+fib(i-2), fib(i));
}

The Three Rules of TDD

by
Over the years I have come to describe Test Driven Development in terms of three simple rules. They are:

  1. You are not allowed to write any production code unless it is to make a failing unit test pass.
  2. You are not allowed to write any more of a unit test than is sufficient to fail; and compilation failures are failures.
  3. You are not allowed to write any more production code than is sufficient to pass the one failing unit test.

You must begin by writing a unit test for the functionality that you intend to write. But by rule 2, you can't write very much of that unit test. As soon as the unit test code fails to compile, or fails an assertion, you must stop and write production code. But by rule 3 you can only write the production code that makes the test compile or pass, and no more.

If you think about this you will realize that you simply cannot write very much code at all without compiling and executing something. Indeed, this is really the point. In everything we do, whether writing tests, writing production code, or refactoring, we keep the system executing at all times. The time between running tests is on the order of seconds, or minutes. Even 10 minutes is too long.

Too see this in operation, take a look at The Bowling Game Kata.

40 signs you really are a lousy PHP programmer

This is something I prefer to call my "programming list of shame". Although having a formal university education with courses on software engineering, enterprise software architecture & database design I have been guilty of every single one of those things at one time or another. This is completely subjective & Eclipse oriented


You are a lousy PHP programmer if you



  1. don't comment your code properly with something like phpDoc

  2. don't see the need and/or benefits of a good programming IDE like Zend Studio or Eclipse PDT

  3. have never used some form of version control like Subclipse

  4. don't adopt some coding & naming standards and general conventions and stick to to them at least throughout the project

  5. don't use a consistent methodology

  6. don't escape and/or validate properly input or sql queries

  7. don't plan your application thoroughly before starting to code

  8. don't use test-driven development

  9. don't program & test with error reporting on

  10. don't see the benefits of a debugger

  11. don't refactor your code

  12. don't keep the different layers seperated using something like MVC

  13. don't know what these stand for: KISS, DRY, MVC, OOP, REST

  14. don't return content but echo or print it from your functions or classes

  15. have never seen the advantage of unit tests or testing in general

  16. return HTML, not data, strings, or objects.

  17. hard code messages and configuration parameters

  18. don't optimize your sql queries

  19. don't use __autoload

  20. don't allow intelligent error handling

  21. use $_GET instead of $_POST for any destructive actions

  22. don't know how to use regular expressions

  23. you've never heard of sql injection or cross-site scripting

  24. don't allow simple configuration, can be parameters passed to a class’s constructor, set/get methods called later, or constants defined at a runtime.

  25. don't understand the benefits and limitations of Object Oriented Programming

  26. misuse OOP / everything you write , no matter how small is OOP

  27. you think reusable software equals/requires your code to be OOP

  28. don't choose intelligent defaults

  29. don't have one single configuration file

  30. don't want the file contents to be seen, but give it a .inc extension instead of .php

  31. don't use a database abstraction layer

  32. don't keep it DRY, Don't repeat yourself. If you have to copy and paste or duplicate something your design may be off.

  33. don't make a function/class/method do just one thing and don't make them interact.

  34. don't try to take advantage of OOP specific features like abstract/interface classes, inheritage polymorphism & access modifiers.

  35. don't optimize your application design with established design patterns

  36. don't allow your user to define a base directory if you have multiple files and/or directories

  37. pollute the global namespace, one option is to prefix the functions in your library with a common string

  38. don't allow a table prefix when using database tables

  39. use a separate template engine

  40. don't take a look at established php frameworks for inspiration, most of them have advanced web dev concepts and good code

4/23/2008

It is more easy to install wmVare in ubuntu than Fedora 8

I want to build a test Environment for Centos, so I will install the vmVare in Unbuntu. I thinked it could be hard for me because I have a hard process installing it in Fedora eight.
but the installing process is easy, and very fast. Great!

4/22/2008

CentOS: It is a good choise for free web server

CentOS is an Enterprise-class Linux Distribution derived from sources freely provided to the public by a prominent North American Enterprise Linux vendor. CentOS conforms fully with the upstream vendors redistribution policy and aims to be 100% binary compatible. (CentOS mainly changes packages to remove upstream vendor branding and artwork.) CentOS is free. CentOS is developed by a small but growing team of core developers. In turn the core developers are supported by an active user community including system administrators, network administrators, enterprise users, managers, core Linux contributors and Linux enthusiasts from around the world.CentOS has numerous advantages over some of the other clone projects including: an active and growing user community, quickly rebuilt, tested, and QA'ed errata packages, an extensive mirror network, developers who are contactable and responsive, multiple free support avenues including IRC Chat, Mailing Lists, Forums, a dynamic FAQ. Commercial support is offered via a number of vendors.
Some good resource for CentOs:
Downloading server for China:http://mirror.be10.com/centos/
Managing Software with yum:http://mirror.centos.org/centos/4/docs/html/yum/
Forum in China :http://www.centoschina.com/

Wireframes:User experience design resources

Wireframes serve a central function in the development of a web .They are a key tool in communicating the content and layout of each web page for internal and client reviews as well serving as a blueprint for graphic designers to produce designs and for programmers develop functionality.
further website:
http://www.deyalexander.com/resources/uxd/wireframes.html
http://iainstitute.org/tools/

4/21/2008

Common abbreviations Chatting with a foreigner

gimme=give me=给我
xfer=transfer=传输
em=them=他们的宾格
thx=thanks=谢谢
happy bday=happy b-day=happy birthday!=生日快乐
dunno=dont know=不知道
kinda=a little bit=有点

例子The game is kinda hard for me.i kinda think i should get it done as soon as possible.


tho=though=虽然尽管

例子That demo was very nice,kinda old tho.那个demo很不错,虽然有点老

plz=please=请
cmon=c'mon=come on 加油/别吹了/快点/起来(这个词意思太多了,不赘述了)
suka=s ucker s uck(吮吸),er(表“人”),吮吸的人...没天真到无邪的人都能明白了。
enuff=enough=足够
hax=hack=cheat=作弊,说谎(很地道时尚的词,老外用的比较多)
ty=thank you 原本用的不多,不过现在又开始兴起来了
conn=connection=线路,网络,网络类型 (例句:what conn do you have? / cable )
asap=as soon as possible 尽快
imo=in my opinion 我认为
smh=shake my head (摇头叹气)
dayum=damn=dang
ttyl=talk to you later
b/c=because
j/j=j/k=j/p=just joking, kidding, playing (开玩笑)
w/=with
w/o=without
holla=来和我讲话,also, holla at yo boy, holla at yo girl etc.
atcha=at you


DIY:Do It Yourself的缩写,自己动手做的意思
SOHO:Small Office Home Officer的简称,意思是“在家办公”。
C U/c ya :See You的缩写带音译,
I C:I See的缩写带音译,我知道了
FT:分特,Faint的缩写,昏倒、晕厥之意。
SP:support,支持。
LOL:Laugh Out Loud,大笑。
KFC:Kill fu*king customers。
PK:player kill。
BTW:By the way,顺便说一句。
BRB:Be right back,马上回来。
TTYL:Talk to you later,回头再谈。
BBL:Be back later,过会儿就回。
PPL:people,人们。
PLZ:please,请,也有缩写成PLS
R U OK:Are you OK?
IOWAN2BWU:I only want to be with you
M$ULKeCraZ:Miss you like crazy
CUL8R:see you later
IMHO:In my humble opinion
asap:as soon as possible
for:4
2:to
u=you
ur=your