Archives
-
封闭笔记——第四天,平静的前行
2010-03-04 晴 又是微凉 今天的工作比较平淡,只是一切按部就班的前行。各个项目组也开始拆分场景和任务并且入Trac了。 这里面突然发现团队梯队建设的重要性。其实我一直自认为梯队做的还是不错的,高中低错落有致,但是在此次封闭中,还是发现了一些问题。 能够全面把控和影响队友的人还是少。如果说是因为我们第一次采用全新的开发方式导致了很多初级工程师不习惯,很纠结,那么我们在流程制度的推行上是否要更加的慎重和考虑更多的东西呢? 这些恼人的问题值得总结和深思。 晚上还是照例的 Code Review,之后和几个同事针对 TestCase 进行了一些思辨。发现了几个问题,总结一下 从开发的角度,是从下往上看,还是从上往下看? TestCase 是否真的节省时间? 第一次用 TestCase 怎么估计开发时间? 为什么功能性代码写起来很快,而 TestCase 耗时巨长? 其实这些都是我们成长中必经的一些道路。我们每个人都无法停留在 舒适区,我们必然要痛苦和茫然的跨过恐慌区,走进学习区。逆水行舟不进则退,要相信,我们一直在成长、前行。
-
封闭笔记——第三天,项目任务
2010-03-03 晴 微凉 今天是忙碌和劳累的一天。搞的我现在才能写今天的封闭笔记。 今天的流水账有: 场景继续拆分 确认开发流程,如何和现有工具结合 Git使用 CodeReview 今天说话的成分非常的多。其中最关键的一点就是确认了开发的流程,和现有工具结合。 我一直是推行燃尽图的,因为这样可以有效的观察到项目的进度。而且对团队的心理情况也有良好的促进作用。但是这两天一个问题一直困扰着我。当我们采用场景、用例迭代开发的时候,我们还能否采用燃尽图来观察进度,我们如何有效的观察和控制进度? 今天算是有一个可以接受的答案。 由产品人员给出场景(多个),代替以前的一大坨的需求。并建立Trac Ticket,类型为“场景”。 场景会被拆分成为两部分 测试人员根据场景拆分测试用例 开发人员根据场景拆分任务 这两部分是相辅相成的,需要测试、开发人员有一个大纲性质的沟通。 开发人员把拆分好的任务写入Trac,建立Ticket,完成任务卡。 开发人员根据任务(卡)完成燃尽图。燃尽的点为任务。 多个任务合并成为一个场景,完成之后可以单独上线。 这样可以结合现行的工具和流程的情况下,对流程进行初步的改进。希望会有一些好的结果。 晚上闲来无事时候,主动的去骚扰了一下开发的工程师,一起做了一个小范围的Code Review。内容大致如下: 区分行为和数据 用职责的眼光看待类 从使用者的角度看待API设计 内容虽然很少,感觉到他收益还是颇多。我们写代码的时候多思考一些,站的角度变一下,写代码会顺畅很多。
Tags: 项目管理 -
封闭笔记——第二天,开始优化流程
2010-03-02 晴 微凉 今天我们进入了正式的开发阶段,各个项目组也都开始按照自己的步骤进行下去了。 今天非常显著的几点进步如下: 产品、测试拆分场景 研发拆分用例为 TestCase Git 初步使用 今天我一直在整理新的开发流程,相对于以往,新的流程非常强调场景的概念。从产品的需求到最终上线,都是围绕场景的。(具体我会稍后详细解说) 对于场景,第一步也是关系着流程能否跑起来的关键的一部就是产品的用户“场景”。今天我们伟大的产品人员抽象了每一个用户场景,让我们测试和研发的童鞋非常容易入手。 对应着“场景” ,我们的产品、测试、研发都进入了角色,都开始了围绕着场景的战斗。 花开两朵各表一枝,我们先说产品和测试的用户场景。早上,产品和测试的童鞋采取了半结对的方式拆分用户场景,把每一个场景都拆分成为逻辑上可以测试的用例,并记录为Wiki。这样以后对产品的需求覆盖有据可循,也对研发的开发边界有了一个良好的指导。 我们再看另一路的研发。携昨晚测试童鞋拆分用例之威,今天研发的童鞋就已经开始撰写 TestCase,并且已经跑起来了。来,为他们呱唧呱唧。 TestCase 就没什么可说的,今天说说在使用过程中,尤其是初次使用的时候可能遇到的一些问题和疑问。最常见的是: TestCase 和功能性代码貌似只能迭代进行,无法先写完整的TestCase TestCase 中的那些只有名称没有实现的代码,看上去怪怪的。 先说第一个问题,如果是个人开发,当然是迭代进行最为爽快,用例完成,代码也完成。但是对于团队开发,而且是从业人员有梯度的情况,情况可能不同。因为有时候要以一个设计者的身份,有时候要以一个管理者的身份。这时候,我们可能需要更多的统管的一些责任,那么完成大多的TestCase是一种比较可行的办法。 对于第二个问题,其实使我们在开发中身份转换的一个情况。大多的场合,我们是开发的身份是开发人员,我们是细节,这时候我们的视角是从下向上看的。而在我们撰写TestCase时候,是一个使用者和设计者,这时候我们是需要从上往下看的。我们是API的第一批使用者,如果这些API我们自己用着都不爽,那么别人一定会来砍我们的。 另外,我们这次还有很重要的一个环节,就是每天晚上的Review。这里既包含对代码的Review,也包含对TestCase的Review。这里不再废过多的笔墨,我会找时间专项讲解的。 第二天的工作是充实的,我们感受到了团队在成长,感受到每个人在成长。真不错。
-
封闭开发——第一天
2010-03-01 小雪 今天是公司进行封闭开发的第一天。这次封闭开发将为期三周,除了要完成三个项目之外,我还想推动一些敏捷开发。 公司现行的开发流程还是偏向传统的开发流程,不能说不好,但是效率还有很多可以提高的部分。 这次开发一行16人,从产品到开发到测试,可以覆盖到开发流程的全部上下游人员了。大家一早到来兴致颇高,一下就进入了状态,直到现在(北京时间22:53)我们还被测试的老大们着讨论测试用例。看来他们想定下基调,然后这几天搞死洒家们。 俗话说得好,行百里者半九十,好的开始是成功的一半。今天我们尝试了大量的新内容 Git 的使用 PhpUnit 新的开发模式 产品按照用户场景提需求 产品开发共同分析拆分用户场景 测试尽早介入设计测试用例 这些虽然是第一次使用,而且顺利的都用起来也很不容易,但是毕竟走出了第一步。我们会继续前进下去。我也会更加详细进行跟踪报道和讲解。
Mar 1st, 2010 | Filed under 程序设计 -
又是IDE的争论
在邮件列表发现又一个IDE的争论。 我说一下我作为一个实用主义者的做法。 我平常写,Java,PHP,Python,C,HTML, JavaScript,还有一些Shell脚本和RST文档 如果让我在一个IDE上都写好了,那么这个IDE一定要无比强大,但是现实的问题就是可能非常占用内存。所以我使用emacs。 我用emacs,主要使用 1,语法高亮,因为可以让我方便的看到我写的 function 是不是写对了,不用仔细看,只看颜色就行了,我懒嘛。 2,自动补全,emacs的自动补全不是ide里面点 “.” 之后出来的方法列表,而是说你要写 function, 那么你打出 fun 你再使用快捷键补全就可以了。而emacs的特性又决定了,只要你打开的文件,他就可以作为不全的被选 3,多窗口编辑,我有时需要同时看不同的文件、相同文件的不同部分,没有多窗口,我会死 4,etags,我写程序有一个毛病,写Java时候做下的,就是只要时间不特别紧张,我就喜欢看一些类库的实现,并跟踪进去,这时候,没有etags,我会抓狂 5,在双手不离开大键盘区的情况下,完成几乎所有动作 但是我也会使用IDE,尤其再写Java的时候,因为我喜欢eclipse的, 1,import 自动补充,我懒嘛 2,重构,这个真的是非常强大,如果我用emacs,光改import的package就耽误我很多时间 还有,我(几乎)不用 IDE debug/step into 等等的功能,我调试代码都是考log的,我个人觉得这样快,而且可以复用(我还不知道怎么把断点放在svn里面,共享给其他的不用eclipse的人)。 所以总体上,如果是Java项目,我会用eclipse搭建原型,然后写道一定程度(就是不需要很多import的时候),补充ant脚本,完全切换回emacs。只有在需要大量的重构的时候,我再切换到 eclipse。 如果不是Java项目,几乎只用emacs,因为我不知道其他的语言的好用的IDE是什么,我懒啊。 而使用emacs,我会明白什么? 1,整体代码的框架结构。eclipse看到的结构是用看的,emacs会强制要求你记在脑子里面。这个强制会成为一种习惯。说实话,其实这是一个可有可无的,你用eclipse甚至file explorer都可以,但是强制的,可以让我随着项目的前进随着就记住,我懒嘛。 2,记住API,很多使用IDE的兄弟姐妹们非常喜欢 “.” 或者 “->” 之后,IDE给你所有的方法列表。但是我不喜欢,尤其是我自己设计一些API要别人使用的时候。如果只能使用editor这样的土土的工具,你就会让自己做出来更好的,更容易记忆的API,就像说话一样自然,所以很多时候,什么API,就是很自然的就记住了,而且配合我说的自动补全,这样每写一个这样的方法,可以节省我几百和毫秒吧。 3,多语言的同时编辑,最常见的就是一边修改Server的代码(Java、Python、PHP等),一边修改前台的代码(HTML,JavaScript)等。emacs,一个就搞定了,不需要从不同的IDE切换。我知道Eclipse也支持多语言,但是他不能非常好的做到同时支持,至少需要切换一个语言的主题,这会浪费我几秒钟的时间,而且我需要动鼠标,这个不能忍,没办法,我懒嘛。 所以,我基本上90%的时间用emacs。但我不反对IDE,虽然我不怎么用。 而大家说的对程序的理解,运行机制的理解,我觉得这是一个程序员的基本能力。不管工具是什么,都应该明白。这样才能驾驭工具。 工欲善其事,必先利其Emacs。
Apr 20th, 2009 | Filed under 程序设计 -
Build Up Full Performance Model From Scratch
本来是要给公司写的一个文档,但是觉得很有用,所以拿出来和大家分享一下。 趁热尝尝,还冒热气呢。 鉴于我实在是不想在折腾一次了,大家凑合着看这个语法错误百出的英文文档吧 ===================文章的分割线,耶耶===================== Build Up Full Performance Model From Scratch Performance Issues are the big thing for a system. Lots of time, we need a performance model to get the detail performance information. This document is talking about how to build up a performance model from scratch. Checkpoint First of all, the goal of [...]
Sep 4th, 2008 | Filed under 程序设计 -
再次感受TDD
今天下午发现了一个大BUG,好大啊,是我自己的一个DataModel组件不支持数据库的联合主键(composite-id)。然后为了修正这个Bug,我必须要对代码的设计进行改动,这时候,如何保证我的代码修改完了是正确的呢?再次感受了TDD。 好在我人品不错,以前一直有写TestCase的习惯,虽然不多也不全面吧,但是聊胜于无,多胜于聊嘛。在对现有的TestCase进行了简单的修改之后,使得在使用的时候可以使用上联合主键了。也就是从TestCase,使用,设计的角度,DataModel 开始支持联合主键了。然后就是编码,修改,重构,跑TestCase。 今天让我感觉很爽的就是,其中有几个比较诡异的Bug,如果没有TestCase的帮助,我真的是自己想不到的,毕竟这个东西已经有月记没有进行这么深层的改动了。看着一次一次的大红线,大红块,逐渐的变成绿色的,感觉真的是很爽的。最爽的就是,我基本上是可以比较自信的告诉别人,这个东西是可用的,而不是颤颤巍巍的告诉他们,这个,嗯,没测试过,你们包涵吧。
Sep 2nd, 2008 | Filed under 程序设计 -
一个人的项目—-第二天
今天继续很早睡了,凌晨4点,够早吧。 完成了第一版的几乎所有功能,当然仅仅是完成了功能。在使用ScrumWorks进行自我管理的时候还是可以的,但是自己一个人就有一个大问题,就是基本上想到了什么任务就做什么任务,而没有从最初就设定一系列的任务然后自我分配,这就是项目管理的最大的问题。我想也许是因为一个人的缘故吧。但是这里面存在的一个问题就是,这样干到哪想到哪的方式,是很混乱的,几乎就是没有管理嘛。要非说有,也是存在于一个自己脑子里面的一时干不完的TODO list。 为了改变这个龌龊的做法,我对自己进行了如下的要求。 设定最终完成要达到的状态,也就是做的这个东西要满足什么需求 根据这些需求拆分功能和组件 设定Milestone,每一个Milestone要完成什么东西 根据情况设定工作时长,每一个Milestone的完成时间(这个可以酌情) 使用一个工具记录下来这些 Just Do It 这里面的几个难点 针对上面的要求1,很多时候我们是做不到的,也就是我们在做一个东西的时候,大多的时候只有一个笼统的想法,和最后我要把这个东西做成一个什么样子。但是具体的是什么,也许我们并说不清楚。这个东西越大,越说不清楚。所以,我要求自己停下来,好好的想,我到底要一个什么东西,我要干什么,要实现什么功能,要满足我什么需求,这个一定要想清楚。 针对上面的要求2,我们大多时候,是不能非常好的进行拆分的,我们缺乏的是经验,没办法,多做吧。 针对上面的5,一定要用一个工具记录下来,因为你不记录下来,没有监督,那不就是自我安慰了么。现在的工具很多,Trac,Redmine,很多很多的。最不济的,记事本你总有吧,纸笔你总有吧。 在这个为期两天的一个土鳖小项目里面,我发现工具的重要性,我现在是Bug,REF,什么的都放在Trac上面,但是我的Task,时间管理都是使用ScrumWorks(而且这个还是一个试用版)。我没有找到一个能够把他们都管理起来并且很容易结合的东西。对了,Trac 还不支持bzr。 看来没办法,只能自己写了。现在正在缓慢的进行一个项目,就是做一个完整的 Ticket,代码,时间管理的工具,最好天然的支持Scrum。
-
一个人的项目—-第一天
现在在给一个自己的网站 http://www.yes7080.com 写一个类似于百度贴吧的功能。当前合作者出去和老婆Happy了,暂时项目只有我自己一个人。想想,也不能瞎写,就使用一些东西把自己管理起来吧。 刚刚看完Scrum,发现和我平常期望的,理想的,使用的方法很像很像(看来我有慧根)。所以打算自己一个人试试看。并结合TDD等方法,把自己管起来。 毕竟,刚刚入门,而且一个人,难免有东施效颦,丢三落四的情况出现。 第一天,也就是今天凌晨1,项目初创开始新项目,使用bzr开启一个新的repository,开工。采用TDD,构建一个最简单的,最土鳖的测试用例,不要求很完整,只是一个对大多数常用功能的简单使用,目的是为了尽快的搭建出项目原型和框架。遵照Uncle Bob的谆谆教诲,在完成一个土鳖测试用例之后,成功的让Eclipse画出来一坨坨的小红线(编译不过嘛)。然后撰写真正的Interface,还有Abstract Class,真不错,终于编译成功。 收获:这个过程并不是一个浪费时间的过程,而是结合了思考,设计,具体请参见我的《初涉敏捷编程》。这过程中出现了很多的对API的推敲,对类的职能的思考。而且,在写真正的接口的时候,可以不用过多的考虑用不到的方法,也就是我总说的,关注一个类的职能。Duty Oriented. 2,开始功能实现有了用例和接口,就可以写实现了。因为项目的特性,一个只读的数据存储结构是最合适的。但是无奈项目时间紧迫,所以我没有这么充裕的时间去选型,甚至设计实现一个适合这个场景的存储结构。所以我把实现分成了多个部分,第一部分,也就是使用传统的数据库作为存储,这样可以最快的实现功能,并且满足现在访问量并不大的情况。以后随着访问量的增加以及时间的充裕,可以继续完善甚至更改存储体系。 醒目的目录结构是这样的./src./src/com/yes7080/saybar (存放所有的接口,并且这是使用时候的统一入口)./src/com/yes7080/saybar/impl (存放实现)./src/com/yes7080/saybar/impl/datamodel (存放使用datamodel,亦即使用数据库的实现)./test./test/src./test/src/com/yes7080/test/saybar (测试代码)实现使用了二级目录结构,也就是使用impl/datamodel,这样的目的就是因为以后可能出现其他的存储方式。而且,正因为这样从目录解耦,就可以更好的进行设计了(具体的设计思想,我以后会撰文解说的)。 很爽的写了很多,很土鳖的没有采用任何的项目管理。工具使用Trac,但是更多的是一个用于文档和Ticket跟踪。所以我决定对自己采用Scrum进行管理。也对自己有一个监控。 最开始,实话实说,我真的忘记了Scrum具体应该怎么开始了,但是非常简单,用户故事(是这样么说么)只有一个,就是实现一个用数据库的存储。我给自己两天的时间,也就是后天天亮之前完成,大约是还有10-16小时的工作时间。然后在看情况进行修改吧。嘿嘿~暂时给自己定一个时间,然后,继续工作鸟~~
-
初涉敏捷编程
我们都知道一个设计良好的程序是优雅的,我们也知道单元测试是很重要的,有充足的单元测试就可以尽可能的保证一个程序模块的正确性。这两部分是一直困扰我的部分,如何保证一个设计是尽可能的优雅的,还有就是让单元测试测试到尽可能多的测试点。以前的做法都是提前对程序进行设计,然后进行编码,然后编写单元测试代码,再根据觉得哪里不妥修改代码,修改测试用例。 这里我遇到的问题是 设计阶段不能设计的足够精细这一点非常令我恼火,有的想要给别人看的代码,比如开源,要求你的API设计来不得半点马虎,要设计的很合理。前期的脑纸笔的设计方式,会让细节偏差很大。而合理的API基本上都是通过不断的编码得到的。 单元测试用例并不能覆盖几乎100%的代码当你写好了代码之后,你就懒得写测试用例了,尤其是针对一些不总用到的功能。而写出的用例大多都是一个非常完整的场景,而不是针对某一个小模块的测试。针对性不强。 针对这两个让我极其愤恨的问题,我决定使用敏捷编程,测试先行。 我对测试的看法一直是测试(我承认这是一句废话),我以前都是写了代码(也就过了设计阶段)再写用例,这样程序的API设计大都是凭借对代码的理解捏造出来的,理解的深,功力深,API设计的就相对好一些,理解的不够深,捏造的成分就大,后期自己看着都恶心。但是Kent Beck和Uncle Bob告诉我们测试用例就是在进行程序的设计。其实,一个好用的API,都是经过实践检验的,这样自然要不断的编写和修改代码,而我们把这个过程提前,放在最初要设计的测试用例里面。一个测试用例,就是对一组API的调用的描述,也就是场景重现,这阶段已经就是在使用自己的API,也就是检验自己的API。当然,最初的这部分编码连编译都无法通过,因为你要求的所有东西都没有,但也正因为如此,你才能按照你最舒服的调用方式调用API,而不是受到什么限制。 例如 Query query = xxDAO.createQuery(“Target”); query.addExpression(Expression.eq(“name”, “Testing”); 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好很多
Apr 30th, 2008 | Filed under 程序设计