警世格言以及常识性问题无法教会一个人成为一位高效的Java开发人员。您还需要了解如何交付高质量软件。在高效软件开发人员中有着一些共同的习惯。下面介绍这些习惯。
2.2.1 交流过去一提到软件开发,脑海里就会出现这样的画面:一个书呆子般的软件工程师寂寞地坐在地下室某个黑暗的角落里,像神经病一样一刻不停地敲着键盘,但这已经是过时的描述了(当然在大多数情况下,“黑暗”还是恰当的)。上文中说过,开发软件是为了满足某个特定业务流程的需求。要想成功,您必须深入并真正懂得这种需求。通过阅读一个说明很难实现这一点。您必须与用户进行交流,如果不能与用户交流,就与曾经是用户或者与用户交流过的人进行交沈阳网站建设流。需要了解用户的行业、用户是如何成功的,以及您的软件将如何帮助他们更加成功。如果只是根据管理层的要求来开发软件,那么您的软件注定寿命不长。
同时,您还必须与同事进行交流,向他们说明您自己学到的经验、从他们的错误中学到的经验,以及如何协调软件的兼容性。即使是一次偶尔的午餐或简短的聊天,也要让它成为一个团队交流的时间。软件开发是一项艰苦并且压力重重的工作,熟悉自己的团队同伴将很有帮助。
2.2.2 模型在您跑去购买新款服饰之前,请先看一下本书的封面。上面的人物非常平实,不需要摆出什么造型!建模是在交流的基础上,通过一种更切实际的方法将给定的概念或想法呈现出来。
不要假设团队中的每个人都需要参加统一建模语言(unified modeling language,UML)培训或者去购买昂贵的UML建模软件。UML用一种常用的格式表达许多事情,大多数人群(从用户到开发人员)都能理解这种格式。当然,这并非症结所在。任何表示法的关键在于它必须能够被那些阅读它的人理解。如果您的团队了解或者将要了解UML,您将发现它是一种非常神奇的表示法——由一群非常聪明的人组成的委员会规划出来的表示法。
当然,有一则老笑话说“委员会设计出来的马是骆驼”。这就是说,您得注意UML包含的工具集远远超出了实际项目建模的需求。关键在于,找出一种每个人(包括用户)都可以理解的表示法并坚持使用它。同样,如果所使用的工具弊大于利,也不要使用它们。其实您可以在一个白板上画出模型,然后用数码相机将整个白板拍下来,就得到您要的了,不需要花钱购买任何工具。
2.2.3 敏捷变化是软件开发中一个不可避免的情况。这不仅仅是因为技术在不断地变化,客户的业务流程也在变化,还因为您实际上提供了某种自动化支持。
在教授面向对象的软件开发课程时,我经常向我的学生指出,尽管我现在已经成为一个高级软件工程专家,也开发了许多能够改进人们工作方式的软件解决方案,但是我仍然不能轻易地找到自己的需求集合,以便开发一个改进自己业务流程的系统。实际上,就同世界上大多数工作人员一样,我没有花费太多的时间思考我在做什么我将怎样做。如果需要这样做,我可能会根据我的经历构建我的理想系统。但如果一个软件团队向我介绍一个新的系统,那么这种情况将马上改变,因为我的整个参考框架现在将相对于软件团队向我呈现的系统。我曾经认为重要的事情现在都不再重要,我曾经认为应该改进的地方现在不再需要改进,等等。最后,我的需求发生变化是一件自然而然的事情!
您可能经常会听到软件工程师抱怨需求的不停变化。这令人很迷惑,因为选择软件工程师这个职业就是希望开发软件,而不断变化的需求正好促进了这一目标。不断变化的需求并非症结所在。软件团队不能适应变化才是根本原因;也就是说,他们不够敏捷。
Lou Holtz曾经说过:“生活是百分之十的命中注定和百分之九十的打拼。”这句话表明了一个软件工程师在高效的Java开发中应该持有的态度。
2.2.4 条理
在一头钻进编程的世界之前,一定要有条理。当出现大量可能分散注意的事情时,要保持集中注意力。这并不是要您头悬梁锥刺股。要做您该做的事情,而不是您能做的事情。
请回忆一下前面讨论的高质量软件开发的几条原则,确信自己没有违背任何一条。切记欲速则不达。要防微杜渐,提早捕获小bug,不要为了方便而丧失了判断能力。
但是,同样不要因为谨慎而放慢开发速度。通过放慢速度来避免错误不一定有效,但它确实会减少用来纠正错误的时间。
修补bug或开发一种新方法来处理无法预料的事情时尤其要注意条理。渴望尝试新鲜事物可能会使您忽略条理对于实现系统目标的重要性。
2.2.5 根据需要追溯行为保持条理性的同时,还要根据需要追溯自己的行为,这使得软件变得可以处理。懂得为什么团队中的一个人负责构建软件系统中的一个组件非常重要。
可追溯性是指在整个系统中跟踪所需内容的能力。假如您要提供一份打印报告,那么首先将看到的是一个使用情况或软件需求集合,这个集合被反映到某种设计元素,设计元素通过某段代码段实现,代码被编译成为某种可执行程序或库,最后可执行程序被部署到某台机器上,等等。
您可能会想,“嗯,这确实很简洁,但我为什么要这样做?”答案很简单。假如有人请您修改代码以支持另一种类型的打印机,那么通过追溯代码,就能知道应该在什么地方进行修改。
可追溯性并不意味着需要处理堆积如山的文件、庞大的数据库、电子表格或文档,也不需要为了向那些不懂代码的人解释而重写代码。可追溯性只要求必要时开发人员可以从代码中找到解决问题的办法。
2.2.6 不要害怕编写代码
这是不言而喻的,但是您可能会很惊讶地发现,编写代码常常只占到软件开发工作中很小的一部分,特别是在最需要编写代码的复杂系统中。通常,开发人员首先在纸上勾勒出系统轮廓,接着找到合适的设计模式,或者恰当地建模。
但是,只有在代码中才能恰如其分地表达出特定的逻辑结构。同时,编译器和运行时环境将帮您验证设计中的各种假设。
如果您所开发的系统都很相似,那么就能很容易地估计出代码执行时所需的时间。一个完整系统的微模型有助于准确地理解某项任务的复杂程度或时间消耗。
进一步说,在Java开发中,不要奢望自己能对系统了如指掌。Java开发中存在着大量的内容重用行为,您的系统将不可避免地依赖在自己的设计范围之外开发的代码。因此,假设一个给定的API会按照自己设想的方式运行是很愚蠢的。影响结果的因素实在太多了。
此外还可以修改代码。重构(修改现有代码的设计)是软件开发的一个重要部分。[FOWLER]
2.2.7 将代码当作设计而非产品重构是高效软件开发中一个重要的习惯。代码不能被当作交付的产品。毕竟,很少有人将源代码交付给用户,交付给客户的通常是一个经过编译的、可以根据源代码执行操作的字节码。
这是因为源代码是设计的一部分。在前面说过,有些逻辑结构只能在代码中表达。进一步说,源代码提供了一个人们可以理解的逻辑表达形式,这个逻辑将被编译成字节码(然后被转换成机器指令)。
您可能会说,“嗯,当然,源代码不是产品,谁说它是啦?”对于不知道这个前提的组织您不会遇到任何问题,但这样的组织是不存在的。注意到我们目前对设计阶段非常关注,但是却有相当数量的设计人员不会编写代码。这也证明了项目关注点的错位。
2.2.8 不断学习这并不是为了作者的书能够畅销而提的建议,这是因为软件总是在变化和改进,不停地出现新技术、新实现、新API、新标准等。软件开发过程是一个知识积累的过程,其工作的一部分就是学习,开发其他任意系统也是一样。要学习新技术、学习更好的方法,甚至要学习有关当前解决方案中所用工具和API的更多知识,因为这是成功的关键所在。
大部分学习资料都可以从互联网和开源软件中得到。Java已经不仅仅是一种编程语言,它更像是一个软件开发社区。
如果在软件开发中遇到问题,那么首先应该在线查找,看看是否已经有人解决了您的问题。此外,还可以查看那些遇到相同问题的人是如何解决这些问题的。
2.2.9 自下而上构建流程
流程就是团队处理业务的途径。无论建立流程的情况如何,您的团队都需要熟知处理业务的方式。构建一个有效流程的关键在于自下而上。管理层将设置他们的期望产出和绩效管理方式。如果他们很重视文档和文书工作,那么您的流程就必须确保能满足这些要求。
最关键的部分是,您的团队必须在一起工作,这将决定您如何满足管理层的期望值。如果您不同意作为一个团队来使用流程,那么这个流程将变成摆设。您也不能让流程成为区分合作者的工具。一旦发生这种情况,您就会觉得技术比好的软件开发原则更为重要,从而失去了根据软件需求追溯行为的能力沈阳网站设计。
自下而上构建流程要考虑的一个重点内容是,流程实际从哪里开始到哪里结束。开发团队成员之间的斗争从集成开发环境(integrated development environment,IDE)标准化(如Eclipse)这个问题上就开始了。您应该问问自己是否真的需要标准化IDE。即使确实需要一些能使用有效的配置管理(下文将讨论该内容)支持团队成员之间通过有效配置管理进行互操作的工具,也没有必要使一些成员在开发工具方面陷入困境。软件开发本身已经是一件非常困难的工作了,不要再在开发工具方面增加困难。
这就是构建流程的关键因素。决定团队成员都能接受的内容,使每个人都能高效地工作。如果您不能统一团队思想,那么就需要管理层的干涉,这种情况应当尽量避免。
2.2.10 配置管理配置管理(configuration management)非常重要,因为总会有小小的意外发生。一个硬盘坏了,您的最新进展将会变得一团糟,诸如此类。软件开发的正常过程中此类事例随处可见。
要注意配置管理和源代码控制是完全不同的两个概念。配置管理是一个控制如何将系统集成在一起的过程。配置管理的关键目标是可以在其他地方复制配置。不仅需要维护源代码的配置控制,还需要维护运行时环境(包括相关库、应用服务器配置、Java运行时环境和数据库规划等)的配置控制,也就是说,维护所有重建系统所需的配置控制。
源代码控制使用并发版本控制系统(Concurrent Versioning System,CVS)之类的工具,允许多个开发人员在共享文件中工作,并且在保存修订历史树时可以集成他们的修改。CVS是开源环境中的主流工具,它已经完整集成到大多数主流IDE中。当然,如果不需要提交修改,源代码控制也就没有用处了。
2.2.11 单元测试代码在设计和编写代码的时候,同时也是在编写测试用例。编写测试用例是为了处理预计的情形,即使用系统时系统是如何运行的。这样做时会假设系统对于一个给定的环境集是如何响应的。例如,如果要查看一个不是null的对象,那么我将假设该对象在某一时刻前不是null。
在编写代码时,要开发自己的复杂逻辑来支持预计的情形,检查代码正常运行所需的前提。然而,您的代码总是要在某一个场景集中运行。单元测试使您能测试这些场景。
本章将讨论如何使用开源工具TestNG(与JUnit类似的回归测试框架)来执行单元测试,单元测试已经成为持续集成(continuous integration)的一个重要部分。
2.2.12 持续集成
有了一个强壮的单元测试集来确保系统中单个组件功能的正确性后,现在可以将这些组件组合在一起形成产品,然后对所有组件运行所有的单元测试,看看系统作为一个整体的功能如何,如图2-1所示。
注意,即使对于单元测试不是很熟悉,也可以应用持续集成,它可以为开发团队提供很大的帮助。随着整个开发团队成果的组合,将会看到这些组件是如何在一起相互作用的,并且可以确保假设对于各自的代码都是有效的。
图2-1
系统的集成程度越高,对成功推出一个整体产品就越有信心。这种方式可以及早发现问题并进行修补,因此有助于降低开发风险。持续集成与短期开发迭代维护过程紧密相连。
2.2.13 维护短期迭代正如上文所说,发现问题越及时,这些问题对整个开发造成的影响就越小。达到这个目标的诀窍是维护短期开发迭代(development iteration),这意味着您必须在一段较短时间期限内完成整个开发周期循环(需求、代码、设计和测试)。
如果有可能,在每个迭代期应该努力让客户参与进来,因为前面已经提过,软件可能会修改它们的上下文。这样客户就可以面对开发人员构建的上下文环境而不是某个抽象概念来描述他们的需求。
迭代周期的长短取决于团队,但是,由于本节提到的这些原因,应该以周而不是月来计量迭代周期。您应该在最短的时间内使一个迭代中包含足够多有意义的内容。第一次迭代最好是两周到一个月。之后,您就可以根据第一次的经验来决定下一次迭代。
2.2.14 度量成果——间接度量在软件估计(software estimate)中有一个老笑话,“童话故事和软件评估有何区别?软件估计的故事不是以‘在很久很久以前’开始的。”这个笑话说明软件估计的确很难,大多数软件估计技术经常被认为是巫术。
成功的软件估计都是基于经验的。经验就是对曾经完成的软件内容和开发时间进行量化,并以此为基础预测下一次软件开发要消耗的时间。由于一般的工作空间对估计过高没有像估计过低那样有所惩罚(提前就是好,延后就是不好),所以估计总是过于保守。这些估计开始建立于另一次估计之上,并且不能估计得太低,否则下一次评估将变得不太可信,然后将无事可干。于是便开始画蛇添足(也就是说,添加一些不必要的无法追溯的特性),最后导致系统丧失了灵活性。
也可能发生相反的情况。由于对软件开发人员进行的估计不信任(因为他们喜欢画蛇添足和无所事事),于是管理层进行干预,根据他们的想象来估计软件的开发时间。通常,他们仅仅从市场目标出发来设置过度激进的进度表,并号称这是对开发人员的一次技术挑战。开发人员一般比较乐观并且喜欢挑战,于是欣然接受这种荒谬的进度表,直至终于无法忍受而跳槽。
因此,如何避免这种混乱不堪的情形呢?可以使用一个间接度量来度量您完成的内容,使您无法隐瞒实际情况。极限编程(Extreme Programming,XP)中有一个概念称为速度(velocity)。XP将会在后面讨论,现将速度的概念解释如下:
1.有一个任务集合,对于集合中的每一个任务,分配特定的点数,这些点数与完成它们所需的努力相关。
2.接着估计团队中的每一位开发人员在给定的迭代中可以完成多少点,并对剩下的点数进行统计等。迭代是一个指定时间量的时间限制(例如,一般是两周时间)。
3.执行工作,追踪实际能完成的点数。
4.对新任务启用相同的流程,根据实际结果调整具体内容。随着估计能力的提高,或者系统变得越来越容易理解,您的速度将越来越快。
当然,没有任何事情比度量更令开发人员恐惧了。马克吐温曾经说过,“有三种类型的谎言:谎言、可恶的谎言和统计数据。”开发人员都知道度量标准可能过于简化或者失去了它们的实际意义。这就是为什么团队工作以及沟通是如此重要的原因。应该允许这些度量标准对于实际使用它们的人都是可见的。您可以将它作为您的团队通行证;也就是说,如果您没有速度概念,那么您也就无需了解速度。
当然,在有关开发性能度量这个敏感而必需的问题上,也应该学会追踪自己的问题。
2.2.15 追踪问题
开发团队面临的另一个不稳定问题是bug报告和追踪。正如前面提到的,很难理解客户希望得到什么,客户自己也很难理解他们希望得到什么。进一步说,用户将用您无法预知的方式使用开发的软件,他们将会发现软件系统中未文档化的特性。
然而,如果放下羞愧之心,坦然关注那些必然出现的bug和变化,那么您的问题追踪系统将成为一个解决问题的良好途径。
无论是使用一个高级在线系统还是一个简单的电子表格,最重要的是要自始至终追踪具体细节。您将发现允许用户直接输入对产品的反馈是一个非常好的方式。如何处理反馈由您决定,但是始终聆听用户的声音将非常有用。当然,如果您让用户经常向系统输入反馈,您必须公开表明您确实在另一端聆听着他们的声音。