【代码大全2】第34章 关于软件匠艺

目录

1. 征服复杂性

2. 优选开发过程

3. 编写程序时,先考虑人,再考虑机器

4. 深入语言去编程,而不是用语言来编程

5. 借助于规范来保持专注

6. 面向问题域编程

7. 当心落石

8. 迭代、迭代、迭代,重要的事情说三遍

9. 警惕编程中的执念

总结:



1. 征服复杂性

没有一个人的大脑真正能够跨越9个数量级的细节,所以我们需要这样做          

  • 在架构层面把一个系统分解成若干个子系统,以便一次只聚焦于系统的一小部分。
  • 精心定义类的接口,以便能够忽略类的内部工作机制。
  • 类的接口保持抽象,以便无需记住所有细节。
  • 避免使用全局变量,因为全局变量会显著增加你需要兼顾的代码。
  • 避免深层次的继承,因为这需要耗费大量的经历。
  • 避免循环和条件的深度嵌套,因为其实它们能被更简单的控制结构所代替,让我们少费些脑细胞。
  • 避免使用goto语句,因为它们引入来非顺序执行,大多数人都看不懂。
  • 小心定义错误处理方法,不要滥用不同的错误处理技术。
  • 系统地使用内置的异常机制,因为一旦使用不当,会同goto语句一样引入非顺序执行,让人看不懂。
  • 不要让类过度膨胀,以至于占据整个程序。
  • 保持程序短小。
  • 变量名要清楚直观,不要浪费脑力去记住大量的细节,比如“i表示账户的下标,j表示客户的下标或者它们的表示刚好相反?”
  • 尽可能减少参数的数量,或者更重要的是,只传递足以保持程序抽象的参数。
  • 使用规范来避免大脑去记忆代码不同部分之间随意、偶然的差异。 

2. 优选开发过程

软件开发过程的选用非常重要

        一个小项目,更多取决于程序员的个人能力

        一个大项目,更多取决于开发流程,它决定多人开发是1+1>2还是1+1<2 

(1)关于开发过程的重要性,一个例子是看设计和编码前,需求还不稳定所造成的后果。 

          a. 如果不知道正在构建什么,就不能为其做出卓越的设计。

          b. 如果在开发过程中需求和设计发生来变更,必然涉及代码的修改,这样会产生系质量降低的风险。 

(2)有意关注过程这一原则,同样适用于设计。

           a. 盖房子前,必须打牢地基。如果基础不牢,就匆忙上手写代码,会导致对系统架构的基础改变变得异常困难。一旦开始建房子,就很难废掉不稳的地基重新再来

           b. 软件开发过程很重要的主要原因是内建质量必须从头做起。

           c. 这与我们通常的做法相反,以往,我们是先完成代码,然后在通过测试去除软件的错误。这种做法完全是错误的,测试只会指出软件有缺陷,并不会使程序更有用、更快、更小、更有可读性或更具扩展性。

           d. 过早优化是另外一种错误,在有效的开发过程中,可以一开始只做粗略的调整,后期再做精细的调整,就好比雕塑家在精雕细琢之前,会雕刻出一个大概。

           e. 过早优化是浪费时间,因为后期需求变化,可能导致你的代码根本用不上了。

(3)底层过程也很重要。

           a. 如果遵循先写伪代码,后填充的过程,就能受益于自上而下的设计方式。

           b. 还要保证在写代码的时候添加注释,而不是之后再添加。

(4)关注大的过程和小的过程,意味着停下来关注软件构建方式。这是值得花时间的。

           a. 有人说,“代码才是最重要的,所以必须将注意力集中于如何写好代码,而不是抽象过程”

           b. 这简直是鼠目寸光,而且还忽略了大量与之相悖的试验和实践证据。

           c. 软件开发是一个创造性的活动,如果不理解创造性的过程,将无法充分利用构建软件的主要工具----大脑。

           d. 糟糕的过程只会浪费脑力,好的过程则可以将脑力充分发挥到极致。

3. 编写程序时,先考虑人,再考虑机器

 贯穿本书的另一个主题:强调代码的可读性

(1)写可读的代码时,能帮助别人理解你的代码

  • 可理解性
  • 可审查性
  • 错误率
  • 调试
  • 可修改性
  • 开发时间(上述因素的结果)
  • 外部质量(上述因素的结果)                 

(2)写可读性强的代码所花的时间,并不见得比写令人疑惑的代码更长 

        a. 易读的代码,更容易保证它的运行,这也司写可读性代码的重要原因。

        b. 代码审查时,有人读

        c. 自己或别人修改错误时,有人读

        d. 别人要使用时,有人读

(3)让代码可读,不是开发过程中的可选项,而是必选项

        a. 只考虑节省写代码的时间,而不管读代码的时间,并不经济

        b. 应该花时间,一次性写出好代码,而不是花时间一遍又一遍地读烂代码

(4)一个人的项目,是否需要在意代码的可读性呢?

        a. 你经常僵着表情,那么就容易僵着表情,正所谓习惯成自然。

        b. 习惯影响着你的工资,让你做不到收放自如。

        c. 一开始就养成良好的习惯,专业的程序员写的代码总是很容易理解的。

(5)细节技术累加,使程序焕然一新

        a. 好的类、程序和变量命名

        b. 精心的代码布局

        c. 短小的程序

        d. 将复杂的布尔测试隐藏在布尔函数中

        e. 将中间结果赋值给变量,让复杂的计算更清晰

        

4. 深入语言去编程,而不是用语言来编程

不要将编程的想象力局限于语言自动支持的范围。

一流的程序员会深度思考自己的目标,然后评估如何利用手头的编程工具来达成目标。 

(1)不能因为语言支持使用全局数据或goto语句就用它们。

        a. 可以选择不适用这些危险的编程能力,而是使用编程规范去弥补这些语言的弱点。

        b. 使用最显而易见的方式进行编程,不只限于会使用一种语言,而要深入研究。

        c. “如果弗雷迪从桥上跳下,你也会从桥上跳下吗?”。思考自己的技术目标,然后再决定怎样深入使用编程语言用最好的方式实现这些目标。

        d. 编程语言不支持断言?那就自己动手写assert()程序

5. 借助于规范来保持专注

规范是用于管理复杂性的知识工具 

(1)编程的许多细节是有些随意的,以下问题的一致性更重要

        a. 循环体中缩进多少空格?

        b. 怎么样设置注释的格式

        c. 如何排列类的顺序?

(2)规范应该精确传达重要的信息

        a. 单个字符就能区分局部变量、类变量和全局变量

        b. 使用大写就能精确区分类型、命名常亮和变量

        c. 缩进规范能精确展示程序的逻辑结构

        d. 对齐规范能精确说明不同语句之间的关系

(3)规范能避免各种已知危险。

        a. 建立禁止使用的规范,来说明限制在需要的时候使用它们,例如:

        b. 限制使用全局变量

        c. 禁止一行写多个语句

        d. 复杂表达式必须加括号

        e. 指针删除后立即置空,防止野指针错误

(4)对于低层次的任务来说,规范增加了可预测性

        a. 处理内存请求、错误处理、输入/输出和类接口进行规范,能为代码带来有意义的结构

        b. 禁止使用全局数据,最大的收益是可以避免在不同类和子系统之间进行潜在的交互,其他人修改的时候,意识不到全局数据对子系统所造成的破坏。

        c. 全局数据还增加了读程序时的不确定性。

(5)规范能弥补语言的不足之处

        a. 对不支持命名变量的语言(Python、shell),规范能区分用于读/写的变量和用于只读的常量

        b. 限制全局数据和指针的使用的规范司弥补语言不足的的一个范例

(6)合理、充分利用规范

        a. 大项目中,避免过度使用规范,这会花费大量时间去记忆

        b. 小项目中,不要忽视规范,要意识到精心设计的规范是有很大益处的

6. 面向问题域编程

另外一种处理复杂性的特殊方式是在尽可能高的抽象层次工作 

 将程序划分为不同的抽象层次:

4:高层次问题域        
3:低层次问题域
2:低层次实现结构
1:编程语言结构和工具
0:操作系统的操作和机器指令

 0层:操作系统和机器指令,一般不涉及

1层:编程基本数据类型和控制结构等

2层:通常是数据结构和算法等细节,这也是考验一个程序员的基本实力参考点

3层:它是底层计算机科学结构和顶层高层次问题域代码之间的粘合层。

         创造解决问题的基本部件,他们提供了一个框架使得高层次的类能用它们来构建问题的解决方案。

4层:这个层次提供根据问题域的术语处理问题的抽象能力。

        应该主要依赖于3层所构建的类或工具,实现细节应该隐藏在其下两层

解决问题域的低层次技术

  • 使用类来实现在问题域中有意义的结构
  • 隐藏低层次数据类型及其实现细节的信息
  • 使用命名常量来说明字符串和数字文本的含义
  • 使用中间变量来记录中间计算的结果
  • 用布尔函数来使复杂的测试更清晰

7. 当心落石

编程并不完全是一门艺术,也不完全是一门科学。通常,在实践性应用中,它是介于艺术和科学之间的“手艺”。

(1)好的判断力部分来自于对大量小问题的警告信号是否敏感

        a.  当有人说“这段代码真心搞不定”时,这就是一个警告信号,通常意味着代码有问题。

        b. 一个类产生的错误高于平均数,这也是个警告信号。一些容易出错的类往往是程序中最费力的部分。

        c. 因为编程司一门手艺,所以大部分警告都应该改良,而不是所有的警告都必须改良。

(2)缺陷数量异常意味着代码质量较低,好的开发过程不允许开发容易出错的代码

        a. 它应该有架构的检查和平衡之后的架构评审

        b. 设计之后有设计评审

        c. 代码之后有代码review

        d. 当代码准备测试时,大多数错误应该已经消除了

        e. 出色的工作表现除了要求努力工作,还要聪明工作。

        f. 花一天时间写代码,却要花两周的时间来调试,显然不够聪明

(3)设计度量也是一种类型的警告信号,大多数设计度量都对设计质量有启发性

        a. 一个类的成员如果超过7个,虽然并不意味着设计得不好,但它会提醒你这个类有些复杂

        b. 超过10个决策点的程序、超过三层的逻辑嵌套、过多的变量、与其他类的高耦合以及类或程序的低内聚都是警告标志

        c. 我们应该要以怀疑的眼光看它们

(4)以下情况应该要“感到不满和不安”

        a. 重复写代码或做相似的修改

        b. 很难写测试用例代码

        c. 无法在其他程序中重用代码是因为有些累互相依赖(类的耦合度太高)

  (5) 深入到程序中,留意那些表明设计不合理的警告信号

        a. 写注释、命名变量以及将问题分解为具有清晰接口的内聚类,都很难,表明需要在编码之前更仔细地考虑设计。

        b. 花哨的名字和难以用简洁的注释来描述代码的各个部分,也是预示着有麻烦的信号。

        c. 只要设计清晰,层次的细节也就容易准确

(6)对于程序中出现的难以理解的迹象,要敏感

        a. 任何卡顿的地方都是线索

        b. 如果你都难以理解,接盘的程序员就更难理解了

        c. 如果需要猜测代码的意图,同样说明它太复杂了

(7)要让程序很难忽视问题       

8. 迭代、迭代、迭代,重要的事情说三遍

1. 在系统规划的早期,你和用户合作,反复讨论需求,直到确定已达成共识,这是个迭代过程。

2. 通过增量来构建和交付系统来增加过程的灵活性,也是一个迭代的过程。

3. 在投入开发最终的产品之前,使用原型快速且低成本开发出多个替代方案,是另外一种迭代方式。

4. 需求的迭代比软件开发过程的其他方面更重要。

  • 项目之所以失败,是因为人们在探索替代方案之前致力于解决方案 

迭代提供了一种学习方式,以便可以在更多信息之后才开始真正构建

 (1) 软件设计是一个启发式的过程,和所有的启发式过程一样,需要不断迭代修正和改进。

        a. 软件更多是实证而不是证明,意味着需要不断迭代测试和开发,直到正确解决问题。

        b. 概要设计和详细设计也都是迭代的过程。

        c. 首先,尝试产生一个能工作的解决方案,而不是最好的解决方案,经过反复尝试不同的方法来洞察问题,这是用单一方法做不到的。

(2) 迭代思想也可以应用于代码调优

        a. 一旦软件可以运行,你就可以重写其中一小部分,从而大大提高系统的整体性能。

        b. 然而,许多优化的尝试对代码而言弊大于利。这不是一个直观的过程,有些技术看似使系统更小、更快,实际上却使系统更大、更慢了。

        c. 优化技术影响的不确定性使得我们需要不断地调优、度量再调优

        d. 如果系统有性能瓶颈,可以根据需要对代码进行多次调优,并且,多次之后的尝试可能比第一次更成功

(3)评审贯穿整个开发过程

        a. 在迭代的任何阶段都可以插入评审。

        b. 评审的目的司检查某个特定时刻的工作质量。

        c. 如果产品评审有问题,就返工,如果通过,就不需要进一步迭代

(4) 工程的一个定义是以最短的时间和最少的人力与物力做出有价值的东西。

        a. 软件开发后期,迭代会有事半功倍的效果

        b. 务必计划着废掉一个,因为最后总会那样,都要先做个一次性的

        c. 软件工程的诀窍司尽可能快速、低成本地构建一次性的部件,这是早期迭代的重点

9. 警惕编程中的执念

执念在软件开发中,以多种形式出现

   a. 教条主义者,坚持单一的设计方法

   b. 对特定风格或注释保持坚定不移的信念

   c. 对全局数据的非理性回避

(1)折中主义

        软件开发技术或设计方法,就像工具箱中扳手🔧 ,老虎钳,螺丝刀 🪛,等多种工具,我们不能仅仅只用一种工具去解决问题

(2)试验 

        抱着开发的心态去试验新的方法,并且愿意根据试验结果改变自己的想法

总结

        1. 编程的一个主要目标是管理复杂性

        2. 编程的过程对最终的产品有着重大影响

        3. 团队编程更多的人与人之间的沟通,而不是人与计算机的沟通。个人编程更多的是同自己沟通(思考)而不是计算机

        4. 如果编程规范被滥用,可能会适得其反。如果能够谨慎而合理地使用,编程规范可以为开发环境增加有价值的结构并且有助于管理复杂性和促进沟通

        5. 面向问题而不是解决方案的编程有助于管理复杂性

        6. 重视“质疑之源”的警告信号在编程中特别重要,因为编程几乎是一种纯粹的智力活动

        7. 开发活动迭代次数越多,活动的产出就越好

        8. 教条主义方法论和高质量软件开发不能混为一谈。在我的“智力工具箱”中装备满各种不同编程方法,并且提高技能选择合适的工具来完成工作

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
本系统的研发具有重大的意义,在安全性方面,用户使用浏览器访问网站时,采用注册和密码等相关的保护措施,提高系统的可靠性,维护用户的个人信息和财产的安全。在方便性方面,促进了校园失物招领网站的信息化建设,极大的方便了相关的工作人员对校园失物招领网站信息进行管理。 本系统主要通过使用Java语言编码设计系统功能,MySQL数据库管理数据,AJAX技术设计简洁的、友好的网址页面,然后在IDEA开发平台中,编写相关的Java代码文件,接着通过连接语言完成与数据库的搭建工作,再通过平台提供的Tomcat插件完成信息的交互,最后在浏览器中打开系统网址便可使用本系统。本系统的使用角色可以被分为用户和管理员,用户具有注册、查看信息、留言信息等功能,管理员具有修改用户信息,发布寻物启事等功能。 管理员可以选择任一浏览器打开网址,输入信息无误后,以管理员的身份行使相关的管理权限。管理员可以通过选择失物招领管理,管理相关的失物招领信息记录,比如进行查看失物招领信息标题,修改失物招领信息来源等操作。管理员可以通过选择公告管理,管理相关的公告信息记录,比如进行查看公告详情,删除错误的公告信息,发布公告等操作。管理员可以通过选择公告类型管理,管理相关的公告类型信息,比如查看所有公告类型,删除无用公告类型,修改公告类型,添加公告类型等操作。寻物启事管理页面,此页面提供给管理员的功能有:新增寻物启事,修改寻物启事,删除寻物启事。物品类型管理页面,此页面提供给管理员的功能有:新增物品类型,修改物品类型,删除物品类型。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值