Edith's profile♀小婷子的亭子间♀PhotosBlogListsMore ![]() | Help |
|
October 25 1095天-我要吃肉35个月29天 2009.10.25 九月初八 周日 晴 晚饭时候,菲菲照样端着自己的巧虎便当盒坐在自制餐椅上吃饭。 妈妈:菲菲要吃什么呀? 菲菲:我要吃肉(指着桌上那碗肋排汤中的肋排) 妈妈给夹了一块,吃完 再问:菲菲还要吃什么呀? 菲菲:我要吃肉(吐字非常清晰) 再夹了一块,并提醒说:菲菲吃两口饭 菲菲:我不要吃饭,我要吃肉(汗……⊙﹏⊙) 又夹了一块,菲菲边吃边说:蛮好吃的 吃完又说:我要吃肉…… 一桌子的人那个汗啊…… October 22 155天 5个月-快速成长期2009-10-22 周四 晴添添的胃口一天比一天大,今天才下午两点多,就把准备的三瓶口粮一扫而光了(120ml一瓶),梦花姐姐急忙问妈妈辅食怎么加,不一会儿,被告知“小的超厉害啊,蛋黄和蔬菜粉都吃没了,一滴没剩” 我突然反应过来,小的是不是进入传说中的“快速成长期”了?在这期间,宝宝成长的速度会加快,同时所需要的能量当然也跟着要加大,表现出来便是胃口猛增! 五个月的添添需要更多地营养来让自己快快长大 October 21 154天 4个月30天-不规律的辅食2009-10-21 周三 晴添添胃口越来越大了,妈妈前一天吸出来的奶都不够她吃的了(基本在400ml左右),可不是,添添长大了,明天就满5个月了呀!也是时候可以添加辅食了,早在4个半月的时候,添添妈就给小宝宝添加蛋黄、蔬菜粉了,可是半个月过去了,总共就吃过两次~ 都没有有规律地每天给她吃。 想想菲菲那个时候,都是外婆白天细心照料,辅食添加,加热喂奶…… 现在的添添没有姐姐那时那么有福气了 粗心的妈妈要注意给添添有规律地添加辅食了,另外,要加大产奶量啦~~ 做个高产奶牛!! October 20 152天 4个月29天-添添的吻 甜甜的吻2009-10-20 周二 晴我滴好妈妈呀下班回到家见到了添添多么开心呀妈妈妈妈快亲亲妈妈妈妈快亲亲添添真开心让我亲亲妈妈让我亲亲妈妈我滴好妈妈~~谁知道添添在妈妈脸上这么一“亲”,就留下了一道亲子痕迹~ 原来添添可不像妈妈这样温柔地亲额~,要知道添添目前最拿手的就是“吮吸”!! 于是,妈妈的脸上就多了那么一块添添留下的“吻痕” October 17 149天 4个月26天-大一天的姐姐2009-10-17 周六 晴今天把添添留在家里,带着菲菲去看望一个比添添大了一天的小姐姐。 刚见到这个小家伙还真让妈妈吃了一惊! 这哪里像比添添大了一天呀,好结实的孩子呀,瞪着圆圆的眼睛,一直望着陌生的来客。身形比添添可大了不止一圈啊!看上去很是“老结”,接过来抱了下,再一次雷到了,比添添不知道重了多少哦 想想也是,虽说是只有大了一天,可人家是足足待满40周才出生的呀,我们的小添添才在妈妈肚子里住了37周就出来了,这样算可是要比小姐姐小了半个月呢,自然身高体重都是不好比的,出生时才5斤七两,这就比人家少了2斤了。 我们的小添添宝宝,你要快快长哦~ (虽然知道自然才是最好,“快快长”不符合自然规律,但做妈妈的就是希望宝宝快快长呀 呵呵) October 07 139天 4个月16天-新食物2009-10-7 周三 晴 添添四个半月了,想着给添添加辅食了,于是,烧了个白煮蛋,挖了1/4个蛋黄(蛋白和剩下的蛋黄自然而然成了菲菲姐姐的小点心了) 第一次尝到妈妈乳汁以外的味道,添添似乎不那么习惯,边吃边往外流,好容易给喂了进去,似乎不像菲菲姐姐那么容易接受新食物。 2009-10-22补充:后来一次加上了蔬菜粉一起吃,添添似乎更不接受了,小舌头直往外顶,如果自制新鲜的蔬菜泥会不会好些呢,我自己闻了闻蔬菜粉的味道,不是很令人感到愉快的味道。 August 17 1026天-幼儿园的第一天32个月22天2009.8.17 六月二十七 周一 晴 盼望着、盼望着,终于迎来了这一天,我们菲菲上幼儿园啦!! 前一段时间就开始给她灌输幼儿园的好:幼儿园里面小朋友、有老师、还有玩具,大家一起玩,真开心!望有了这样的思想准备,菲菲会喜欢幼儿园,至少不抗拒幼儿园。 由于是新生第一天,所以只上半天,而且可以有家长陪读。于是一早穿上前一天晚上就准备好的干净整洁的衣服,背上小书包来到了幼儿园。 幼儿园的安排还是比较合理的,先室外活动一会儿,再到室内休息会儿,动静结合。只是我们的菲菲喜动不喜静,一早操场上做操的时候,她算是新生里表现最好的一个吧,跟着音乐学着老师一起蹦蹦跳跳做早操。但是到了室内上课时间,她便坐不住了,要到边上去玩玩具,不过老师的儿歌也比较吸引她(巧虎的儿歌菲菲就比较喜欢嘛)。 到了中午吃饭,呵呵,一个个小碗,小调羹分配好,大家围着桌子吃饭,相比较而言,菲菲吃饭还算比较好的,不过…… 一上来先把碗里的三个小肉丸子吃掉了,接着自己一调羹一调羹地吃着其余的素菜,一会儿老师端上来剥好的虾,又是一口一个,把虾干掉了,我看看其他小朋友,有些因为嚼不烂又吐出来的,而菲菲却是干净利落地吃光光了…… 又过了一会儿老师端着盛肉丸子的锅问:还要不要? 她点点头,于是把老师后来分配来的小肉丸子又吃掉了…… 老师又来问虾还要不要,继续点头,要,又吃了两个虾…… 我坐在边上那个汗啊,家里是不是不给吃啊…… 吃完饭,第一天(半天)的幼儿园生活结束了,总体来说菲菲还算适应,不知道后面的日子里没有妈妈陪着会怎么样 November 21 HY10W 大量见红 先兆流产 入院保胎~11W+2天 2008-11-21 周五 晴 继上次妞妞第一次胎动的博文后,没有想到,这第二篇是妞妞妈妈在医院里写下的。 还在回味妞妞踢妈妈肚子的情形,毫无征兆。
这天,妈妈还在正常上班,跟同事讨论问题,突然间,妈妈感到一股暖流从沿着双腿汹涌而出,立刻,知道妞妞出事了,还是大事! 匆忙走向卫生间,沿途感觉似乎有液体要滴落在地毯上,进卫生间一看,满眼触目的鲜血!上医院,我的第一个反应。站在卫生间门口,拿出手机拨妞妞爸爸的电话,双手不自觉地颤抖着,竟然把电话都拨错了…… 妞妞爸爸的电话没有人接,妞妞妈妈应该还算镇静,现在最重要的是抓紧时间去医院,妞妞爸爸人在外地,不可能指望他什么的,电话只是通知一声。于是小心而快速回到座位上,收拾自己的东西,此时收到妞妞爸爸的电话,简单扼要的把情况说明后,挂断电话,拿着拎包,对同事说“我不舒服,去医院,我的电脑帮忙收一下”,于是电脑都还摊着,离开了单位。 在等电梯的间隙电话告知了外公所发生的事情,而后在马路口拦了辆车,直奔医院。路上和妞妞爸爸通电话,伤心地说“宝宝没有了”,这时候眼泪也止不住地往下掉。 …… 写这篇文章我还在医院 试了一下 竟然能连到无线~ November 15 胎动~胎动~今天第一次感到了妞妞的胎动~~ 才第十周(10W-4/7) 就感到了胎动! 菲菲那会儿是我感觉迟钝还是啥的,知道二十周才感到那么一点点地动, 而今天,就在刚才(19:30左右),我明显感到妞妞在顶我的肚子,我索性躺下来看着肚皮,果然一会儿左边顶出来,一会儿右边顶出来,我还顶回去跟妞妞玩,哈哈 菲菲看到我在玩肚皮,也跑过来,叫着"MM,MM",还亲了亲MM,用手再拍拍MM 哈 姐妹俩先互动一下 November 14 749天-妈妈再见,byebye
2008.11.14 十月十七 周五 晴 “再见,byebye”一直是菲菲讲得最流利的话。 早上妈妈拿起包,她就知道你要走了,有时会很爽气地挥着小手跟你说“妈妈再见,byebye”,重复好几遍,一直目送你出门。但也有粘的时候,看你拿包或换鞋,她就粘上来,任你怎么跟她“再见,byebye”她也决不开金口,只是抱着你的腿不放。 平时外公带她出门,她会高兴的跟妈妈“再见,byebye”,但如果有时妈妈或者谁要离开下,跟她“再见,byebye”,她就不愿意了,瘪着个小嘴就是不说话,一副尴尬面孔。 有时带着她打车,让她跟外公再见,她只挥动小手,就是不说话,等车子一开,就开始唠叨“外公再见,byebye”,可以一直重复,直到到达目的地…… 家里的阿姨打扫完跟她说阿姨走了哦,她立刻一句“阿姨再见,byebye”。 这个“再见,byebye”还有它特殊的音调,无法在此用语言形容,下次把它录下来,等菲菲长大后给她自己听 November 13 748天-搂着妈妈觉觉
2008.11.13 十月十六 周四 晴 晚上: “搞搞,搞搞……”菲菲手指着房间,跟你说要搞搞,于是带着她到房间里面,“阿阿特特”,帮她把鞋子脱掉,“麽麽特特”,再帮她把袜子脱掉,“宝宝衣”,再把衣服脱掉,然后钻到被子里面,自己把被子盖好,两个小胳膊放在外面,一本正经地睡觉姿势。 半夜: 菲菲睡姿不咋样,喜欢横着睡,就是和枕头平行的那种。开始我还不停地把她搬回来,可她一个翻身整个人就翻出被窝,身体就横过来了(别看她上床的时候规规矩矩的睡觉姿势)。反复多次后,我也就随她去了,只是注意帮她把被子盖好,别着凉了。 早上: 天亮了,菲菲一般会哼哼几声,于是我就抱她去斯斯,完了后再把她抱回床上,这时候,她两个手就紧紧地勾着妈妈,深怕妈妈偷偷溜了似的。重新睡到床上后,她也是两手搂着妈妈的脖子不放,甜甜地继续她的梦。想想自己小时候也喜欢和妈妈捂着一起睡,原来小孩子都是这样的呀,于是我也搂着她,两个人一起再睡个回笼觉。 740天-餐椅DIY24个月12天 2008.11.5 十月初八 周三 多云 菲菲吃饭一直是站在椅子上的(她没有自己的餐椅,有时想想有点对不起她,虽然小时候到外面吃饭不愿意坐宝宝椅),站着也能够到更远的菜。但是最近她不爱站着了,要学你们大人的样子坐着吃饭(随着不断长高的个子,站着似乎也太高了点),于是她自己端着个小碗坐着埋头吃饭,可是坐着又太矮了,感觉整个人缩在桌子下面。 我突发奇想,家里刚刚买了箱光明优+,还没有拆开,叠在椅子上当个小凳子,宝宝坐在上面不高不低,正正好好,哈哈,这个餐椅不错吧! 菲菲似乎也比较满意自己的这个位子,小PP坐在牛奶上,小脚脚搁在椅子上,小碗放在桌子上,拿着调羹自己吃饭,哈哈,真不错,坐得舒服了,好像胃口也大了些,自己可以吃掉小半碗饭(白饭)。 November 07 哈哈 菲菲认识的第一个卡通形象--“哈哈”,现在只要我一转到“哈哈少儿频道”,一看到那个蓝色的大眼睛哈哈,她就会指着电视说“哈哈”,发音和电视里那个还一模一样,哈哈,哈哈 应该是“哈哈”的发音比较简单也容易记吧,哈哈哈哈 January 09 2007不可能实现的愿望:好好睡一觉 自从有了小菲菲 时间就不再是自己的了 说说晚上吧 每天吃好晚饭后是最精神的活动时间 陪着她玩啊玩 玩到11点多 帮她洗洗PP 换上一次性尿布 再拿热水泡泡小脚 再美美地吃上一顿 已经到了子夜时分 幸运的话 这时候应该做梦去了 也有可能再兴奋一下下 那就还得继续陪玩……
小家伙太平点 可以睡一阵子 但无论如何我都无法太平 3点左右我不得不爬起来 给菲菲准备早餐 若是赖着不想起来 那不多久也会涨得不得不惺忪着双眼爬起来吸奶 唉 半个多小时后再继续我的睡眠
6点 小东西开始嗯啊嗯啊叫唤了 起来给她吃早饭 看着天空发白直到全亮 小东西吃好继续睡 而我则没有这么好的福气 要给她准备下一顿:继续吸奶!
吸完之后也要起床了 因为还有一堆尿布要洗 还有奶瓶要洗 还有房间要整理 还有被子要晒 还有……
2007不可能实现的愿望:好好睡一觉!
September 11 回来继续 先自己汗一个 上一篇竟然是在一年前提交的!
一年里发生了很多事情 一点点来吧 先谈谈工作 最近比较轻松 于是趁机学习学习 找了篇LR的文章 照葫芦画瓢开始弄 希望也能弄个像样点的东西出来 等弄出来之后也放上来 自己欣赏欣赏也好 在这里提一下这件事情 也算是对自己的一种鞭策吧 不然估计我坚持不下去
坚持是比较难的 心血来潮时把这里整理得井井有条 一旦懒起来就一年不碰 其它事情也是如此 希望能改掉这个毛病吧 August 11 测试人如何行走江湖-浅谈测试人员的技术构成和发展zt测试人如何行走江湖-浅谈测试人员的技术构成和发展 刚做软件测试时,是很不情愿的,一直认为开发要比测试牛,测试太没有创造力了。不过做了三年的软件测试后,我的看法改变了,测试人员更需要发散的思维,也需要很多专业的知识做铺垫。接触过国外的软件工程师,其中就有15年软件经验的人在做测试,也在华为做过软件测试经理,要知道测试报告不通过,产品是绝对不能发布的,呵呵,测试对产品的质量最有发言权。 测试工作是适合聪明人来做的,它需要综合的能力。要想做好测试工作,在技术上要保证三个方面的均衡发展。我把测试人比做行走江湖的大侠,必需要具备以下三点: 一、内功心法:软件技术。做软件测试的,不通软件是绝对不行的。软件技术好比内功,决定了测试人员的级数。无内功者只会用软件,所以对照说明书就测功能。甚至啥也不懂也可以测试,测试方法中不还有一招猴子测试法么,呵呵。不过专业的软件测试人员,要对软件开发工具、软件工程方法都要有了解,比如C的测试员、Java的测试员,了解得越全,功力就越深。对于应用和开发测试工具都大有裨益,我就见过一个高人,重写了C的编译器,可以实现对基于C的程序进行变量、代码段、堆栈的实时镜象跟踪,强啊!再比如对软件工程了解了,就有能力修炼进行质量控制、流程管理、缺陷管理等高级武功啦。 二、武功招式:测试技术。呵呵,既然凭测试行天下,那测试技术自是当家功夫了。对于测试用例设计方法、不同的测试工具使用、测试度量方法、测试管理都要逐步了解。嘿嘿,专家一出手,就知有没有,不管你是什么东东的测试,小到手机,大到波音飞机,其实测试原理都是相通的。进行测试分析、完成测试设计、执行测试、评估测试结果。只有将招式练得纯熟了,见招拆招,自然行遍天下。要是练成了可测试性设计、缺陷度量等绝学,就如同学会了降龙十八掌、凌波微步,行走江湖,自是所向无敌。当然还有我们的测试工具,就如同倚天屠龙、小李飞刀等绝世神兵,各位行走江湖的测试大侠,自然要常备在身。测试中还有黑客一族,身怀域外奇功,又似唐门暗器,让系统漏洞无处藏身啊。 三、江湖阅历:产品技术。纵然你身怀奇功,也需要懂得江湖规矩,才能成就功业。不懂产品的人,很难深入地测试出系统性的问题,很难站在客户角度测试,也很难从产品战略的角度分派测试资源。你测试的是通信产品,就好好地研究一下ITUT协议;你测试的是嵌入式系统,就好好地学习Linux和Vxworks;你测试的是购物网站,那有空就多上上当当易趣和淘宝。只有深入钻研你所测试的对象,你才有可能发现它的缺点以及缺陷出现的深层原因。 测试是值得你一辈子付出的事业,她有着无穷的魅力,她能让你发挥出自己的创造力和想像力。而且有经验的专业的软件测试人员,在江湖上的地位也越来越高,测试这一派必将不断壮大! August 02 持续集成持续集成
作者:Martin Fowler -------------------------------------------------------------------------------- Martin Fowler & Matthew Foemmel著 透明 译 英文原文版权由Martin Fowler拥有
Original text is copyrighted by Martin Fowler 原文链接:http://martinfowler.com/articles/continuousIntegration.html Martin Fowler
Chief Scientist, ThoughtWorks 译者语:2002年1月23日,我们很荣幸的在UMLCHINA组织的网上交流中聆听了Martin Fowler先生的教诲。在 交流中,Martin Fowler向所有中国软件开发者推荐了这篇文章:Continuous Integration(《持续集成》)。
初读之下,我便感觉到了它的分量,AgileChina的林星也称赞:“其中的思想非常的好,大师就是大师。”然 后,用了一周的时间,我终于把这篇文章翻译出来,以飨读者。 由于这是Fowler先生送给全体中国软件开发者的礼物,所以我绝对不敢独占。任何人都可以在任何地方随意 转载本文,但是在转载时请保持本文完整性——包括标题、版权声明、原文链接、译者语……总之,请不要在转 载的时候做任何改动或增删。另外,如果能在转载的时候顺手给我一个mail,我会更加高兴。
下面,请开始欣赏这篇精彩的文章。
在任何软件开发过程中都有一个重要的部分:得到可靠的软件创建(build)版本。尽管知道创建的重要 性,但是我们仍然会经常因为创建失败而惊讶不已。在这篇文章里,我们将讨论Matt(Matthew Foemmel)在 ThoughtWorks的一个重要项目中实施的过程,这个过程在我们的公司里日益受到重视。它强调完全自动化的、可 重复的创建过程,其中包括每天运行多次的自动化测试。它让开发者可以每天进行系统集成,从而减少了集成中 的问题。
ThoughtWorks公司已经开放了CruiseControl软件的源代码,这是一个自动化持续集成的工具。此外,我们还 提供CruiseControl、Ant和持续集成方面的顾问服务。如果需要更多的信息,请与Josh Mackenzie
(jmackenz@ThoughtWorks.com)联系。 本文有以下主要内容:
持续集成的优点
集成越频繁,效果越好 一次成功的创建是什么样的? 单一代码源 自动化创建脚本 自测试的代码 主创建 代码归还 总结 在软件开发的领域里有各种各样的“最佳实践”,它们经常被人们谈起,但是似乎很少有真正得到实现的。 这些实践最基本、最有价值的就是:都有一个完全自动化的创建、测试过程,让开发团队可以每天多次创建他们 的软件。“日创建”也是人们经常讨论的一个观点,McConnell在他的《快速软件开发》中将日创建作为一个最 佳实践来推荐,同时日创建也是微软很出名的一项开发方法。但是,我们更支持XP社群的观点:日创建只是最低 要求。一个完全自动化的过程让你可以每天完成多次创建,这是可以做到的,也是完全值得的。 在这里,我们使用了“持续集成(Continuous Integration)”这个术语,这个术语来自于XP(极限编程) 的一个实践。但是我们认为:这个实践早就存在,并且很多并没有考虑XP的人也在使用着它。只不过我们一直用 XP作为软件开发过程的标准,XP也对我们的术语和实践产生了深远的影响。尽管如此,你还是可以只使用持续集 成,而不必使用XP的任何其他部分——实际上,我们认为:对于任何切实可行的软件开发活动,持续集成都是很 基本的组成部分。
实现自动化日创建需要做以下几部分的工作:
将所有的源代码保存在单一的地点,让所有人都能从这里获取最新的源代码(以及以前的版本)。 使创建过程完全自动化,让任何人都可以只输入一条命令就完成系统的创建。 使测试完全自动化,让任何人都可以只输入一条命令就运行一套完整的系统测试。 确保所有人都可以得到最新、最好的可执行文件。
所有这些都必须得到制度的保证。我们发现,向一个项目中引入这些制度需要耗费相当大的精力。但是,我 们也发现,一旦制度建立起来,保持它的正常运转就不需要花多少力气了。 持续集成的优点
描述持续集成最大的难点在于:它从根本上改变了整个开发模式。如果没有在持续集成的实践环境中工作过,你很难理解它的开发模式。实际上,在单独工作的时候,绝大多数人都能感觉到这种气氛——因为他们只需 要与自己的系统相集成。对于许多人来说,“团队开发”这个词总让他们想起软件工程领域中的一些难题。持续 集成减少了这些难题的数量,代之以一定的制度。 持续集成最基本的优点就是:它完全避免了开发者们的“除虫会议”——以前开发者们经常需要开这样的 会,因为某个人在工作的时候踩进了别人的领域、影响了别人的代码,而被影响的人还不知道发生了什么,于是 bug就出现了。这种bug是最难查的,因为问题不是出在某一个人的领域里,而是出在两个人的交流上面。随着时 间的推移,问题会逐渐恶化。通常,在集成阶段出现的bug早在几周甚至几个月之前就已经存在了。结果,开发 者需要在集成阶段耗费大量的时间和精力来寻找这些bug的根源。
如果使用持续集成,这样的bug绝大多数都可以在引入的同一天就被发现。而且,由于一天之中发生变动的 部分并不多,所以可以很快找到出错的位置。如果找不到bug究竟在哪里,你也可以不把这些讨厌的代码集成到 产品中去。所以,即使在最坏的情况下,你也只是不添加引起bug的特性而已。(当然,可能你对新特性的要求 胜过了对bug的憎恨,不过至少你可以多一种选择。)
到现在为止,持续集成还不能保证你抓到所有集成时出现的bug。持续集成的排错能力取决于测试技术,众 所周知,测试无法证明已经找到了所有的错误。关键是在于:持续集成可以及时抓到足够多的bug,这就已经值 回它的开销了。
所以,持续集成可以减少集成阶段“捉虫”消耗的时间,从而最终提高生产力。尽管现在还不知道是否有人 对这种方法进行过科学研究,但是作为一种实践性的方法,很明显它是相当有效的。持续集成可以大幅减少耗费 在“集成地狱”中的时间,实际上,它可以把地狱变成小菜一碟。
集成越频繁,效果越好
持续集成有一个与直觉相悖的基本要点:经常性的集成比很少集成要好。对于持续集成的实践者来说,这是 很自然的;但是对于从未实践过持续集成的人来说,这是与直观印象相矛盾的。 如果你的集成不是经常进行的(少于每天一次),那么集成就是一件痛苦的事情,会耗费你大量的时间与精 力。我们经常听见有人说:“在一个大型的项目中,不能应用日创建”,实际上这是一种十分愚蠢的观点。
不过,还是有很多项目实践着持续集成。在一个五十人的团队、二十万行代码的项目中,我们每天要集成二 十多次。微软在上千万行代码的项目中仍然坚持日创建。
持续集成之所以可行,原因在于集成的工作量是与两次集成间隔时间的平方成正比的。尽管我们还没有具体 的衡量数据,但是可以大概估计出来:每周集成一次所需的工作量绝对不是每天集成的5倍,而是大约25倍。所 以,如果集成让你感到痛苦,也许就说明你应该更频繁地进行集成。如果方法正确,更频繁的集成应该能减少你的痛苦,让你节约大量时间。
持续集成的关键是自动化。绝大多数的集成都可以而且应该自动完成。读取源代码、编译、连接、测试,这 些都可以自动完成。最后,你应该得到一条简单的信息,告诉你这次创建是否成功:“yes”或“no”。 如果成 功,本次集成到此为止;如果失败,你应该可以很简单地撤消最后一次的修改,回到前一次成功的创建。在整个
创建过程中,完全不需要你动脑子。 如果有了这样一套自动化过程,你随便想多频繁进行创建都可以。唯一的局限性就是创建过程本身也会消耗 一定的时间。(译注:不过与捉虫所需的时间比起来,这点时间是微不足道的。)
一次成功的创建是什么样的?
有一件重要的事需要确定:怎样的创建才算是成功的?看上去很简单,但是如此简单的事情有时却会变得一 团糟,这是值得注意的。有一次,Martin Fowler去检查一个项目。他问这个项目是否执行日创建,得到了肯定 的回答。幸亏Ron Jeffries也在场,他又提了一个问题:“你们如何处理创建错误?”回答是:“我们给相关的 人发一个e-mail。”实际上,这个项目已经好几个月没有得到成功的创建了。这不是日创建,这只是日创建的尝 试。 对于下列“成功创建”的标准,我们还是相当自信的:
所有最新的源代码都被配置管理系统验证合格
所有文件都通过重新编译 得到的目标文件(在我们这里就是Java的class文件)都通过连接,得到可执行文件 系统开始运行,针对系统的测试套件(在我们这里大概有150个测试类)开始运行 如果所有的步骤都没有错误、没有人为干涉,所有的测试也都通过了,我们就得到了一个成功的创建 绝大多数人都认为“编译+连接=创建”。至少我们认为:创建还应该包括启动应用程序、针对应用程序运行 简单测试(McConnell称之为“冒烟测试”:打开开关让软件运行,看它是否会“冒烟”)。 运行更详尽的测试 集可以大大提高持续集成的价值,所以我们会首选更详尽的测试。 单一代码源
为了实现每日集成,任何开发者都需要能够很容易地获取全部最新的源代码。以前,如果要做一次集成,我 们就必须跑遍整个开发中心,询问每一个程序员有没有新的代码,然后把这些新代码拷贝过来,再找到合适的插 入位置……没有什么比这更糟糕的了。 办法很简单。任何人都应该可以带一台干净的机器过来,连上局域网,然后用一条命令就得到所有的源文 件,马上开始系统的创建。
最简单的解决方案就是:用一套配置管理(源代码控制)系统作为所有代码的来源。配置管理系统通常都设 计有网络功能,并且带有让开发者轻松获取源代码的工具。而且,它们还提供版本管理工具,这样你可以很轻松 地找到文件以前的版本。成本就更不成问题了,CVS就是一套出色的开放源代码的配置管理工具。
所有的源文件都应该保存在配置管理系统中。我说的这个“所有”常常比人们想到的还要多,它还包括创建 脚本、属性文件、数据库调度DLL、安装脚本、以及在一台干净的机器上开始创建所需的其他一切东西。经常都 能看到这样的情况:代码得到了控制,但是其他一些重要的文件却找不到了。
尽量确保所有的东西都保存在配置管理系统的同一棵代码源树中。有时候为了得到不同的组件,人们会使用 配置管理系统中不同的项目。这带来的麻烦就是:人们不得不记住哪个组件的哪个版本使用了其他组件的哪些版 本。在某些情况下,你必须将代码源分开,但是这种情况出现的几率比你想象的要小得多。你可以在从一棵代码 源树创建多个组件,上面那些问题可以通过创建脚本来解决,而不必改变存储结构。
自动化创建脚本
如果你编写的是一个小程序,只有十几个文件,那么应用程序的创建可能只是一行命令的事:javac *.java。更大的项目就需要更多的创建工作:你可能把文件放在许多目录里面,需要确保得到的目标代码都在适 当的位置;除了编译,可能还有连接的步骤;你可能还从别的文件中生成了代码,在编译之前需要先生成;测试 也需要自动运行。 大规模的创建经常会耗费一些时间,如果只做了一点小小的改动,当然你不会希望重新做所有这些步骤。所 以好的创建工具会自动分析需要改变的部分,常见的方法就是检查源文件和目标文件的修改日期,只有当源文件 的修改日期迟于目标文件时,才会重新编译。于是,文件之间的依赖就需要一点技巧了:如果一个目标文件发生
了变化,那么只有那些依赖它的目标文件才会重新编译。编译器可能会处理这类事情,也可能不会。 取决于自己的需要,你可以选择不同的创建类型:你创建的系统可以有测试代码,也可以没有,甚至还可以 选择不同的测试集;一些组件可以单独创建。创建脚本应该让你可以根据不同的情况选择不同的创建目标。
你输入一行简单的命令之后,帮你挑起这副重担常常是脚本。你使用的可能是shell脚本,也可能是更复杂 的脚本语言(例如Perl或Python)。但是很快你就会发现一个专门设计的创建环境是很有用的,例如Unix下的make工具。
在我们的Java开发中,我们很快就发现需要一个更复杂的解决方案。Matt用了相当多的时间开发了一个用于 企业级Java开发的创建工具,叫做Jinx。但是,最近我们已经转而使用开放源代码的创建工具Ant (http://jakarta.apache.org/ant/index.html)。Ant的设计与Jinx非常相似,也支持Java文件编译和Jar封 装。同时,编写Ant的扩展也很容易,这让我们可以在创建过程中完成更多的任务。
许多人都使用IDE,绝大多数的IDE中都包含了创建管理的功能。但是,这些文件都依赖于特定的IDE,而且 经常比较脆弱,而且还需要在IDE中才能工作。IDE的用户可以建立自己的项目文件,并且在自己的单独开发中使 用它们。但是我们的主创建过程用Ant建立,并且在一台使用Ant的服务器上运行。
自测试的代码
只让程序通过编译还是远远不够的。尽管强类型语言的编译器可以指出许多问题,但是即使成功通过了编 译,程序中仍然可能留下很多错误。为了帮助跟踪这些错误,我们非常强调自动化测试——这也是XP提倡的另一 个实践。 XP将测试分为两类:单元测试和容纳测试(也叫功能测试)。单元测试是由开发者自己编写的,通常只测试 一个类或一小组类。容纳测试通常是由客户或外部的测试组在开发者的帮助下编写的,对整个系统进行端到端的 测试。这两种测试我们都会用到,并且尽量提高测试的自动化程度。
作为创建的一部分,我们需要运行一组被称为“BVT”(Build Verification Tests,创建确认测试)的测 试。BVT中所有的测试都必须通过,然后我们才能宣布得到了一个成功的创建。所有XP风格的单元测试都属于 BVT。由于本文是关于创建过程的,所以我们所说的“测试”基本上都是指BVT。请记住,除了BVT之外,还有一 条测试线存在(译注:指功能测试),所以不要把BVT和整体测试、QA等混为一谈。实际上,我们的QA小组根本不会看到没有通过BVT的代码,因为他们只对成功的创建进行测试。
有一条基本的原则:在编写代码的同时,开发者也应该编写相应的测试。完成任务之后,他们不但要归还 (check in)产品代码,而且还要归还这些代码的测试。这也跟XP的“测试第一”的编程风格很相似:在编写完 相应的测试、并看到测试失败之前,你不应该编写任何代码。所以,如果想给系统添加新特性,你首先应该编写一个测试。只有当新的特性已经实现了以后,这个测试才可能通过。然后,你的工作就是让这个测试能够通过。
我们用Java编写这些测试,与开发使用同样的语言,所以编写测试与编写代码没有太大的区别。我们使用JUnit(http://www.junit.org/)来作为组织、编写测试的框架。JUnit是一个简单的框架,让我们可以快速编 写测试、将测试组织为套件、并以交互或批处理的模式来运行测试套件。(JUnit是xUnit家族的Java版本 ——xUnit包括了几乎所有语言的测试框架。)
在编写软件的过程中,在每一次的编译之后,开发者通常都会运行一部分单元测试。这实际上提高了开发者的工作效率,因为这些单元测试可以帮助你发现代码中的逻辑错误。然后,你就没必要去调试查错,只需要注意 最后一次运行测试之后修改的代码就行了。这个修改的范围应该很小,所以寻找bug也就容易多了。
并非所有的人都严格遵循XP“测试第一”的风格,但是在第一时间编写测试的好处是显而易见的。它们不但 让每个人的工作效率更高,而且由这些测试构成的BVT更能捕捉到系统中的错误。因为BVT每天要运行好几次,所 以BVT检查出的任何问题都是比较容易改正的,原因很简单:我们只做了相当小范围的修改,所以我们可以在这 个范围内寻找bug。在修改过的一小块代码中排错当然比跟踪整个系统来排错要有效多了。
当然,你不能指望测试帮你找到所有的问题。就象人们常说的:测试不能证明系统中不存在错误。但是,尽 善尽美不是我们唯一的要求。不够完美的测试只要经常运行,也比永远写不出来的“完美测试”要好得多。
另一个相关的问题就是:开发者们为自己的代码编写测试。我们经常听人说:开发者不应该测试自己的代 码,因为他们很容易忽视自己工作中的错误。尽管这也是事实,但是自测试过程需要快速将测试转入代码基础 中。这种快速转换的价值超过独立测试者的价值。所以,我们还是用开发者自己编写的测试来构造BVT,但是仍 然有独立编写的容纳测试。
自测试另一个很重要的部分就是它通过反馈——XP的一项核心价值——来提高测试的质量。这里的反馈来自 于从BVT中逃脱的bug。自测试的规则是:除非你在BVT中加入了相应的测试,否则就不能修正任何错误。这样, 每当要修正某个错误的时候,你都必须添加相应的测试,以确保BVT不会再把错误放过去。而且,这个测试应该 引导你去考虑更多的测试、编写更多的测试来加强BVT。
主创建
创建过程的自动化对于单个开发者来说很有意义,但是它真正发光的,还是在整个系统的主创建(master build)的生成。我们发现,主创建过程能让整个团队走到一起来,让他们及早发现集成中的问题。 第一步是要选择运行主创建的机器。我们选择了一台叫做“投石车”的计算机(我们经常玩“帝国时代” J),这是一台装有四个CPU的服务器,非常适合专门用来做创建。(由于完整的创建需要相当长的时间,所以这 种马力是必须的。)
创建进程是在一个随时保持运行的Java类中进行的。如果没有创建任务,创建进程就一直循环等待,每过几 分钟去检查一下代码仓库。如果在最后的创建之后没有人归还任何代码,进程就继续等待。如果代码仓库中有了 新的代码,就开始创建。
创建的第一阶段是完全提取仓库中的代码。Starteam已经为我们提供了相当好的Java API,所以切入代码仓 库也很容易。守护进程(daemon)会观察五分钟以前的仓库,看最近五分钟里面有没有人归还了代码。如果有, 守护进程就会考虑等五分钟再提取代码(以免在别人归还代码的过程中提取)。
守护进程将全部代码提取到投石机的一个目录中。提取完成之后,守护进程就会在这个目录里调用Ant脚 本。然后,Ant会接管整个创建过程,对所有源代码做一次完整的创建。Ant脚本会负责整个编译过程,并把得到 的class文件放进六个jar包里,发布到EJB服务器上。
当Ant完成了编译和发布的工作之后,创建守护进程就会在EJB服务器上开始运行新的jar,同时开始运行BVT 测试套件。如果所有的测试都能正常运行通过,我们就得到了一个成功的创建。然后创建守护进程就会回到 Starteam,将所有提取出的源代码标记上创建号。然后,守护进程会观察创建过程中是否还有人归还了代码。如 果有,就再开始一次创建;如果没有,守护进程就回到它的循环中,等待下一次的归还。
创建结束之后,创建守护进程会给所有向最新一次创建归还了代码的开发者发一个e-mail,汇报创建的情 况。如果把创建留在代码归还之后去做,而又不用e-mail向开发者通报创建的情况,我们通常认为这是不好的组 织形式。
守护进程将所有的步骤都写在XML格式的日志文件里面。投石车上会运行一个servlet,允许任何人通过它检 查日志,以观察创建的状态。(见图1)
屏幕上会显示出创建是否正在运行、开始运行的时间。在左边有所有创建的历史记录,成功的、失败的都记 录在案。点击其中的某一条记录,就会显示出这次创建的详细信息:编译是否通过、测试的结果、发生了哪些变 化……
我们发现很多开发者都经常看看这个页面,因为它让他们看到项目发展的方向,看到随着人们不断归还代码 而发生的变化。有时我们也会在这个页面上放一些其他的项目新闻,但是需要把握好尺度。
要让开发者能在自己的本地机器上模拟主创建过程,这是很重要的。这样,如果集成错误出现了,开发者可 以在自己的机器上研究、调试,而不必真的执行主创建过程。而且,开发者也可以在归还代码之前先在本地执行 创建,从而降低了主创建失败的可能性。
这里有一个比较重要的问题:主创建应该是干净的创建(完全从源代码开始)还是增量创建?增量创建会快 得多,但是也增大了引入错误的风险,因为有些部分是没有编译的。而且我们还有无法重新创建的风险。我们的 创建速度相当快(20万行代码约15分钟),所以我们乐于每次都做干净的创建。但是,有些团队喜欢在大多数时候做增量创建,但是当那些奇怪的问题突然出现时,也经常性地做干净的创建(至少每天一次)。
图1:运行在投石车上的servlet 代码归还(Check in)
使用自动化创建就意味着开发者应该遵循某种节奏来开发软件,最重要的就是他们应该经常集成。我们曾经 见过一些组织,他们也做日创建,但是其中的开发者却不经常归还代码。如果开发者几周才归还一次代码,那么 日创建又有什么意义呢?我们遵循的原则是:每个开发者至少每天要归还一次代码。 在开始新的任务之前,开发者应该首先与配置管理系统同步。也就是说,他们应该首先更新本地机器上的源 代码。在旧的代码基础上编写代码,这只会带来麻烦和混乱。
然后,开发者要随时保持文件的更新。开发者可以在一段任务完成之后将代码集成到整个系统中,也可以在 任务的中途集成,但是在集成的时候必须保证所有的测试都能通过。
集成的第一步是要再次使开发者的本地文件与代码仓库同步。代码仓库中所有新近有改动的文件都要拷贝到 开发者的工作目录中来,当文件发生冲突时,配置管理系统会向开发者提出警告。然后,开发者需要对同步后的 工作集进行创建,对这些文件运行BVT,并得到正确的结果。
现在,开发者可以把新的文件提交到代码仓库中。提交完成之后,开发者就需要等待主创建。如果主创建成功,那么这次归还也是成功的。如果主创建失败了,开发者可以在本地修改。如果修改很简单,就可以直接提 交;如果修改比较复杂,开发者就需要放弃这次修改,重新同步自己的工作目录,然后继续在本地开发、调试,然后再次提交。
某些系统强制要求归还进程逐个进行。在这种情况下,系统中会有一个创建令牌,同一时间只有一个开发者 能拿到令牌。开发者获取创建令牌,再次同步文件,提交修改,然后释放令牌。这就确保创建过程中,最多只能 有一个开发者在更新代码仓库。不过我们发现,即使没有创建令牌,我们也很少遇到麻烦,所以我们也不用这种方法。经常会有多个人同时向同一个主创建提交代码的情况,但是这很少造成创建失败,而且这样的错误也很容 易修复。
同时,我们还让开发者自己来决定归还过程中的小心程度。这反映出开发者对集成错误出现几率的评估。如 果她觉得很有可能出现集成错误,那么她就会在归还之前先做一次本地创建;如果她觉得根本不可能出现集成错误,那么她可以直接归还。如果犯了错误,在主创建运行时她立刻就会发现,然后她就必须放弃自己的修改,找到出错的地方。如果错误很容易发现、很容易修补,那么这种错误也是可以接受的。
总结
发展一个制度严密的自动化创建过程对于项目的控制是很重要的。许多软件先贤都这样说,但是我们发现, 这样的过程在软件开发领域中仍然罕见。 关键是要让所有的事情都完全自动化,并且要经常进行集成,这样才能尽快发现错误。然后,人们可以随时 修改需要修改的东西,因为他们知道:如果他们做的修改引起了集成错误,那也是很容易发现和修补的。一旦获得了这些利益,你会发现自己再也无法放下它们
July 30 梁祝 --楼台会梁祝 楼台会 (梁)贤妹妹,我想你,神思昏昏寝食废; 梁哥哥,我想你,三餐茶饭无滋味; (梁)贤妹妹,我想你,衣冠不整无心理; 梁哥哥,我想你,懒对菱花不梳洗; (梁)贤妹妹,我想你,哪日不想到夜里; 梁哥哥,我想你,哪夜不想到鸡啼。 (梁)我想你,你想我, (祝)今生料难成连理。 (梁)辞别贤妹回家门, (祝)今日别后你何时来呀? (梁)回家病好来看你,只怕我短命夭伤不能来。 倘若我有长和短,就在那胡桥镇上立坟碑, (祝)立坟碑啊立坟碑,梁兄你红黑二字立两块, 红的刻着我祝英台,黑的刻着你梁山伯。 我与你生前不能夫妻配,我就是死也要与你同坟台。 梁祝--十八相送十八相送
人物: 梁山伯(伯) 祝英台(台) 银心(心) 四九(九) 三载同窗情如海 山伯难舍祝英台 相依相伴送下山 又向钱塘道上来 祝: 梁兄~~ 书房门前一枝梅 树上鸟儿对打对 喜鹊满枝喳喳叫 向你梁兄报喜来 梁: 弟兄二人出门来
门前喜鹊成双对 从来喜鹊报喜讯 恭喜贤弟一路平安把家归 祝: 梁兄请~~~ 梁: 请~~ 祝: 出了城过了关
但只见 山上樵夫把柴担 梁: 起早落夜多辛苦 打柴度日也艰难 祝: 梁兄啊他为何人把柴打 你为哪个送下山 梁: 他为妻儿把柴打 我为你贤弟送下山 祝: 过了一山又一山 梁: 前面到了凤凰山 祝: 凤凰山上百花开 梁: 缺少芍药共牡丹 祝: 梁兄若是爱牡丹 与我一同把家归 我家有枝好牡丹 梁兄你要摘也不难 梁: 你家牡丹虽然好 可惜是路远迢迢怎来攀 祝: 青青荷叶清水塘 鸳鸯成对又成双 梁兄啊英台若是女红装 梁兄你愿不愿意配鸳鸯 梁: 配鸳鸯配鸳鸯 可惜你英台不是女红装 祝: 前面到了一条河 梁: 漂来一对大白鹅 祝: 雄的就在前面走 雌的后面叫哥哥 梁: 啊~~ 祝: 喏~~咕咕咕~~ 梁: 不见二鹅来开口 哪有雌鹅叫雄鹅 祝: 你不见雌鹅她对你微微笑 他笑你梁兄真象呆头鹅 梁: 哎~~ 既然我是呆头鹅 从今你莫叫我梁哥哥 祝: 梁兄~~小弟讲错了~~ 梁: 下次不可 下次不可 前面一条独木桥 梁: 贤弟请~~ 祝: 梁兄请~~~ 啊~~梁兄~~ 我心又慌胆又小 梁: 愚兄扶你过桥去 祝: 你我好一比牛郎织女渡鹊桥 梁: 你呀~~ 祝: 梁兄~~ 过了河滩又一庄
庄内黄犬叫汪汪 祝: 不咬前面男子汉 偏咬后面女红装 梁: 贤弟说话太荒唐 此地哪有女红装 放大胆子莫惊慌 愚兄打犬你过庄 祝: 眼前原有一口井 不知道井水有多深 梁: 井水深浅不关紧 你我赶路最要紧 祝: 梁兄~~ 梁: 啊~~ 祝: 来~~ 你看这井底两个影 一男一女笑盈盈 梁: 啊~~ 祝: 喏~~ 梁: 哎~~ 愚兄明明是男子汉 你为何将我比女人 走吧~~ 梁: 离了井 又一堂 前面到了观音堂 祝: 梁兄~~我去大堂去一拜呀~~ 梁: 好啊~~ 观音堂 观音堂 送子观音坐上方 祝: 观音大士媒来做 我与你梁兄来拜堂 梁: 哎~~贤弟越说越荒唐 两个男子怎拜堂 快走吧~~ 离了古庙往前走 但见过来一头牛 牧童骑在牛背上 唱起山歌解忧愁 祝: 只可惜对牛弹琴牛不懂 可叹你梁兄笨如牛 梁: 哎~~非是愚兄动了火 谁叫你比来比去比看我 祝: 请梁兄你莫动火 小弟赔罪来认错 梁: 好了~~好了~~快走吧~~ 祝: 梁兄~~ 多承梁兄情意深 登山涉水送我行 常言到送君千里终须别 请梁兄就此留步转回程 梁: 与贤弟草桥结拜情义深 让愚兄再送你到长亭 四九 快走吧~~ 十八里相送到长亭 十八里相送到长亭 祝: 梁兄 梁: ~~啊~~ 祝: 你我鸿雁两分开 问贤弟你还有何言来交代 问梁兄你家中可有妻房配 梁: 你早知愚兄未婚配 今日相问为何来 祝: 要是你梁兄亲未定 小弟替你做大媒 梁: 贤弟替我来做媒 还未知千金哪一位 祝: 就是我家小九妹 不知你梁兄可喜爱 梁: 九妹今年有几岁 祝: 她是与我同年 梁: 啊~~ 祝: 乃是双胞胎 梁: 九妹与你可相象 祝: 她品貌就象我英台 梁: 但未知仁伯肯不肯 祝: 家父瞩我选英才 梁: 如此多谢贤弟来玉成 祝: 梁兄你花轿早来抬 我约你乞巧之期 梁: 啊~~乞巧~~ 祝: 我家来 临别依依难分开 心中想说千句话 万望你梁兄早点来 July 28 权衡?! 时间紧,任务重,资源少几乎是所有项目都会遇到的问题,既然无法做到需求永恒不变,无法把一天变出42个小时,也没有人手可增加,那么与其时常怨声载道,为何不切实考虑在目前这样的情况下如何做才能高效且保质保量完成工作? 完美主义毕竟不现实,权衡是无奈的,但也是不可避免的,在各类资源缺乏的情况下,要考虑的就是如何权衡才能得到最高效的结果。作为测试人员,眼里容不得一丝瑕疵,但是在现实情况下,不得不做一些权衡与让步:这方面优先级较低暂时不考虑,那方面不影响主要功能就睁只眼闭只眼,可到了交付的那天,虽然说是"通过了测试",但是心里总是不那么舒坦,如鲠在喉,可是又能如何呢?对经手测试产品总有那么些感情,说自己的孩子也好,宠物也罢,还没有梳洗干净,便邋邋遢遢地带到大家面前,总是不那么情愿…… |
|
|