《代码大全2》读书笔记(1): 架构的典型组成成分

前言

自己独立设计开发过多个项目,从最初的毫无前期设计到后面有一定的设计意识,但是总觉得对于前期的架构设计理解不够,对于架构设计应该产出的东西也缺乏认识。
一番思索之后觉得可能是缺乏相关理论的支撑才导致了架构能力一直难以提升,于是想从一些经典书籍中吸取一些营养。
本文是读《代码大全2》的第一篇读书笔记。便以架构组成开始,也会涉及到第三章的一些总结。

程序组织

系统架构首先要以概括的形式对有关系统做一个综述,将所有的子系统拼接在一起。将那些曾将考虑过的最终组织结构的替代方案记叙下来,并给出选与不选的理由。

定义主要的构造块

根据程序的规模不同,每个构造块可能是单个类,也可能是由许多类组成的子系统;每条列在需求中的功能都至少有一个构造块覆盖它;如果两个或多个构造块声称实现同一项功能,那么它们应该相互配合而不会冲突。

明确各个构造块的责任

每个构造块应该负责某一个区域的事情,并且对其它构造块负责的区域知道得越少越好,通过每个构造块对其它构造块的了解达到最少,你能将设计的信息局限在各个构造块。

一句话总结,就是: “高内聚,低耦合”

主要的类

  • 架构应该详细定义所用的主要的类。它应该指出每个主要的类的责任,以及该类如何与其它的类交互;
  • 它应该包含对类的继承体系,状态转换,对象持久化等描述;
  • 如果系统足够大,它应该描述如何将这些类组成一个个子系统;
  • 无需说明每一个类,对于构成80%的行为的20%的类进行详细说明。

数据设计

架构应该描述所用到的主要文件和数据表的设计。它应该描述曾经考虑过的其它方案,并说明做出选择的理由。

数据通常只应该由一个子系统或者一个类直接访问;例外的情况就是通过访问器(access class)或访问器子程序(access routine)–以受控且抽象的方式–来访问数据。

私以为这种设计理念类似于DAO(Data Access Objects)的设计。

业务规则

如果架构依赖于特定的业务规则,那么它就应该详细地描述这些规则,并描述这些规则对于系统设计的影响。

用户界面设计

架构应该详细定义Web页面格式、GUI、命令行接口等主要元素。

架构应该模块化,以便在替换为新用户界面时不影响业务规则和程序的输出部分。

资源管理

架构应该描述一份管理稀缺资源的计划。稀缺资源包括数据库连接、线程、句柄等。

架构应该估算在正常情况和极端情况的资源使用量。

在更复杂的情况中,也许会要求程序主动管理其拥有的资源。

安全性

架构应该描述设计层面与代码层面的安全性方法。

在制定编码规范的时候应该把安全性牢记在心,包括处理缓冲区的方法,处理非信任数据(用户输入的数据,cookie、配置数据(文件)和其它外部接口输入的数据)的规则、加密、错误消息的细致程度、保护内存中的数据,以及其它事项。

性能

如果需要关注性能,就应该在需求中详细定义性能目标。

架构师应该提供估计的数据,并解释为什么架构师相信能达到性能目标。如果某些部分存在达不到性能目标的风险,那么架构也应该指出来。如果为了满足性能目标,需要在某些部分使用特定的算法或者数据类型,架构也应该说清楚。架构中也可以包含各个类或各个对象的空间和时间预算。

可升缩性

可伸缩性是指系统增长以满足未来需求的能力。架构应该描述如何应对用户数量、服务器数量、网络节点数量、数据库记录数、数据库记录的长度、交易量等的增长。

互用性

如果预计这个系统会与其它软件或硬件共享数据或资源,架构应该描述如何完成这一任务。

国际化/本地化

对于交互系统,各种状态和提示消息非常多,架构应该表现出已经考虑过典型的字符串问题和字符集问题,如何无需更改代码就能维护这些字符串,如何将这些字符串翻译成另外一种语言而又尽量不影响代码和用户界面。

架构可以决定,在需要的使用,是在代码中直接嵌入字符串;还是将这些字符串封账在某个类中,并透过类的接口来使用它;或者将这些字符串存入资源文件。架构应该说明选用哪种方案,并解释原因。

输入输出

架构应该详细定义读取策略: (reading scheme)是先做(look-ahead)、后做(look-behind)还是即时做(just-in-time)。而且应该描述在那一层检测IO错误: 在字段、记录、流、或者文件的层次。

错误处理

错误处理需要考虑的一些问题:

  • 错误处理是进行纠正还是仅仅进行检测?无论哪种情况,都应该通知用户说检测到一个错误。
  • 错误检测是主动的还是被动的?
  • 程序如何传播错误?
  • 错误消息的处理有什么约定?
  • 如何处理异常?架构应该规定代码何时能抛出异常,在什么地方抛出异常,如何记录异常,以及如何在文档中描述异常。
  • 在程序中,在什么层次上处理错误: 发现错误的地方处理;将错误传递到专门处理错误的类处理;沿调用链往上传递错误。
  • 每个类在验证其输入数据的有效性方面需要负何种责任?是每个类负责校验自己数据的有效性,还是有一组类负责校验整个系统的数据的有效性?某个层次上的类是否能假设它接收到的数据是干净的。
  • 使用环境内建的错误机制还是建立一套自己的错误机制?

容错性

架构还应该详细定义所期望的容错种类。容错包括: 检测错误;如何可能的话从错误中恢复;若不能恢复,则包含其不利影响。
常用考虑:

  • 系统在检测到错误的时候退回去,重试一次;
  • 系统拥有一套辅助代码,以备在主代码出错的时候使用;
  • 系统使用一种表决法,确定结果的准确性;
  • 系统使用某个不会对系统其余部分产生危害的虚假值代替错误的值。
  • 在遇到错误时,让系统转入某种“部分运转”的状态,或者转入某种“功能退化”的状态,系统可以自动关闭或重启。

架构的可行性

架构应该论证系统的技术可行性。如果任何一个方面不可行都会导致项目无法实施,那么架构应该说明“这些问题是如何经过研究的”–通过验证概念的原型(proof-of-concept-prototype)、研究、或其它手段。必须在全面开展构建之前解决掉这些风险。

优秀架构核对表

针对各架构主题:

  • 程序的整体组织结构是否清晰?是否包含一个良好的架构全局观(及其理由)?
  • 是否明确定义了主要的构造块(包括某个构造块的职责范围及与其它构造块的接口)?
  • 是否明显涵盖了“需求”中列出的所有功能(每个功能对应的构造块不太多也不太少)?
  • 是否描述并论证了那些最关键的类?
  • 是否详细定义了数据库的组织结构和内容?
  • 是否指出了所用关键的业务规则,并描述其对系统的影响?
  • 是否描述了用户界面设计的策略?
  • 是否将用户界面模块化,使界面的变更不会影响程序的其余部分?
  • 是否描述并论证了处理IO的策略?
  • 是否估算了稀缺资源(如线程、数据连接、句柄、网络带宽等)的使用量,是否描述并论证了资源管理的策略?
  • 是否描述了架构的安全需求?
  • 架构是否为每个类、每个子系统、或每个功能域提出空间与时间预算?
  • 架构是否描述了如何达到可升缩性?
  • 架构是否关注互操作性?
  • 是否描述了国际化/本地化策略?
  • 是否提供了一套内聚的错误处理策略?
  • 是否规定了容错的办法?
  • 是否证实了各个系统的技术可行性?
  • 是否详细描述了过度工程的方法?
  • 是否包含了必要的“买 vs 造”的决策?
  • 是否描述了如何加工被复用的代码,使之符合其它架构目标?
  • 是否将架构设计得能够适应很可能出现的变更?

架构的总体质量

  • 架构是否解决了全部需求
  • 有没有哪个部分是“过度架构”或“欠架构”?是否明确宣布了在这方面的预期指标?
  • 整个架构是否在概念上协调一致?
  • 顶层设计是否独立用于实现它的机器和语言?
  • 是否说明了所有的主要的决策的动机?
  • 你,作为一名实现该系统的程序员,是否对这个架构感觉良好?

花费在前期准备上的时间长度

花费在问题定义、需求分析、软件架构上的时间,依据项目的需要而变化。一般来说,一个运作良好的项目会在需求、架构以及其它前期计划投入10%-20%的工作量和20%-30%的时间。这些数字不包括详细设计的时间—那是构建活动的一部分。

前期准备核对表

  • 你是否辨明了自己所从事的软件的类型,并对所用的开发方法做出相应的剪裁?
  • 是否充分明确地定义了需求?而且需求足够稳定,能开始构建了?
  • 是否明确定义了架构,以便开始构建?
  • 是否已经指出你的(当前)项目中独有的风险(以避免构建活动面临不必要的风险)

本章要点

  • 构建活动的准备工作的根本目标在于降低风险。要确认你的准备活动是在降低风险,而非增加风险。
  • 如果你想开发高质量的软件,软件开发过程必须由始至终关注质量。在项目初期关注质量,对产品质量的正面影响比在项目末期关注质量的影响要大
  • 程序员的一部分工作是在教育老板和合作者,告诉他们软件的开发过程,包括在开始之前进行充分准备的必要性。
  • 你所从事的软件项目的类型对构建活动的前期准备有重大影响–许多项目应该是高度迭代式的,某些应该是序列式的。
  • 如果没有明确的问题定义,那么你很可能在构建期间解决错误的问题。
  • 如果没有做完良好的需求分析工作,你可能没能察觉待解决问题的重要细节。如果需求变更发生在构建之后的阶段,其代价是“在项目早期更改需求”的20至100倍。因此在开始编程之前,你要确认“需求”已经到位了。
  • 如果没有做完良好的架构设计,你可能在构建期间以错误的方法解决正确的问题。架构变更的代价随着“为错误的架构编写的代码数量”增加而增加,因此,也要确认“架构”已经到位了。
  • 理解项目前期准备所采用的方法,并相应地选择构建方法。

本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可。转载请注明: 作者staneyffer,首发于我的博客,原文链接: https://chengfy.com/post/6


载入评论中....