夸克学校专业代码准吗?

一、欢迎进入软件构建的世界

你一定知道“构建”一词在软件开发领域之外的含义。“构建”就是“建筑工人(construction workers)”在建设一栋房屋、一所学校、及至一座摩天大楼时所做的工作,在你年轻时,可能也曾用“硬纸板(construction paper)”构建过什么东西。按照一般的用法,“构建”是指建设的过程。构建过程可能包含有计划、设计、检查工作的一些方面,但在多数时候,“构建”就是指创建事物过程中动手的那些部分。

非构建活动主要包括管理(management)、需求分析、软件架构设计、用户界面设计、系统测试、以及维护。

2 、软件构建为何如此重要
    把主要精力集中于构建活动,可以大大提高程序员的生产效率
    构建活动的产物——源代码——往往是对软件的唯一精确描述

 1、软件构建是软件开发的核心活动;构建活动是每个项目中唯一一项必不可少的工作。
 2、软件构建的主要活动包括;详细设计、编码、调试、集成、开发者测试(developer testing)(包括单元测试和集成测试)。
 3、构建也常被称作“编码”和“编程”。
 4、构建活动的质量对软件的质量有着实质性的影响。
 5、最后,你对“如何进行构建”的理解程序,决定了你这名程序员的优秀程序——这就是本书其余部分的主题了。

二、用隐喻来更充分地理解软件开发

计算机科学领域中有着所有学科中最为丰富多彩的语言。你走进一间安全严密、温度精确控制在20度的房间,并在里面发现了病毒、特洛伊木马、蠕虫、臭虫、逻辑炸dan、崩溃、论坛口水战、双绞线转换头,还有致命错误......,这此形象的隐喻(比喻)描述了软件领域中各种特定的现象和事物。像这样生动活泼的隐喻还能够描述更加广泛的现象。借助这些隐喻,我们能更深刻地理解软件开发的过程。

        与其说一个软件隐喻像是一张路线图,还不如说它是一盏探照灯。它不会告诉你到哪里去寻找答案 ,而仅是告诉你该如何寻找答案。隐喻的作用更像是启示(启发、试探法),而不是算法。

        算法是一套定义明确的指令,使你能完成某个特定的任务。算法是可预测的、确定性的、不易变化的。一个告诉你如何从A点到达B点的算法,不会让你绕路,不会让你额外地经过D、E、F等地方,更不会让你停下来闻闻玫瑰花或喝杯咖啡。

而启发式方法是一种帮你寻求答案的技术,但它给出的答案是具有偶然性的,因为启发式方法仅仅告诉你该如何去找,而没有告诉你要找什么,它并不告诉你该如何直接从A点到达B点,它甚至可能连A点和B点在哪里都不知道。实际上,启发式方法是穿着小丑儿外套的算法;它的结果不太好预测,也更有趣,但不会给你什么30天无效退款的保证。

        4、通过把软件的构建过程比作是房屋的建设过程,我们可以发现,仔细的准备是必要的,而大型项目和小型项目之间也是有差异的。

        5、通过把软件开发中的实践比作是智慧工具箱的工具,我们又发现,每位程序员都有许多工具,但并不存在一个能适用于所有工作的工具,因地制宜地选择正确工具是成为能有效编程的程序员的关键。

三、三思而后行:前期准备

在开始建造房子之前,施工人员会审视蓝图(包含所有细节信息的设计详图),查看是否获得了全部(建筑)许可证,并测量房屋的地基。施工人员建造摩天大楼是一种方法,建造普通住宅用另一种方法,建造犬舍用第三种方法。无论何种项目,都会对“准备工作”进行剪裁,使之符合项目的特定需要;在构建活动开始之有,准备工作要做周全。

    本章描述软件构建必须做的准备工作。就像修建建筑物一样,项目的成败很大程度上在构建活动开始之前就已经注定了。如果地基没打好,或者计划不充分,那么你在构建期间能做的无非是尽量让损害最小罢了。

        使用高质量的实践方法是那些能创造高质量软件的程序员的共性。这些高质量的实践方法在项目的初期、中期、末期都强调质量。

    关于开始构建之前要做前期准备的绝对有力且简明的论据

        设想你已经到过“问题定义”之山,与名为“需求”之人同行数里,在“架构”之泉面前脱下脏兮兮的外套,然后在“前期准备”之纯净水中沐浴。那么你就会知道,在实现一个系统之前,你需要理解“这个系统应该做什么”,以及“它该如何做这些”。

2、辨明你所从事的软件的类型

        不同种类的软件项目,需要在“准备工作”和“构建活动”之间做出不同的平衡。三种常见的软件项目种类:商业系统(Intenet站点)、使命攸关的系统(软件工具)、性命攸关的嵌入式系统(航空软件)

开发商业系统的项目往往受益于高度迭代的开发法,这种方法的“计划、需求、架构”活动与“构建、系统测试、质量保证”活动交织在一起。性命攸关的系统往往需求采用更序列式的方法——“需求稳定”是确保“超高等级的可靠性”的必备条件之一。

    迭代的开发法:随着着项目的进展不断找出错误,在项目进行过程中一点点地吸收消化返工,这样使得总体成本较低。

   序列式的方法:仅仅依赖于测试来发现缺陷,将绝大部分缺陷修正工作推迟到项目结束的时候进行,使得成本较高。

3、问题定义的先决条件

        在开始构建之前,首先要满足的一项先决条件是,对这个系统是解决的问题做出清楚的陈述。这有时称为“产品设想”、“设想陈述”、“任务陈述”或者“产品定义”。这里将它称为“问题定义”。

“问题定义”只定义了“问题是什么”,而不涉及任何可能的解决方案。这是一个很简单的陈述,可能只有一到时两项,并且听起来应该你一个问题。像“我们跟不上Gigatron的订单了”这样的句子听起来你是个问题,而且确实是一个很好的问题定义。而“我们需要优化数据自动采集系统,使之跟上Gigatron的订单”这种句子是糟糕的问题定义。它听起来不像是问题,倒像是解决方案。

        “未能定义问题”的处罚是,你浪费了大量时间去解决错误的问题。这是双重处罚,因为你也没有解决正确的问题。

 4、需求的先决条件

        “需求”详细描述软件系统应该做什么,这是达成解决方案的第一步。“需求”活动也称为“需求开发”、“需求分析”,“分析”、“需求定义”、“软件需求”、“规格书”、“功能规格书”、“规格”

    为什么要有正确的需求:明确的需求有助于确保用户(而不是程序员)驾驭系统的功能。如果没有好的需求,你可能对问题有总体的把握,但却没有击中问题的特定方面。

        这张需求核对表包含了一系列的问题——问问自己项目的需求工作做得如何。在开始构建之前,用这份列表做一次“心智健全”检查,看看你的地基到底有多坚固——用“需求里氏震级”来衡量。

四、关键的“构建”决策
    第3章“三思而后行,前期准备”讨论了设计蓝图和建筑许可证在软件业里的等价物。你可能对那此准备工作没有多少发言权,所以第3章关注的焦点是确定“当构建开始后你需要做什么”。
    本章关注的焦点是程序员和技术带头人个人必须(直接或间接)负责的准备工作。在向工地进发之前,如何选择适用的工具别在你的腰带上,你的手推车里该装哪些东西?本章讨论的就是这些事务在软件中的等价物。
        在高质量软件中,你可以看到“架构的概念完整性”与“其底层实现”之间的关系。“实现”必须与(指导该实现的)“架构”保持一致,并且这种一致性是内在的、固有的。这正是变量名称、类的名称、子程序名称、格式约定、注释约定等这些针对“构建活动”的指导方针的关键所在。
3、你在技术浪潮中的位置
        “深入一种语言去编程”的程序员首先决定他要表达的思想是什么,然后决定如何使用特定语言提供的工具来表达这些思想。
4、选择主要的构建实践方法
         “构建”有一部分准备工作,就是决定在这么多的可选的实践方法中,你想要强调哪些。下面的核对表总结了在“构建”过程中,应该有意识地使用或者排斥的特定编程实践。
核对表:主要的构建实践
        你有没有规定的由软件架构确定的编码实践,比如如何处理错误条件、如何处理安全性事项、对于类接口有哪些约定、可重用的代码遵循哪些标准、在编码时考虑多少性能因素等?
        你有没有找到自己在技术浪潮中的位置,并相应调整自己的措施?如果必要,你是否知道如何“深入一种语言去编程”,而不受限于语言(仅仅“在一种语言上编程”)?

        3、“构建的实践方法”的种类比任何单个项目能用到的要多。有意识地选择最适合你的项目的实践方法。
        4、问问你自己,你采用的编程实践是对你所用的编程语言的正确响应,还是受它的控制?请记得“深入一种语言去编程”,不要仅“在一种语言上编程”。
        5、你在技术浪潮的位置决定了哪种方法是有效的——甚至是可能用到的。确定你在技术浪潮中的位置,并相应调整计划和预期目标。

         高质量的设计具有很多常见特征。如果你能实现所有这些目标,你的设计就真的非常好了。这些目标之间会相互抵触,但这也正是设计中的挑战所在———在一系列相互竟争的目标之中做出一套最好的折中方案。有些高质量设计的特征也同样是高质量程序的特征,如可靠性和性能等。而有些则是设计范畴内的特征。

最小的复杂度:正如刚刚说过的,设计的首要目标就是要让复杂度最小。要避免做出“聪明的”设计,因为“聪明的”设计常常都是难以理解的。应该做出简单且易于理解的设计。如果你的设计方案不能让你在专注于程序的一部分时安心地忽视其他部分的话,这一设计就没有什么作用了。

          易于维护:易于维护意味着在设计时为做维护工作的程序员着想。请时刻想着这些维护程序员可能会就你写的代码而提出的问题。把这些程序员当成你的听众,进而设计出能自明的系统来。

          松散耦合:松散耦合意味着在设计时让程序和各个组成部分之间关联最小。通过应用类接口中的合理抽象、封装性及信息隐藏等原则,设计出相互关联尽可能最少的类。减少关联也就减少了集成、测试与维护时的工作量。

          可扩展性:可扩展性是说你能增强系统的功能而无须破坏其底层结构。你可以改动系统的某一部分而不会影响到其他部分。越是可能发生的改动,越不会给系统造成什么破坏。

低扇出:低扇出就是说一个类里少量或适中地使用其他的类。高扇出(超过约7个)说明一类使用了大量其他的类,因此可以变得过于复杂。研究发现,无论考虑某个子程序调用其他子程序的量,还是考虑某个类使用其他类的量,低扇出的原则都是有益的。

精简性:精简性意味着设计出的系统没有多余的部分,伏尔泰曾说,一本书的完成,不在它不能再加入任何内容的时候,而在不能再删去任何内容的时候。在软件领域中,这一观点就更正确,因为任何多余的代码也需要开发、复审和测试,并且当修改了其他代码之后还要重新考虑它们。软件的后续版本也要和这些多余代码保持向后兼容。要问这个关键的问题:“这虽然简单,但把它加进来之后会损害什么呢”?

层次性:层次性意味着尽量保持系统各个分解层次的层次性,使你能在任意的层面上观察系统,并得到某种具有一致性的看法。设计出来的系统应该能在任意层次上观察而不需要进入其他层次。举例来说,假设你正在编写一个新系统,其中用到很多设计不佳的旧代码,这时你就应该为新系统编写一个负责同旧代码交互的层。在设计这一层时,要让它能隐藏旧代码的低劣质量,同时为新的层次提供一组一致的服务。这样,你的系统其他部分就只需与这一层进行交互,而无须直接同旧代码打交道了。在这个例子中,层次化设计的益处有:(1)它把低劣代码的烂泥潭禁闭起来;(2)如果你最终能抛弃或者重构旧代码,那时就不必修改除交互层之外的任何新代码。

          标准性:一个系统所依赖的外来的、古怪的东西越多,别人在第一次想要理解它的时候就越是头疼。要尽量用标准化的、常用的方法,让整个系统给人一种熟悉的感觉。

下面是对主要的设计中的启发式方法的总结:

下列的启发式方法有时也很有用

 六、为什么有这么多关于继承的规则

         3、如果多个类既共享数据也共享行为,应该让它们从一个共同的基类继承而来,并在基类里定义共用的数据和子程序。

功能上的内聚性:是最强也是最好的一种内聚性,也就是说让一个子程序仅执行一项操作。例如:GetCustomerName(),这样的子程序都是高度内聚性的。当然,以这种方式来评估内聚性,前提是子程序所执行的操作与其名字相符---如果它还做了其他操作,那么它就不够内聚,同时其命名也有问题。

通信上的内聚性:是指一个子程序中的不同操作使用了同样的数据,但不在在其他任何联系。例如某个子程序先根据传给它的汇总数据打印一份汇总报表,然后再把这些汇总数据重新初始化,那么这个子程序就具有通信上的内聚性;因为这两项操作只是因为使用了相同的数据才彼此产生联系。

过程上的内聚性:是指一个子程序中的操作是按特定的顺序进行的。一个例子是依次获取员工的姓名、住址、和电话号码的子程序。这些操作执行的顺序之所以重要,只是因为它和用户按屏幕提示而输入数据在顺序相一致。另一个子程序用来获取员工的其他数据。这段程序也具有过程上的内聚性,因为它把一组操作赋以特定的顺序,而这些操作并不需要为了除此之外的任何原因而彼此关联。

逻辑上的内聚性:是指若干操作被放入同一个子程序中,通过传入的控制标志选择执行其中一项操作。之所以称之为逻辑上的内聚性,是因为子程序的控制流或所谓“逻辑”是将这些操作放到一起的唯一原因-----它们都被包在一个很大的 if 语句或case语句中,而不是因为各项操作之间有任务逻辑关联。认为是逻辑上的内聚性的标志属性就是各项操作之间的关联,因此,似乎更应称其为“缺乏逻辑的内聚性”。

           1、创建子程序最主要的目的是提高程序的可管理性,当然也有其他一些好的理由,其中,节省代码空间只是一个次要原因;提高可文读性、可靠性和可修改性等原因都更重要一些。

           4、子程序的名字是它的质量的指示器。如果名字糟糕但恰如其分,那就说明这个子程序设计得很差劲。如果名字糟糕而且又不准确,那么它就反映不出程序是干什么的。不管怎样,糟糕的名字都意味着程序需要修改。

          5、异常提供了一种与代码正常流程角度不同的错误处理手段。如果留心使用异常,它可以成为程序员们知识工具箱中的一项有益补充,同时也应该在异常和其他错误处理手段之间进行权衡比较。

本章将从微观上关注编程过程-------也就是关注创建单独的类及其子程序的特定步骤,这些步骤对任何规模的项目来说都十分关键。

         2、编写好的伪代码需要使用易懂的英语,要避免使用特定编程语言中才有的特性,同时要在意图的层面上写伪代码(即描述该做什么,而不是要怎么去做)。

         3、伪代码编程过程是一个行之有效的做详细设计的工具,它同时让编码工作更容易。伪代码会直接转化为注释,从而确保了注释的准确度和实用性。

         5、每一步完成后都要检查你的工作成果,还要鼓励其他人帮你检查。这样你就会在投入精力最少的时候,用最低的成本发现错误。

十、使用变量的一般事项

对程序维护和更改有很深远影响的一个话题就是“绑定时间”,对变量与数据绑定的时间进行一下总结。( 编码时、编译时、加载时、对象实例化时、即时),一般而言,绑定时间越早灵性性就会越差,但复杂度也会越低。

        循环下标的名字有意义吗(如果循环的长度超出了一两行代码或者出现了嵌套循环,那么就应该是i/j或k以外的其他名字)?

常见命名问题:你避免使用......

       1、 好的变量名是提高程序的可读性的一项关键要素。对特殊种类的变量,比如循环下标和状态变量,需要加以特殊的考虑。

       3、命名规则应该能够区分局部数据、类数据和全局数据。它们还应当可以区分类型名、具名常量、枚举类型名字和变量名。

       4、无论做哪种类型项目,你都应该采用某种变量命名规则。你所采用的规则的种类取决于你的程序的规模,以及项目成员的人数。

       5、现代编程语言很少需要用到缩写。如果你真的要使用缩写,请使用项目缩写词典或者标准前缀来帮助理解缩写。

        1、使用特定的数据类型就意味着要记住适用于各个类型的很多独立的原则。用本章的核对表来确认你已经对常见问题做了考虑。

十三、不常见的数据类型

 核对表:使用不常见数据类型的注意事项

        5、如果你不得不使用全局变量,那么就通过访问器子程序来使用它。访问器子程序能为你带来全局变量所能带来的一切优点,还有一些额外好处。

核对表:组织直线型代码

        2、保持循环简单的技巧包括:避免使用怪异的循环、减少嵌套层次、让入口和出口一目了然、把内务操作代码放在一处。

十七、不常见的控制结构

核对表:不常见的控制结构

        你考虑过把表数据存储在外部并在运行期间读入,以便在不修改代码的情况下就可以改变这些数据吗?

        如果无法用一种简单的数组索引(像agc示例中那样)去访问表,那么你把计算访问键值的功能提取成单独的子程序,而不是在代码中重复地计算键值吗?

        1、表提供了一种复杂的逻辑和继承结构的替换方案。如果你发现自己对某个应用程序的逻辑或者继承树关系感到困惑,那么问问自己是否可以通过一个查询表加以简化。

核对表:控制结构相关事宜

        用重新判断部分条件、转换成if-then-else或者case语句、把嵌套代码提取成单独的子程序、换用一种更面向对象的设计或者其他的改进方法来简化嵌套语句了吗?

        3、结构化编程是一种简单并且仍然适用的思想:你可以通过把顺序、选择和循环三者组合起来而开发出任何程序。

二十、 软件质量概述

        1、开发高质量代码最终并没有要求你付出更多,只是你需要对资源进行重新分配,以低廉的成本来防止缺陷出现,从而避免低价高昂的修正工作。

        2、并非所有的质量保证目标都可以全部实现。明确哪些目标是你希望达到的,并就这些目标和团队成员进行沟通。

        3、没见有任何一种错误检测方法能够解决全部问题,测试本身并不是排除错误的最有效方法。成功的质量保证计划应该使用多种不同的技术来检查各种不同类型的错误。

        4、在构建期间应当使用一些有效的质量保证技术,但在这之前,一些具有同样强大功能的质量保证技术也是必不可少的。错误发现越早,它与其余代码的纠缠就越少,由此造成的损失也越小。

        5、软件领域的质量保证是面向过程的。软件开发与制造业不一样,在这里并不存在会影响最终产品的重复的阶段,因此,最终产品的质量受到开发软件所用的过程的控制。

结对编程:在进行结对编程的时候,一位程序员敲代码,另外一位注意有没有出现错误,并考虑某些策略性的问题,例如代码的编写是否正确,正在编写的代码是否所需等。结对编程最初是由极限编程所普及推广的,现在已经使用得相当广泛了。

核对表:有效的结对编程

正式检查:详查(正式检查)是一种特殊的复查,种种迹象表明它在侦测缺陷方面特别有效,并且相对测试来说更加经济合理。

        是否所有详查会议的参与者都接受了如何进行详查的针对性培训,是否主持人接受了有关主持技巧方面的针对性培训?

其他类型的协同开发实践:走查、代码阅读、公开演示

        每行代码是否被至少一个测试用例所测试?你是否通过计算测试到每行代码所需的最少测试用例数量来验证这一点?

        是否检查了与旧数据的兼容性?以及是否对旧硬件、旧操作系统版本以及其他旧版本软件的接口进行了测试?

        1、开发人员测试是完整测试策略的一个关键部分。独立测试也很重要,但这一主题超出了本书的范围。

        2、同编码之后编写测试用例相比较,编码开始之前编写测试用例,工作量和花费的时间差不多,但是后者可以缩短缺陷--侦测--调试--修改这一周期。

        3、即使考虑到了各种可用的测试手段,测试仍然只是良好软件质量计划的一部分。高质量的开发方法至少和测试一样重要,这包括尽可能减少需求和设计阶段的缺陷。在检测错误方面,协同开发的成效至少与测试相当。这此方法所检测错误的类型也各不相同。

        4、你可以根据各种不同的思路来产生很多测试用例,这些思路包括基础测试、数据流分析、边界分析、错误数据类型以及正确数据类型等。你还可以通过猜测错误的方式得到更多的测试用例。

        6、测试数据本身出错的密度往往比被测试代码还要高。查找这种错误完全是浪费时间,又不能对代码有所改善,因此测试数据里面的错误更加让人烦恼。要像写代码一样小心地开发测试用例,这样才能避免产生这种问题。

        8、从长远来看,改善测试过程的最好办法就是将其规范化,并对其进行评估,然后用评估中获得的验证教训来改善这个过程。

核对表:关于调试的建议

        你是否会避免采用随机尝试查找错误或迷信式的调试方法(不听话的机器,奇怪的编译器错误,月圆时才会出现的编程语言的隐藏缺陷,失效的数据,忘记做的重要改动,一个不能正常保存程序的疯狂的编辑器,这种行为描述为迷信式的编程)

        1、调试同整个软件开发的成败息息相关。最好的解决之道是使用本书中介绍的其他方法来避免缺陷的产生。然而,花点时间来提高自己的调试技能还是很划算的,因为优秀和拙劣的调试表现之间的差距至少是10:1。

        2、要想成功,系统化的查找和改正错误的方法至关重要。要专注于你的调试工作,让每一次测试都能让你朝着正确的方向前进一步。要使用科学的调试方法。

        3、在动手解决之前,要理解问题的根本。胡乱猜测错误的来源和随机修改将会让你的程序陷入比刚开始调试时更为糟糕的境地。

        4、将编译器警告级别设置为最严格,把警告信息所报告的错误都改正。如果你忽略了明显的错误,那么要改正那些微妙的错误就会非常麻烦。

        5、调试工具对软件开发而言是强有力的支持手段。找出这些工具并加以应用,当然,请记得在调试的时候开动脑筋。

        2、在修改中软件的质量要么改进,要么恶化。软件演化的首要法则就是代码演化应当提升程序的内在质量。

        6、开发阶段的重构是提升程序质量的最佳时机,因为你可以立刻让刚刚产生的改变梦想变为现实。请珍惜这些开发阶段的天赐良机。

二十五、代码调整策略 

        1、性能只是软件整体质量的一个方面,通常不是最重要的。精细的代码调整也只是实现整体性能的一种方法,通常也不是决定性的。相对于代码本身的效率而言,程序的架构、细节设计以及数据结构和算法选择对程序的运行速度和资源占用的影响通常会更大。

         2、定量测量是实现性能最优化的关键。定量测量需要找出能真正决定程序性能的部分,在修改之后,应当通过重复测量来明确修改是提高还是降低了软件的性能。

        3、绝大数的程序都有那么一小部分代码耗费了绝大部分的运行时间。如果没有测量,你不会知道是哪一部分代码。

        5、为性能优化工作做好准备的最佳方式就是在最初阶段编写清晰的代码,从而使代码在后续工作中易于理解和修改。

        合并:就是把两个对相同一组元素进行操作的循环合并在一起。好处就是把两个循环的总开销减少至单个循环的开销。

        哨兵值:当循环的判断条件是一个复合判断的时候,你可以通过简化判断来节省代码运行时间。如果该循环是一个查找循环,简化方法之一就是使用一个哨兵值,你可以把它放到循环范围的未尾,从而保证循环一定能够中止。

        削减强度:削减强度意味着用多次轻量级运算(例如加法)来代替一次代价高昂的运算(例如乘法)。

        删除公共子表达式:如果发现某个表达式老是在你面前出现,就把它赋给一个变量,然后在需要的地方引用该变量,而非重新计算这个表达式。

6、用低级语言重写代码

同时改善代码执行速度和规模

        1、优化结果在不同的语言、编译器和环境下有很大差异。如果没有对每一次的优化进行测量,你将无法判断优化到底是帮助还是损害了这个程序。

        3、代码调整这一话题有点类似于核能,富有争议,甚至会让人冲动。一些人认为代码调整损害了代码可读性和可维护性,他们绝对会交期弃之不用。其他人则认为只要有适应的安全保障,代码调整对程序是有益的。如果你决定用本章所述的调整方法,请务必谨慎行事。

 二十七、程度规模对构建的影响

        如果项目中只有你一个人,那么唯一的交流路径就是你和你顾客的交流,随着项目成员数目的增加,交流路径的数量也随之增加,但是二者的关系并不是加性的,而是乘性的,即交流路径的条数大致正比与人数的平方。

你所从事的项目的规模具有典型吗?项目规模的范围很宽,这也就意味着不能把任何一种规模视为典型。

3、项目规模对错误的影响

        项目的规模会影响错误的数量,也会影响错误的类型。你也许不曾想到错误类型也会受到影响,然而随着项目规模的增大,通常更大一部分错误要归咎于需求和设计。 

5、项目规模对开发活动的影响

        如果你从事的是一个单人项目,那么对项目成败影响最大的因素就是你自己。如果你在一个具有25个人的项目中工作,那么你仍然可能是最大的影响因素,但更多可能的是,没人能够独享成功的奖牌,组织结构对项目成败的影响力更大。

        程序、产品、系统和系统产品:代码行数和团队规模并不是影响项目大小的仅有因素。另一个更敏感的影响因素是最终软件的质量和复杂度。

        方法论和规模:各种方法论都被用于不同大小的项目。对于小项目,方法论的应用显得很不经意并且趋于本能。对于大项目,它们的应用变得十分严格,并且计划得非常仔细。

        1、随着项目规模的扩大,交流需要加以支持。大多数方法论的关键点都在于减少交流中的问题,而一项方法论的存亡关键也应取决于它能否促进交流。

        4、在小项目里的一些看起来“理当如此”的活动在大项目中必须仔细地计划。随着项目规模扩大,构建活动的主导地位逐渐降低。

1、鼓励良好的编码实践

什么是配置管理:配置管理是“系统化地定义项目工件和处理变化,以使项目一直保持其完整性”的实践活动。它的另一种说法是“变量控件”。其中的技术包括评估所提交的更改、追踪更改、保留系统在不同时间点的各历史版本。

        你是否将一些变更请求聚成一组?无论采用非正式的方法(如创建一份未决更改的列表)还是更加系统的方法(如设立变更控制委员会)。

度量软件项目有很多种方法。以下是对项目进行度量的两项根本原因

        信仰问题(编程语言、缩进风格、大括号的摆放位置、所用的集成开发环境、注释风格、效率与可读性的取舍、对方法的选择--例如,Scrum-极限编程-渐进云交付、编程工具、命名习惯、对goto的使用、对全局变量的使用、量度---特别是有关生产力的量度,如每天编写的代码行数)

在软件开发中,非技术出身的管理者随处可见,具有技术经验但却落后于这个时代10年(以上)的管理者也比比皆是。技术出色并且其技术与时俱进的管理者实属凤毛麟角。如果你正在为一位这样的管理者工作,那么就尽可能地保住你的工作吧。这可是非常难得的待遇。

        3、好的软件评估是一项重大挑战。成功的关键包括采用多种方法、随着项目的开展而修缮评估结果,以及很好地利用数据来创建评估等。

        4、度量是构建管理成功的关键。你可以采取措施度量项目的任何方面,而这要比根本不度量好得多。准确的度量是制定准确的进度表、质量控制和改进开发过程的关键。

在软件以外的工程领域,正确集成的重要性已广为人知。一起事故戏剧性地展示了糟糕的集成的危险,华盛顿大学的露天足球场在建设时中途坍塌。因为它在建造时不能支撑自己的重量。很可能在完工后它会足够牢固,但是它在建造顺序是错误的------这是一个“集成”错误。它必须在每一步都要足够牢固才行。如果你按错误的顺序构建并集成软件,那么会难于编码、难于测试、难于调试。

2、 集成频率---阶段式集成还是增量集成

        增量集成的益处:易于定位错误、及早在项目里取得系统级的成果、改善对进度的监控、改善客户关系、更加充分地测试系统中的各个单元、能在更短的开发进度计划内建造出整个系统。

3、增量集成的策略自顶向下集成、自底向上集成、三明治集成、风险导向的集成、功能导向的集成、T-型集成。

        集成方法的小结:请不要像教条一样遵循前面提到的任务过程,而应该为特定项目剪裁一套独一无二的策略。

build和冒烟测试都是软件集成的好方法。每天都将各个(源)文件编译、链接并组合为一个可执行程序,然后对这个程序进行冒烟测试,即执行一种相对简单的检查,看看产品在运行时是否“冒烟”。

        组件之间的接口是否有明确定义?(定义接口不是集成的任务,但要验证这些接口的定义是否正确。)

      4、针对每个特定的项目,最佳的集成步骤通常是自顶向下、自底向上、风险导向及其他集成方法的某种组合。T-集成和竖直分块集成通常都能工作得很好。

现代化的编程工具减少了构建所需的时间。使用最前沿的工具集---并熟悉你所用的工具---能使用生产力增加50%还不止。编程工具也能降低编程中必须的单调乏味的琐碎事务的劳动量。

        工具幻境当你听到某个工具厂商宣称“这一新工具将会消除计算机程序设计时”,躲开它!或者对这种厂商的幼稚的乐观主义一笑置之。

        如果你正面对超大型的项目,你是否使用了数据字典或者其他“包含系统中使用的各个类的权威描述”的中央知识库。

        你的测试环境包含有自动化的测试框架、自动测试生成器、覆盖率监视器、系统扰动器、diff工具,以及缺陷跟踪软件吗?

        5、好的工具能减少软件开发中最单调乏味的工作的量,但它不能消除对“编程”的需要,虽然它会持续地重塑(reshape)“编程的含义”。

本章转向计算机编程的美学问题---程序源代码的布局。编排出色的代码会带来视觉上和思维上的愉悦,这是非程序员的人不能感受到时的。而精雕细琢代码、使之达到美观的程序员们,却会从这一过程得到艺术上的满足。

 类、文件和程序的布局

        1、可视化布局的首要任务是指明代码的逻辑组织。评估该任务是否实现的指标包括准确性、一致性、易读性和易维护性。

        2、外表悦目比起其他指标是最不重要的。然而,如果其他指标都达到了,代码又质量好,那么布局效果看上去也会不错。

        4、结构化代码有其自身目的。始终如一地没用某个习惯而少来创新。不能持久的布局规范只会损害可读性。

        5、布局的很多方面涉及信仰问题,应试着将客观需要和主观偏好区分开来。定出明确的目标 ,在些基础了再讨论风格参数的选择。

序”:为一组常于文件头的注释,起到介绍程序的作用。它和书的序功能相同,提供有关程序的情况。

“目录”:给出顶层文件、类和子程序(即“章”),它们可以是清单形式,就如同书本列出章节那样,也可以结构图的形式表示。

6、IEEE(电子与电器工程师协会)标准

        子程序的其他有关情况(诸如输入输出数据、接口假设、局限性、纠错、全局效果和算法来源)都注释出来了吗?

        2、源代码应当含有程序大部分的关键信息。只要程序依然在用,源代码比其他资料都能保持更新,故而将重要信息融入代码是很有用处的。

        3、好代码本身就是最好的说明。如果代码太糟,需要大量注释,应先试着改进代码,真至无须过多注释为止。

         每个行业的工程人员都了解其工作用的工具及材料和各种限制。如果是电气工程师,就该知道各种金属的电导率,以及电压表的上百种用法;如果是建筑工程师,就该知道木材、混凝土和钢铁的承载量。

        假如你是软件工程师,基本的建造材料就是你的聪明才智,主要工具就是你自己。建筑工程师对建筑物结构进行详细的设计,然后将设计蓝图交给其他人施工;而你一旦从细节上对软件做好设计后,软件就生成出来了。编程的整个过程如同建造空中楼阁一样——这是人们能做的纯粹脑力劳动之一。

        因此,当软件工程师研究其工具和原材料的本质时,会发现其实是在研究人的智力、性格,这些可不像木材、混凝土和钢材是有形的东西。

        向专业开发看齐——第一级入门级、第二级中级、第三级熟练级、第四级技术带头人级(具有第三级的专业才学),并明白编程工作中只有15%用来和计算机交互、其余都是与人打交道的。

       我们的精神品德即非与生俱来,也非逆于天性......其发展归因于习惯......我们要学的任何东西都通过实际做的过程学到......如果人们建的房子好,他们就成为好的建设者;而造的房子不好时,他们就是差的建设者......所以小时候形成了怎样的习惯关系很大——正是它会造成天壤之别,或者说就是世上所有差异之源。

        5、很多程序员不愿主动吸收新知识和技术,只依靠工作时偶尔接触新的信息。如果你能抽出少量时间阅读和学习编程知识,要不了多久就能鹤立鸡群。

        6、好性格与培养正确的习惯关系甚大。要成为杰出的程序员,先要养成良好习惯,其他自然水到渠成。

三十四、软件工艺的话题

1、征服复杂性:致力于降低复杂度软件开发的核心。第5章“软件构建中的设计”说明了管理复杂度是软件的首要技术使命。

       例:A、在架构层将系统划分为多个子系统,便让思绪在某段时间内能专注于系统的一小部分

 3、首先为人写程序,其次才是为机器

4、深入一门语言去编程,不浮于表面

        不要将编程思路局限到所用语言能自动支持的范围。杰出的程序员会考虑他们要干什么,然后才是怎样用手头的工具去实现他们的目标。

        另一个处理复杂性的特殊方式就是尽可能工作于最高的抽象层次。其中一种方法就是针对编程所要解决的问题来工作,而非针对计算机科学的解决方案。

        3、合作一发要求团队成员之间进行广泛沟通,甚于同计算机的交互; 而单人开发则是自我交流,其次才是与计算机。

        4、编程规范一旦滥用,只会雪上加霜;使用得当则能为开发环境带来良好机制,有助于管理复杂性和相互沟通。

        8、墨守成规的方法有悖于高质量的软件开发。请将编程工具箱中填满各种编程工具,不断提高自己挑选合适工具的能力。

三十五、何处有更多信息

    读到这儿时,你应已对行这有效的软件开发实践有了不少的了解。实际上你还能获取比这些多得多的信息。你犯的错误别人早已犯过,要是不想自讨苦吃,就读读他们的书吧,这样能够避免再走弯路,并找出解决问题的新方法。

4、软件开发者的阅读计划

我要回帖

更多关于 4g手机综测校准代码 的文章

 

随机推荐