2008年12月16日星期二

关于软件过程的比较



关于软件管理过程,目前敏捷过程最为热门。主要的敏捷过程有以下几种:XP 极限编程, SCRUM, FDD 特征驱动开发, DDD 领域建模驱动开发, ICONIX, ASD 自适应, CRYSTAL 水晶, DSDM, TDD 测试驱动开发, AMDD 敏捷建模。再加上“传统”的RUP。
浏览这些过程会发现这些敏捷过程所涉及的领域还是有所区别的。简单来讲,可以粗略的划分为管理过程设计过程。例如:
  • SCRUM:很明显是管理过程。在实践框架中提供了一些可以明确执行的实践指南。而其中对于设计方法或者过程基本没有什么要求。
  • FDD:应该属于管理过程。其中明确了对项目的进行如何规划。而对设计方法所述比较少。
  • ASD, CRYSTAL:属于管理过程,其中重点讨论对人的管理理念。管理框架具有很大的灵活性。
  • DDD:属于设计过程,重点描述如何从业务需求导出到系统设计编码的过程。
  • AMDD:属于设计过程。
  • XP:比较特殊,不是完整的管理体系。而对设计过程也很少描述,仅仅提供了一些最佳实践。由于其要求非常明确,所以我觉得更接近与设计过程。
  • TDD:应该不算是过程,仅仅是一种辅助设计的方法。所以经常被其它敏捷过程所引用。
  • ICONIX:对管理过程与设计过程都有所涉及。不过更加接近于设计过程。
  • DSDM:不太了解,无法分类。
基于此原因,所以经常可以看到将两种或者以上的敏捷过程组合进行应用的现象。如:SCRUM+XP, FDD+DDD等等。而AMDD和TDD更是经常被其他过程所引用。
不过这也侧面说明,这些敏捷过程往往内容都不够完整,或者说是针对性比较强。

现 在看来,敏捷过程的宣传者针对的往往是一些传统的重型过程,如CMM, ISO等等。而由于RUP内容比较复杂,所以往往也被算进来。这其实是由于对RUP的误解造成的。RUP被设计为统一过程,所以必然包罗万象,以便适应于 更多类型的项目。这就造成了RUP的复杂性,其实也说明了RUP内容的丰富。但是,当具体到某一个项目的时候,必然会根据项目特点或者企业环境因素对 RUP过程进行裁剪,以形成特色的过程。所以针对小型项目,RUP完全可能变成为非常“敏捷”的过程。
不过这也属于一个矛盾:1. 对于小型项目的项目经理来讲基本没有精力或者经验对整个RUP体系进行完整的研究。2. 如果缺乏对RUP体系的研究,就不可能对RUP体系进行恰当的裁剪。
基于这个矛盾,出现了很多伪RUP过程实践。
这样的现象是因为RUP中缺乏对一些比较典型的项目类型的具体指导和模版,来使项目经理可以快速的对RUP开始实践。而在这方面敏捷过程往往做得更好。例如XP过程,提出了明确的原则和实践指南,使得人可以非常简单清晰的学习和实践练习。
基于此,例如XP这样的过程就在程序员中很受欢迎,因为程序员多数项目管理经验不够充足,所有如果有简单而明确的实践规则的话,当然更容易付诸实施。
但 反过来讲,这些敏捷过程对项目类型的要求往往非常严格,例如,XP过程就会要求:项目组规模、办公地点、用户现场、合同类型等等。所以当人们将它应用与不 同的领域时又不得不对它进行改良或者采用其它的软件过程。在这方面RUP就会好很多,深入研究RUP可以使你用一种软件过程应对更多类型的项目
ICONIX是所以受欢迎,就是因为它延续了RUP的思路而有提供了可明确参考的工作步骤。

当然反过来,对敏捷过程的误解也是存在的,例如:RUP的支持者往往认为XP过程没有设计。实际情况是XP过程也是相当重视设计的,只不过方式不同。XP过程不建议进行预先设计,而是使用其它的一些辅助手段保证软件设计的优化,例如TDD、重构等等。

再看看思维方式。新兴的敏捷过程往往宣传自己基于小型迭代,并以此来对应变更,使项目满足客户业务需求。但所谓迭代一词应该更加细分成:“增量开发”与“迭代开发”,之间的区别如图所示。

由此看来,如XP, SCRUM, FDD等过程其实都属于增量开发。而RUP和ICONIX过程属于迭代开发。所以,对此概念模糊的人就会误解RUP更像瀑布模式。
其实增量与迭代无所谓优劣,仅仅是思维方式的不同。

2008年12月8日星期一

关于系统设计的文章摘抄

模型(Model)代表应用程序的数据(data)和用于控制访问和修改这些数据的业务规则(business rule)。通常模型被用来作为对现实世界中一个处理过程的软件近似。
视图(View)被用来组织模型的内容,它从模型那里获得数据并指定这些数据如何表现。
控制器(Controller)定义了应用程序的行为;它负责对来自视图的用户要求进行解释,并把这些要求映射成相应的行为,这些行为由模型负责实现。

有人提到
MVC模式时说MVC代表了模型层、视图层、控制层,我觉得这是不对的。在经典的J2EE三层架构中,三层是分为Web层、业务层、持久化层;这个经典分层是基于分布式应用(EJB)的,也就说,Web层物理上是在Web服务器中, 业务层和持久化层物理上是在应用服务器中。在这种情况下,MVC只是属于Web层这一层的,而不是分为三层。在这种分布式应用中,视图就是JSP(如果采用的话),控制器就是Servlet(如果采用的话),而模型就是就是调用业务层的在Web层中的桩子。假如我们采用轻量级的SSH技术架构,视图还是JSP,控制器是Struts,而模型就是SpringHibernate这里最难理解的就是模型的概念。我觉得模型是有状态和行为的,那么Struts中的Action调用的Servcie方法就是模型的行为,而返回给JSPDTODO)就是模型的状态。

对于一个页面请求,总要有个地方负责处理和页面跳转的地方,这个地方就是页面控制器。页面控制器有两种,一种是如
Servlet的脚本文件,一种是如JSP的服务器页面。对于Java来说,JSP就是只应该用来显示动态的或静态的信息,而不是用来负责处理RequestRedirect页面,否则Servlet就要失业了。尽管一个Web程序可以全由JSP文件组成,但将控制甚至业务脚本杂乱的穿插在Tag中真的是太糟糕的实践了。

贫血模型:是指领域对象里只有get和set方法,或者包含少量的CRUD方法,所有的业务逻辑都不包含在内而是放在Business Logic层。
优点是系统的层次结构清楚,各层之间单向依赖,Client->(Business Facade)->Business Logic->Data Access(ADO.NET)。当然Business Logic是依赖Domain Object的。似乎现在流行的架构就是这样,当然层次还可以细分。
该模型的缺点是不够面向对象,领域对象只是作为保存状态或者传递状态使用,所以就说只有数据没有行为的对象不是真正的对象。在Business Logic里面处理所有的业务逻辑,在POEAA(企业应用架构模式)一书中被称为Transaction Script模式

充血模型:层次结构和上面的差不多,不过大多业务逻辑和持久化放在Domain Object里面,Business Logic只是简单封装部分业务逻辑以及控制事务、权限等,这样层次结构就变成Client->(Business Facade)->Business Logic->Domain Object->Data Access。
它的优点是面向对象,Business Logic符合单一职责,不像在贫血模型里面那样包含所有的业务逻辑太过沉重。
缺点是如何划分业务逻辑,什么样的逻辑应该放在Domain Object中,什么样的业务逻辑应该放在Business Logic中,这是很含糊的。即使划分好了业务逻辑,由于分散在Business Logic和Domain Object层中,不能更好的分模块开发。熟悉业务逻辑的开发人员需要渗透到Domain Logic中去,而在Domian Logic又包含了持久化,对于开发者来说这十分混乱。 其次,因为Business Logic要控制事务并且为上层提供一个统一的服务调用入口点,它就必须把在Domain Logic里实现的业务逻辑全部重新包装一遍,完全属于重复劳动。

贫血模型是对OO的 非常经典的诠释!数据交给s/g,业务全部交给业务对象来完成。耦合度很低,逻辑清晰,重构空间大!而且在业务逻辑上事务控制的关注点也小!但是也很明 显,业务对象做的事情实在太多了,在领域对象上这个叫做超职责。s/g和业务对象分工虽然明确但工作量截然不同, 也就是说这个对象的职责过于复杂,在一定程度上背离了细力度的OO模型原则。

网友: 对某一个实体信息的管理维护,是分出增加、删除、修改还是只看作一个维护用例?
UMLchina_潘加宇:关键是要找出CRUD背后可能隐藏的业务。

网友: 到底要画哪些图?序列图是必须的吗?
UMLchina_潘加宇:
如果不是面向对象开发,只有用例文档是必须的,然后直接编代码都可以。如果是面向对象开发,需要用类图描述结构,顺序图分配责任。


Martin: 关于这些项目中不写文档的说法是荒诞的。文档和计划当然要做,不过他们不再是过程的一部分,而是过程中的一个任务。在敏捷项目中,会有很多任务,有些任务会包含文档化、项目计划等这些管理团队需要做的规范操作。但它们不再是过程的一部分,这句话的意思是说,它们的秩序不是固定的,我们不是一定要先写文档,也不是一定最后写文档,我们在写文档这个工作变得重要的时候来做它,它会和其它任务一样在日程中进行安排。

Martin: 对.NET开发者而言,在学习敏捷开发的过程中最大的挑战就是测试驱动开发。敏捷开发对单元测试和自动化接受测试的要求很高。TDD现在已经被全行业所接受了,就算你是微软,也是一样的。


那么测试代码是否可以完全取代自然语言形式的设计文档呢?我看还不行,原因有三:
其一,测试代码虽然比源代码容易理解,但它仍然是代码,不是所有人都能理解的;
其二,测试代码的宏观表达能力还是不如自然语言或图表;
其三,很多人习惯看文字而不是看代码,彻底改变人的习惯很难。
所以在TDD开发过程中,比较好的形式是自然语言的文档和测试代码相结合,用自然语言的文档做一个够用的设计就行了,这个设计只要详细到模块关系这一级别就足够了,各个模块的详细设计就由测试代码充当。

Q: 单元测试怎么能反映/代替需求 ?

A: 单元测试未必能直接反映宏观上的需求, 但

  1. 功能测试和集成测试能够反映宏观需求.

  2. 单元测试能够反映系统的其它部分对当前单元的需求.

而从文本的角度, 测试用例的名字就是需求的描述. 换句话说, 你从传统的需求文档中把描述抠出来, 放到测试代码中作为测试用例的名字, 你便拥有了可执行的需求文档


当你试图测试一个单元时, 却发现需要创建大量的其它对象, 而且按照你脑海中的实现, 有些对象是在单元内部创建的, 根本无法在测试环境中假冒它们. 这时候, 你即使只是为了减少测试的难度, 也会逼迫自己思考:

  1. 这个单元是否做了太多的事, 承担了额外的职责, 违反了单一职责原则?

  2. 是否应该把依赖让外界设置进来, 而不是自己在内部创建, 这样测试时就能把依赖设置为假冒的实现?

是的, 单元测试警示你思考一下自己的设计


2008年11月24日星期一

业务流程建模与软件项目需求


在软件开发的阶段定义中,以前一直不太分得清需求阶段内部的子阶段划分。
在以前的项目中,我们仅仅出具软件功能需求文档,并且认为这份文档就是全部的项目需求文档。文档的内容主要包括:功能性需求的用例分析,用例内部的流程图(活动图),用例内部的系统原型,如果需要的话,还要加入模块以及的流程图和系统的WHOLE PICTURE,其他内容(包括:非功能性需求,项目业务目标,名词解释,设计人员等等)。

到新的公司之后,刚刚进入了物流项目组大约一个月,发现软件需求中的业务需求和功能需求还是有所区别。
在项目的早期,我们需要对客户的应用系统所涉及的业务逻辑和业务流程进行分析,并形成业务需求文档。这一份文档的目的是能够是项目组的相关成员对客户的业务有更好的理解,或者是新进入项目组的成员能够对项目的业务背景有一个比较完整的认识。准确的定义客户的业务需求对后面的软件需求分析具有指导性的意义。在这份文档中,将主要使用业务流程建模工具,如数据流图、工作流程图、UML活动图等等。
在分析的业务需求之后,进入到软件功能需求阶段。在这个阶段,将根据将来的系统建设需要对业务需求中所涉及到的功能进行重新的拆分组合排序,并进行一些补充。使之更加贴近设计人员的需要。在这个阶段的产物软件功能需求文档中,将会更多的将用户业务的语言翻译成为软件开发专业的业务描述。这份文档的目的是直接作为系统设计的输入,并能够指导开发工作,所以其还需要能够比较容易的进行任务分解。在这份文档中,将会更多的使用用例分析和业务领域分析、原型设计等工具。

目前新公司的物流项目正处于早期的业务调研阶段。在这一段时间内,我目前正在了解有关业务流程建模的工具。以前一直是在使用UML的活动图,但是总觉的其表现力还是不够丰富,所以也经常在使用跨职能的流程图进行辅助。最近查阅了相关的资料发现,UML在业务流程建模领域的确是弱项。在这个领域现在有很多成熟的工具和理论。最典型的是BPMN和EPC
BPMN图是官方组织发布的专门用于业务流程建模的规范。目前的版本大约是2.0。图例非常丰富——不下50多个。也有很多专门的绘图工具,其中包括免费的产品BizAgi Process Modeler和很多基于Visio的图例插件。不过,对于如何规范的规制业务模型的资料,网上却少得可怜。
EPC图不是行业标准或者规范。但是由于能够绘制EPC图的软件ARIS被内嵌在了者名的SAP软件中,所以EPC图基本上是事实上的行业标准。EPC图例并不复杂,但却能组合起来清晰的表现业务流程。
所以在现在的项目中,我尝试的使用EPC图的方式进行了一些业务流程的说明。当然,在使用的过程中,我对EPC的图例进行了微小的扩展。
下面是我做的一个EPC图的例子。

2008年11月17日星期一

关于业务模型分析的绘图需求

在业务模型分析过程中,发现有以下的一些绘图需求:
  • 需要能够表达工作流程。
  • 需要能够表达系统的功能。
  • 需要能够表达工作流程中的动作。其中最好能够区分关联到系统功能的动作和系统外部的动作。
  • (系统功能和流程中的动作或许可以等同对待)
  • 需要能够表达系统功能的输入和输出,可能是:纸质的单据,电子数据或者业务对象。
  • 需要能够表达操作系统功能的系统角色以及其所属的组织结构。
  • 需要能够表示出发系统功能的事件。或者系统功能完成之后的流程状态。
  • 需要能够表达流程分支的情况,例如:and, or, xor,并行等等。
  • 需要能够对某一个系统功能或者动作进行扩展。例如某一个系统功能中可能会有其子流程。
  • 需要能够对上述的业务对象以及系统角色进行“引用”方式的绘图,以便统一管理。
  • 可以对业务对象进行详细设计(类图)。
  • 最好能够附带对某一节点关联系统页面原型的设计功能。

目前正在参考以下一些工具,但似乎都不能完全满足需求。当然也有可能是没有完全发掘以下一些工具的全部功能。
  • UML活动图+UML类图
  • EPC图(Event-drive Process Chain)
  • Serena Prototype Composer工具

2008年11月13日星期四

Google Chat可以Video

今天一早打开GMAIL主页,在左上角发现了一个新的链接:New! Video chat
点击之。
发现被自动引导至www.google.cn主页,奇怪。
于是重来一遍,在浏览器刷新的过程中使用ESC,遂看到video chat页面。再次使用该方法,终于下载了google video chat插件。

OK,现在在gmail主页中发现了video chat设置,成功。

2008年11月11日星期二

应用软件设计需要原型设计工具

依据ICONIX过程与AMDD方法,敏捷设计的过程可以大致总结为以下的几个步骤:
  1. 进行用例分析(或者用户故事),同时设计初步的域(domain)模型。
    输出:初步用例、领域模型
  2. 同时参照用例和领域模型进行系统健壮性分析(robust)。
    输出:健壮性分析图、更新的用例、初步细化的系统类图(由领域模型而来)。
  3. 参照健壮性分析图,进行系统详细设计——画出UML顺序图。
    输出:顺序图(针对每一个用例至少一个顺序图)、最终细化的系统类图。
以上过程比较清晰,其中robust分析过程是为了弥补用例分析用顺序图之间的GAP而加入的过程。
不过,在第二步与第三步之间,如果能够加入原型分析(界面草图与页面流程),则其输出文档显然比系统顺序图更加直观。系统原型分析的结果能够更加有助于编程人员对与系统需求的理解,而这一步也是AMDD方法建议的步骤。
所以建议加入一步:
2.5. 依据用例分析文档,健壮性分析进行系统原型设计
输出:原型分析文档(页面流程图、系统界面草稿)

你现在在使用什么工具进行系统原型设计?MS Visio, Powerpoint, yEd, Dreamwaver, Flash还是纸和笔?(Sparx EA中虽然集成了界面设计工具,但是毕竟太过简单了)
其实现在已经有很多专业的原型设计工具了,主要的有以下几种:
  1. Axure RP
  2. Caretta GUI Design Studio
  3. iRise Studio
  4. Elegance Lucid Spec
  5. Mockup Screens
  6. OmniGraffle (only for MAC)
  7. Balsamiq Mockups
    有免费版本,但是有功能限制(不能保存,只能其他工具进行抓图了)。但是画出来的图是手写风格的,真的非常漂亮。
  8. Serena Prototype Composer (free)
    免费版本,功能非常齐全(建立项目、多层次的流程设计、界面设计、数据流转设计等等)。
  9. Pencil (firefox addon)
    居然是作为firefox插件形式的产品。免费。虽然只有界面设计功能,但是已经足够令人惊奇的了。
以上产品功能各具特色,都是很成熟的产品,而且非常容易使用。但是值得提到的是Serena Prototype Composer,使我们可以免费的使用到高品质的产品,强烈建议使用。

2008年9月11日星期四

完美To-do List: Toodledo

使用很多年to do list工具了。但是越来越发现难以找到能够完全满足要求的。
结合GTD理论以及柯维的First Things First理论,现在总结需求如下:
  1. 需要能对任务的内容(context)进行分类
  2. 需要能对任务的状态(status)进行分类(next action, action, waiting for, sometimes, finish...)
  3. 另外,各种任务有以下区别:
a. 某一阶段的目标Goal
b. 日常工作
c. 特定日期需要完成的任务Task
d. 某段时间需要不停关注,例如:项目(project),一般有起止时间。
e. 仅仅是某些想法,记录以备参考。Reference
  1. 任务管理需要能够集成日程表(calendar)
  2. 结合日历,可以每天记一些工作日志(相比BLOG应该更加偏向于一些机械性的工作内容)。
  3. 任务(task)不等于日程(appointment)

可用的软件中:
  • outlook理念落后(outlook2007还可以,但也不完全匹配)
  • GTD类软件普遍功能简单,而且不能集成日程表
  • Google Calendar只有日程,没有任务。
  • PlanPlus过于笨重,而且价格不菲。

直到最近看到了www.toodledo.com,发现其可以完全满足上述需求。而且还有额外的功能:
  • 集成Google Calendar
  • 合作与共享
  • 其他功能还在摸索中。

不过强烈建议使用。

新款密码管理工具: LastPass

经常上网的人,有许多username和password需要记住,例如:电子邮箱,网上银行,网上购物,论坛,求职网站,BLOG,社区网站,同学录等等等等。
想全部记住不同的密码,很难;全部使用相同的密码,极不安全。于是乎出现了很多密码管理的软件来帮助人们记住密码。流行的软件有以下一些种:
  1. AIRoboForm:这个领域最著名的产品。功能十分强大,使用方便,能够集成多种浏览器。能够自动识别网站切进行登录,能够管理注册表单,还能够记录一些与网站无关的个人保密数据。唯一的不足是无法进行网络存储且同步。虽然是收费的软件,但物有所值。
  2. KeePass / ALPass:免费产品。KeePass的缺点是操作比较繁琐。ALPass的缺点是仅仅支持IE浏览器。而且两款软件的数据也都是本地存储。
  3. Firefox插件,如Magic Password:免费产品,使用方便。这类软件多是利用网站的关键字和用户设置的主密码来自动计算网站登录的密码。优点是生成的密码非常规范,不易破解,而且没有任何数据进行本地或网络存储,非常安全。缺点是仅仅支持Firefox浏览器,且对插件的依赖性很大。
  4. 密码管理网站:优点是对本地系统没有任何要求,只要有浏览器即可,网络存储,所以随时可以使用。缺点是操作非常不便,基本上需要手工维护。典型的如:豌豆网, PassPack, Clipzz等等。
  5. 浏览器自带的密码管理功能,如IE, Firefox, Opera。功能往往很弱且不完整。
  6. Google Browser Sync:现已停止下载,主要是将Firefox的各种数据(包括书签、密码、Cookie等)同步到GMAIL帐号中。非常方便,缺点是只支持Firefox浏览器。

新产品LastPass与众不同:
  • 集成不同的浏览器,包括IE和Firefox。
  • 帐号密码网络加密存储,所以不需要进行备份。
  • 能够进行自动识别与自动填充,操作方便。
  • 能够自动生成密码,也可以手动输入密码,所以对软件本身没有很强的依赖。
  • 能够导入流行的密码管理软件的导出数据,包括:AIRoboForm,KeePass等。

结论:强烈推荐使用。

2008年9月3日星期三

Redmine试用

由于project server庞大而且安装使用复杂,所以正在考虑使用一些轻量级的项目管理软件。暂时选中Redmine。

  1. 安装
  • 安装instantrails
  • 启动instantrails服务
  • 使用phpmyadmin在mysql中建立数据库
  • 配置database.yaml
  • 启动webrick
  1. 特色
  • 建立项目
  • 建立子项目
  • 自定义项目角色
  • 自定义角色的权限
  • 自定义问题状态流程
  • 自定义问题状态
  • 自定义跟踪标签
  • 自定义版本(相当于里程碑)
  • 自定义问题类型
  • 分配任务
  • 任务日历
  • 任务甘特图
  • 项目成员根据问题(相当于任务)填报工时
  • 灵活的工作量统计报表
  • 基于项目的wiki
  • 基于项目的文档管理
  • 基于项目的论坛
  • 上传文件
  • 新闻/公告
  • 系统活动跟踪
  • 里程碑状态报告
  • 个人的dashboard
  • 缺陷跟踪(问题跟踪)
  • 多语言支持,多时区支持
  • email自动发送
  • 导出到csv/pdf…
  • 版本控制支持(包括subversion, cvs等等)
  1. 没有的功能
  • 人员成本
  • 项目预算
  • 问题不能有子问题(问题不能分层)
  • 问题只能分配给一个成员
  • 版本控制不支持:vss, clearcase, starteam
  • 甘特图的显示细节无法进行自定义
  • 没有pert图
  • 无法定义项目流程规范(模板)
  • 虽然可以进行缺陷跟踪,但是很遗憾无法同时集成test case管理(如果testlink能够集成redmine就好了)

结论:
  • 基于项目组级别的项目管理软件,轻量级的,足以应付一般的软件管理。
  • 不具备企业级的功能,但是如果能够配合一些管理手段的话,也足够用了。
  • 对于一款开源的产品来讲,Redmine已经非常出色了!

2008年9月2日星期二

谈谈人员素质

在国内的现状就是这样的:由于IT行业人员需求量大,而且平均工资水平也还过得去,所以有大批的人才虽然从性格、爱好、综合素质等多方面来看并不适合这一行业,但是出于就业的考虑,也加入了这一行。
在上一家软件外包公司,我参与了3年的毕业生招聘工作,就是说,招聘部门负责面试综合能力,我来负责面试技术。中国的高校发展参差不齐,所以我明白我不能过分苛求应届的毕业生要有某某项目的实战经验。于是乎,我对毕业生的考察以课内的基本功为主。

数据结构
第一题:没有指针机制的情况下,如何实现链表结构?(只有20%左右的人能够回答出使用数组,其中又有一半的人是蒙的而不知道如何实现。)
第二题:哈夫曼编码的作用是什么?(大约60%的学生能够提供正确的答案。)
第三题:列举出你所知道的排序算法的名称,仅仅是名称就可以?(大约90%的学生回答出了冒泡排序;有70%的学生同时回答出了插入排序;又有20%的学生同时答出了快速排序;在我的印象里,几乎没有人能够提及谢尔排序、归并排序和堆排序等等。)
操作系统
第一题:请解释一下什么是进程死锁?(令我吃惊的是,大约只有40%的学生能够让我确认他正确理解了进程死锁。)
第二题(如果你正确回答了第一题的话):最常用的避免进程死锁的方法是什么(提示:教材中所讲解过的)?(只有10%的人能够想起来PV信号灯)
第三题(如果前两道都答对的话):请解释一下操作系统的内存分页管理机制?(要求不高,能够提及局部性原理即可,但是只有零星几个人能够通过)
数据库原理
第一题:请列举出数据库表设计原则中,都有哪几种范式?(大约60%的人能够说出第一到第四范式)
第二题(如果答出第一题的话):其中那一种范式又叫做正规范式?(只有20%的人回答是第三范式,其实说第三范式也不准确,不过马马虎虎就算过了)
C语言
第一题:在struct中可以定义属性,但能否同时定义函数?(当然不可以,否则不成了class?这道题难住了40%的学生)
第二题:函数能否作为另一函数的参数?(呵呵,我相信很多人听到这个问题的时候都蒙了)

其实我从心里最想问的问题是:你们大学4年都学什么了?

我在上大学期间绝对不是什么好学生,在班里排名中等,逃课作弊不在话下,所以对不用功的学生绝对没有仇视心态。不过,我的同学当中,就算最不用功的学生也会非常用心的去听数据结构课程,因为我们都知道:我将来想干这个行业,就得指着这个吃饭啊。我们公司的生源学校也不全是二三流的学校,也包括了几个211工程中的国家重点院校。
不过,在面试的学生中,有两类人回答问题的结果不错:一是考研失败的学生,因为这些内容他刚刚复习过的(课程年了两遍,效果当然不同);二是工作几年之后又读了硕士的研究生毕业生,因为这些人在读研的时候更清楚自己想要学些什么。

我曾经面试过这样一个研究生毕业生,上面的所有问题对答如流,于是,我稍稍来了一点比较邪恶的:
问:C语言,现在有a, b两个变量,想把它们的值交换过来,有什么方法?
答:比较通常的做法是使用第三个临时变量,不过使用“异或”更有效率。

回答完这个问题之后,我告诉人力资源部门:这个人应该高于普通研究生入职标准2000元的水平进行招聘。后来我就再没有见过这个学生,很遗憾,可能多给2000还是少了点,要不然就是老板没有批准我的建议。

再说说在职人员的招聘。
由于以前的公司是做业务应用系统的,所以程序员需要天天和数据库打交道,SQL语句经常使用。所以在招聘的时候,我可以不太看重程序员对编程语言的熟悉程度,但是SQL语句必须熟练。针对这点,我编了两道SQL语言的笔试题。题目不太复杂,第一道主要是考group by 和case when,第二道主要是考union。我准备给候选人们半个小时的时间来完成这两道题。但是这两道题可是难住了一大部分前来面试的候选人。以至于我在怀疑这两道题是不是太难了?
于是我将这两道题发给了两个同事来做测试,其中一个是项目经理,另外一个是作为初级程序员的一个小女生。5分钟之后项目经理交卷。15分钟之后初级程序员交卷。两个人提供的答案和我的参考答案几乎完全相同。

有意思的是,后来我通过MSN MESSENGER将这两道题发给了我一个正在读研的师妹。大约半小时之后,答案发送回来。其中第二道题的答案思路非常奇特,我仔细的看了之后,发现不仅能够得到正确结果而且比我提供的算法效率还要高一些!非常遗憾,我最终没能说服她毕业之后来到我们公司。当然,这对她个人来讲不是坏事。

说到算法效率,还有一个有意思的故事:
我们曾经有一次给客户开发一个业务应用系统。系统的报表功能中,有一个关于返修率的报表。在系统试运行期间,发现该报表无法得出结果。后来,我发现,程序员在生成报表的后台SQL语句中使用了函数,在当时的数据量情况下,粗略的估计这条SQL语句执行完毕需要80几个小时!I am shocked by the result!
我只得亲自出手在客户现场进行优化。2个小时之后,将报表的生成时间控制在了5分钟之内。
后来,其他的项目组在对该客户进行别的项目时,也用到了返修率报表。当时那个项目组的人员并不太清楚返修率报表以前的故事,所以委派他们组里的一个小女生来开发这个报表。结果呢?新开发的报表平均生成时间在15秒之内!I am shocked by the result again!

很遗憾,最终我没能在我的部门中留住这个小姑娘——她后来被人力资源的人偷偷的卖到客户现场去了。为了此事,我和人力资源的经理直吵到了副总经理办公室。但是木已成舟,也无可奈何了。

2008年9月1日星期一

极限编程是否符合中国国情?

XP为什么不适合国内的现状?下面是我个人的一些看法。

针对极限编程的准则:

  1. 用户故事
    先说说XP的描述:不需要在一开始完全了解需求,因为以后很可能会变化。不需要一开始就了解详细的需求,只需要到可以估算的程度就可以了,可以一边实现一边详细了解,因为有现场客户在。不需要详细的需求文档,代之以用户故事,因为沟通胜过文档,而且用户故事简单又容易编写。
    我的想法:用户故事体现了将需求分解为条目的思想,在这点上来说,是可取的。但是其他的说法就有问题了。
    首先是不需要一开始就完全了解需求的说法。对于互联网项目来讲,这种说法可能是正确的,因为需求变化非常快速。但是对于一般的业务应用系统来讲呢?需求会变化,但是关键的业务流程是相对比较稳定的。当你明明可以掌握全局的时候如果还要偏激的从局部开始着眼的话,岂不是有些钻牛角尖了?就好比要盖一座房子,在初期我可以不清楚将来的卫生间如何装修,但是总是需要在一开始的时候就了解需要打多深的地基吧?全面了解需求肯定有助于在项目开始时候建立正确的系统架构方案。
    其次是关于需求文档的问题。不可否认,在一定的项目规模内,有现场客户在,再加上充分的沟通,能够达到比文档更好的效果。但是,限定条件是不是太多了一点啊?大一点的项目,如果需要40个成员都需要和现场客户进行沟通怎么办?另外,我们知道,很多项目都会一期一期的做下去,铁打的营盘流水的兵,几期项目做下来,项目组成员甚至现场客户早就不是原来的人了,这些人靠什么来对项目进行了解呢?是不是项目组的老员工每个人都能够知道项目的所有细节呢?有很多情况,如果想要比较透彻的理解需求和业务,则需要对该业务的发展背景以及生成原因有所了解,程序员和测试人员当然有权了解这些。而这些当然都需要有文档来进行传承,仅靠用户故事显然不能胜任。有很多情况,我们需要从更高的层面来观察客户的业务,需要看到一张客户业务的全局性视图,而从用户故事那里我们能够得到什么呢,全部都是局部的片段。有很多时候,一些非常复杂的业务流程是技术人员和客户进行艰苦的讨论得出的成果,这些讨论的过程和结果如果不能够记录下来的话,早晚有一天,你会发现艰苦的讨论经常会重复的出现。
    第三,我们需要在项目初期就明确项目的business goal,明确项目边界,我们还需要明确项目的非功能需求,这些都是用户故事所无法承担的工作。
    最后,用户故事代替需求需要有一个非常严格的配合条件:必须要有现场客户,并且进行结对编程。
  2. 紧急设计过程
    XP的原则:对于每个故事做少于15分钟的预先设计,主要设计工具是白板和CRC卡片,使用最简单的方式来实现眼前的问题。对于系统中出现的问题,使用重构来解决。
    我的看法:XP承认这样会带来一些问题,所以必须严格执行配合条件:持续的重构
    同样,对于互联网项目来讲,有一定的道理,但也是局部的。而对于业务应用系统来讲呢?对于相对比较稳定的需求,我们仍然需要走到哪里设计到哪里并且修改的哪里吗?设计阶段多花些时间能够避免的问题依靠编码之后的重构来进行解决吗?重构的工作量会比预先设计的工作量小吗?(按照教科书的说法应该是被放大10倍了吧?)这不是人为的造成的浪费吗?你的客户除非就是你某个uncle,能够允许你如此糟蹋他的资金。
    中国古人扁鹊曾经介绍:真正的医术高手其实是他的师兄,但是他的师兄为什么没有他的名气大呢?因为扁鹊的师兄总是在别人的健康又出现问题的前兆的时候,就已经出手化解了。(这才是高手中的高手啊!)亡羊补牢虽不算晚,但是防患于未然岂不是更好?
    事无巨细的预先设计是不现实的,但是完全省略也不是个办法。
    设计文档需要吗?显然非常需要。还是那句话,很多项目是需要进行延续的。对于一个新的项目组成员来讲,源代码就算再规范,其可读性也比不上设计文档。做人真的不能只想着自己方便……
    说的更远一些,你的项目组中的经验丰富的有设计能力的成员将无法充分发挥他的聪明才智。他将经常看到别的一些经验不够多的程序员对子写的低水平代码,然后对他们进行重构。这种感觉就像经常需要给别人擦屁股。
  3. 现场客户
    XP的原则:客户长期与开发人员在同一间办公室办公,随时解决开发人员关于需求的问题。现场客户负责编写用户故事,负责决定用户故事的优先级以及实现顺序。现场客户负责编写验收测试用例。
    说说实话吧,你见过这样的客户吗?
    哪个客户的公司能够安排一个全职的客户代表来参与到项目中呢?如果真的安排了一个客户代表的话,他真的能够全面了解需求并对之进行把握吗?
    哪个客户公司的客户代表有能力完成这些任务呢?如果有的话,我看其他的XP原则就算都不坚持,项目结果也不会差到哪里去,因为你的客户代表本身就应该是一个很有经验的项目经理了。
    我们对客户的要求过高了一点点吧?
    而且,如果你所负责的项目的业务在客户公司是跨部门的,那该怎么办?每个部门派一个客户代表来吗?
    我看最有希望实施现场客户原则的项目应该是那种为公司内部开发的业务系统。即便如此,也很玄。
  4. 小型发布
    XP的原则:每隔一到两个月对客户进行一次系统发布,尽量早的让客户看到可执行的系统。
    我的看法:非常好。但是发布规模小到什么程度不能一概而论,只能说是尽量小。要做到小型发布,则必须先实现持续集成,否则很难承担多次的发布成本。
  5. 规划
    XP强调了对每个迭代进行规划。
    我的看法:XP的说法并没有错,只是还缺了一些东西。我们需要对整个项目进行规划,虽然越远期的计划可能越粗略,但是还是很有必要的。
    软件开发的合同不仅仅只是要求“我限定你这些时间,你看你能完成什么?”,还会要求“我需要完成这些功能,你看看你需要多长时间?”所以,做到哪里算哪里的想法似乎只能存在于政府或高校的研发部门吧。
  6. 隐喻
    在XP中,隐喻用来使项目成员对于系统的实现方式达成共识,但是似乎XP的教科书中对隐喻也没有进行很透彻的讲解。
    在我看来:隐喻是设计和沟通的辅助手段,适当的应用效果理想。但是也仅仅就是一种辅助手段而已。
  7. 简单设计
    XP的原则:力求使用最简单的方式实现当前的需求。简单的就是最好的。
    我的看法:这个说法本身就非常模糊,无法度量。简单与复杂都是相对的,仅仅存在于人们的头脑中,我觉得简单的问题可能你就觉得非常复杂。现实当中无法一概而论。
    另外,所有的时候最简单的就是最好的吗?典型的如8皇后问题,8重循环是最简单的解决方案……
    其实我们所追求的应该是不做不必要的复杂设计。
    同样,如果需要保持简单设计原则有效,则必须配合重构原则
  8. 结对编程
    XP的原则:结对编程的优势在于:代码会被100%review,有效地降低代码缺陷率,提供了很好的机会进行知识传递,使每个成员都有机会了解系统的全貌,提高生产效率。更换结对的周期从半天到3天不等。
    我的看法:结对编程优点与缺点都很明显。
    每个项目组的成员都是有自己的特长和喜好的。最成功的管理是充分发挥每个人的优势,而不是将每个人编程一模一样的编程机器。有的人一边讨论一边工作时思维会更加活跃,而有的人则是喜欢独自安静的思考。同样,遇到不解的问题时,有的人喜欢立刻向别人请教,有的人喜欢现场是自己解决。我们必须面对这些差异性,而不是试图将它们消除。从这个方面来讲,XP显得不那么以人为本。
    开发人员作为技术人员群体,其中有相当一部分人个性很强但主动沟通能力不足。在国内,这样的情况则更为夸张一些。而往往这些技术强人在项目组成员当中有很有影响力。在这样的情况下,如果我们不得不强迫进行结对编程的话,我想,管理层后面将面临非常棘手的问题。
    结论:结对编程是好东西,但需要根据具体情况适度运用。要想进行结对编程,必须具备项目组统一的编码标准
  9. 代码集体拥有
    XP原则:项目组的所有开发人员有权更改所有的代码。每个人都对所有的代码负有责任。
    我的看法:容易落入的陷阱是:没有人对代码负有责任。
    代码集体拥有的前提是结对编程。否则的话,这就是一句空话。
    编程有时候和体育竞技有些类似的地方:高手的某个出招(实现技巧)在庸手看来是非常愚蠢的。在这样的情况下,庸手会根据代码集体所有权理直气壮的对高手的精品代码进行重构……
    结论:代码集体拥有可以实施,但是不能简单处理,需要进行更多的沟通和一些技巧。
  10. 持续集成
    XP原则:开发人员坚持随时进行提交,系统每天一次集成。
    我的想法:这是很好的原则。但愿我们能够做到。
  11. 编码标准
    XP原则:实行项目组统一的编码标准,严格执行。
    我的看法:这是最基本的。而且越严格越好。我们时刻需要提醒自己:软件项目的产出是产品而不是艺术品。开发人员的想象力不需要浪费在这样的地方。每个人写的代码不仅仅是给自己看的。
  12. 测试先行
    XP原则:对于每一个用户故事,在开始代码之前,现场客户就需要编写验收用例,而开发人员需要先编写单元测试。这样能够保证每一个用户故事是可测的而且是自动化测试。
    我的看法:这是个非常令人憧憬的奋斗目标。但是,理想很美好,现实很残酷。
    作为一个典型的国内软件公司来讲,你所处的项目小组是什么样的人员素质呢?如果项目组有10个人的话,那么其中3 个有经验的开发人员,具有一定的设计能力。3个经验稍差的熟练工,另外大约还会有2个应届的毕业生。2个专职的测试人员,大约1-2年的工作经验。这应该算是平均水平了吧,很多团队连这个水平也达不到。这样一个团队存在什么问题呢?
    开发人员不会做测试,更加不会写测试用例。个别开发人员甚至不太清楚单元测试是程序员的责任之一。测试人员不会写代码,多数都是高校it专业能力不足的毕业生,接收单位经考察认为无法胜任开发工作,所以就去做测试吧。并不夸张,现状就是如此。
    在这样一个团队中强制执行测试先行,简直就是自虐。
    要实现这样的目标需要循序渐进:第一步要求编码人员自己完成单元测试并养成习惯,要求测试人员能够撰写全面的系统测试案例;第二步要求编码人员能够编写单元测试代码,要求测试人员能够运用自动化测试工具进行回归测试;第三步要求编码人员将单元测试编码工作提前到编程之前进行,要求测试人员提前根据需求编写自动化测试脚本。
  13. 重构
    XP的原则:随时对代码进行重构,要进行残忍的重构。
    我的看法:有时候重构是必需的,但是重构不能代替预先设计。
    进行重构时也需要小心,基于两个因素:
    第一,你的项目组成员有没有能力进行正确的重构?中国的开发人员有百分之多少充分理解了设计模式呢?而耐心学习过重构的人会更少一些吧?我看你还是现在项目组内部做一些技术培训再说吧。
    第二,你的老板或客户能否允许你这样做?重构是一件需要消耗成本、不产生利润又需要冒很大风险的活动,至少表面看上去是这样的。去说服你的老板支持你的做法对每个人来讲都是挑战。
    实施重构原则的前提是:必须实施代码集体拥有原则
  14. 每周工作40小时
    XP原则:加班只会造成质量低下,要坚持每周工作40小时。
    我的看法:这个不难,我所管理的项目没有实施XP,也都轻松实现了这个原则。

上面就是我对极限编程的一些看法,极限编程并非一无是处,而是不适合中国国情。而且极限编程的各个实施原则之间是紧密耦合互相补充的,所以很难进行裁剪。

在我看来,极限编程的最大问题就在于“极限”二字。“水满则溢,月盈而亏”是国人都明白的道理,所以对于极限编程而言,我们都需要问一句:“把所有的事情都做到极端就好吗?”

最后,推荐ICONIX过程,一个相对比较中庸的敏捷过程,实施起来也不困难,指导明确,效果明显。

2008年8月31日星期日

新工作,项目管理以及一些相关软件

新的工作入职已经两个月了。进入项目两周之后慢慢发现,这个项目是在是一个烂摊子。作为这个项目的副项目经理,以我的工作经验而言,放眼望去,几乎到处都是管理上的错误典范。为了将来能够有机会对项目组进行改进,现在自己在慢慢的列出这个项目中的一些问题,以备将来能参考。列表如下:
  • 项目管理不严格,进度前松后紧,大部分阶段人员工作量不饱满,后期全体加班。
  • 缺乏项目的整体计划,项目组成员不知道项目的里程碑和各个阶段点。后期补了项目计划,但难以追踪,其中有一部分人为原因。
  • 由于没有明确计划,测试人员感觉无所适从。测试人员对项目质量缺乏信心。
  • 个别有经验的程序员不愿将已有的实现进行文档化,对工作交接以及后期维护不利。
  • 项目缺乏设计,导致代码质量不高。
  • 缺乏统一的编码规范,没有必要的代码走查。
  • 沟通不畅,程序员不了解需求,导致经常发生返工现象。
  • 项目组成员对分给自己的任务责任心不强。
  • 项目组工作氛围沉闷。
  • 日常工作分工不明确,例如没有明确指定SCM/SQA人员等等。
  • 对常用功能的设计缺乏基本的规范,导致经常出现低级bug。例如输入合法性检查等等。
  • 没有建立问题报警机制。
  • 缺乏政策性的文档提交列表以及文档模板或规范。
  • 缺乏任务管理系统和报工系统,难以统计项目成本。
  • 缺乏人员评价机制。奖惩制度不明确。
  • 缺乏测试案例管理系统。
  • 缺乏需求追踪表,对设计和测试进行必要的覆盖度审计。
  • 测试时间过短,无法进行充分测试。没有充分利用单元测试工具和自动回归测试工具。

呵呵,听起来想是能犯的错误都犯了。

当然,仅仅找出问题还不能够算是有建设性,找出并解决问题才是管理人员需要做的。其实,只要公司能够给我明确的位置,改变现状应该并不太难。当然,对于现在的情况,不要奢望能够一口吃成胖子,循序渐进是比较现实的方法。

由于现在天天在客户现场上班,没有办法接入互联网。可以这样也算有利有弊。好处就是:可以有充分的时间进行一些学习。

例如:仅仅用了一整天的时间就详细的读完了一本关于XP的书,并且还做了笔记。

最近看了一些关于XP软件过程的书籍,心里在想是否可以解决目前项目中的问题。看来人真的是很容易被洗脑的,尤其是对于自己没有经历过的事情。我几乎是充满期待的憧憬着将来能够在项目中应用XP。

但是,同时也看了一本叫做《重构极限编程》的书(内容是批判XP的)。结果,发现我在这本书里面感受到了更加强烈的共鸣。

今天突然发现,在这里的BLOG中,我在2年以前其实就对XP做了结论性的记载。其实我在4年以前就已经比较详细的研究过XP了。结论和现在基本相同。

和当初一样,我现在还是觉得ICONIX过程是比较适合国内现状的敏捷过程。不过,在ICONIX的经典书籍中,主要还是对于建模过程比较偏重,而对项目管理方法涉及较少。有些遗憾。

公司让我在业余时间研究一下MS Project Server。试了几次才发现,安装过程居然是如此的繁琐!微软的产品麻烦到了如此地步,还是比较少见。而且还是非常昂贵。于是上网去寻找一些开源的或者免费的产品。

结论:开源产品少得可怜。有限的几个,功能少,质量差。基本无法满足需要。

于是转向免费产品或者便宜产品:

  • kiwi manager:收费产品,BS模式软件
  • VersionOne:有免费产品和收费产品,BS模式软件,主要针对敏捷过程
  • ComindWork:收费产品,BS模式软件
  • PlanBee:收费产品,BS/CS模式软件
  • TargetProcess:有免费产品和收费产品,BS模式软件,主要针对敏捷过程
  • Rally:有免费产品和收费产品,BS模式软件,主要针对敏捷过程
  • Mingle:收费产品,BS模式软件,特别针对敏捷过程(极限编程)。极耗资源。
  • ExtremePlanner:针对XP, SCRUM过程,收费产品。

再有就是一些online service:

  • ComindWork:收费产品
  • Basecamp:著名的小型项目管理网络应用,免费产品
  • everydo.com:basecamp的我内仿造品,免费,仿的还不错
  • Projectmanager.com:收费产品
  • Goplan.info:有免费产品和收费产品。免费产品功能很少。
  • Liquidplanner.com:收费产品
  • PlanProjects.com:免费产品,功能较少。
  • Wrike.com:收费产品
  • Huddle.net:有免费产品和收费产品。

有一些开源产品值得注意:

  • Redmine:其实就是Basecamp的开源版本,可以安装在本地。
  • Xplanner:专门针对与敏捷过程。可以支持SCRUM和XP,功能比较单一。

其他的:

  • ]project open[:最著名的开源产品,功能比较多。但是难以使用,界面丑陋。
  • dotProject:软件主页失效。仅仅在sourceforge上面有项目。安装复杂。
  • Onepoint Project:有免费版和收费版。不过功能有些简单。安装复杂。
  • GanttProject:只能算是一个画甘特图的桌面工具。

2008年8月13日星期三

对于书签的管理

长期以来,一直在寻找更加方便的书签管理方法。IE自己的收藏夹管理功能比较弱。于是使用一些书签管理软件。
曾经使用过的最典型的这类软件就是URLMenu和AcqURL。后来发现即使使用这些软件仍然有问题:对这些软件的数据库文件需要进行备份和恢复(以备重装系统),另外如果在多处上网的话,就无法同步数据。
再后来开始使用一些online的书签管理工具,最典型的如: google bookmark和del.icio.us。当然还有firefox下面的Google Browser Sync。
最近,我注意到一个问题:
其实在大多数情况下,我经常使用的网站地址并不很多,这些网址其实完全不用使用书签我也可以记住。
另外一些网址,有可能我在浏览的当时会觉得比较有用,但是过后有可能一年到头也访问不了几次。对于这些地址,google和百度足以临时解决我的问题。对于这类地址,需要记住的往往是一些关键字,例如XX软件的名称等等。
其实书签有用的时候多数是在第三类地址上:使用频率中等(比如一个月会用到几次),地址有比较复杂。这类地址最典型的是网上银行网站。
所以,目前看来,主要寻找的解决方案是:
1. 对于第三类地址的书签管理。
2. 有很多时候,我在浏览时,想收藏下来的其实是网页上面的某一篇文章,而不是整个网站。所以需要寻找文章收藏工具。这类工具也有一些典型的软件。 桌面版的如:MyBase,良友,Evernote等等。 在线的如Clipmarks,Google Notebook等等。在线工具显然比桌面版有很大优势,但是Clipmarks操作并不方便,而且速度也是奇慢,Google Notebook更是经常无法访问。
3. 另外一类就是密码管理,如:招聘网站,论坛的,软件网站的,EMAIL的等等等等。 这类工具其实也是,在线的工具显然更有优势。但是目前能够使用的工具很少,多数也是很不方便。这类工具最典型的有:onedoor, Google Browser Sync 桌面版的工具也有一些很经典的:AI Roboform, keepass, alpass

以上这三类工具,目前还在寻找中。

2008年5月19日星期一

Google又一次先走一步

刚刚发现Google在beta版的toolbar中更新了他的bookmarks和notebook服务方式。

我曾经在del.icio.us和clipmarks两个服务中间犯难,不知道应该使用哪一个。后来我慢慢发现:收藏互联网上的文章和收藏网站地址本来就是两个完全不同而又互相联系的需求。

现在Google也意识到这一点了:将bookmarks和notebook服务进行了整合。

现在唯一的问题:Google Notebook还是经常的无法访问。真的不知道是什么原因搞得?

2008年4月30日星期三

Google Calendar与Outlook同步

google刚刚出了新的服务:能将本地的outlook中的数据与google calendar同步,真够NB的。

新的facebook帐号

今天刚刚申请了一个facebook.com帐号,并且将blogger和facebook链接到了一起。