代码阅读和实践笔记

高级c数据类型

C指针

c程序中,指针一般用来:

  • 构造链式数据结构
  • 引用动态分配的数据结构

    #define new(type) (type*) calloc(sizeof((type),1)
    [...]
    node = new(struct codeword_entry)
    
  • 实现引用调用(call by reference)

  • 访问和迭代数据元素

  • 传递数组参数
    在c和c++程序中,将数组传递到函数和作为结果返回,都要用到指针。在c代码中,将数组名作为函数参数时,实际上传递给函数的是数组第一个元素的地址。因而,函数执行时对数组中的数据做出的任何修改都将影响到数组中的元素。
    类似函数返回也只是返回数组的指针。因此当函数在数组中生成结果并返回相应的指针时,一定要确保该数组不是在函数的栈上分配的局部变量。如果数组是局部变量要记得确保该数组不是在函数栈上分配的局部变量。避免这一问题的方法是将这类数组声明为static

  • 引用函数

  • 作为其他指的别名

    1. 效率上的考虑:
    2. 引用静态初始化的数据
    3. 在全局语境中实现变量引用语义
  • 代表字符串

  • 直接访问系统内存

结构

结构还是指向结构的指针?
把指针作为参数的方法的两个优点:既可以工作在较新的c上,也可以工作较旧的c上;只传递一个地址信息。
缺点:缺少对数据的保护。
把结构作为参数传递的一个优点是函数处理的原始数据的副本,这就比直接处理原始数据安全。

  • 将一般作为一个整体来使用的数据元素集合到一起
  • 从函数中返回多个数据元素
  • 构造链式数据结构
  • 映射数据在硬件设备、网络连接和存储介质上的组织方式
  • 实现抽象数据类型
  • 以面向对象方式编程
    可以将数据元素和函数指针聚合成结构,模拟类的字段和方法,创建与类相仿的实体。

    struct domain{
    int dom_family;
    char *dom_name;
    void (*dom_init)(void);
    [...]
    int (*dom_rtattach)(void **,int);
    int dom_rtoffset;
    int dom_maxrtkey;
    };
    
    //after init the struct,used like class
    for(dom = domains;dom;dom = dom -> dom_next){
    if(dom -> dom_family == i && dom -> dom_rtattach){
        dom -> dom_rtattach((void **)&nep ->ne_rtable[i],
                dom -> dom_rtoffset);
        break;
    }
    }
    

    实际上,由于同一类别的不同对象共享它们的方法,所以,程序常常在“对象”结构中只存储指向另外结构的指针。由这个结构给出指向实际方法的指针,从而达到不同对象间共享方法指针的目的。-》面向对象语言中的“虚方法”和“多态编程”代码阅读和实践笔记_第1张图片

Union

将共享同一块存储区域的项聚合起来。某一时刻,共享该区域的这些项中只有一项可以访问。
主要用途:

  • 有效利用存储空间
  • 实现多态
    多态数据

    enum msg_type{
    CALL = 0;
    REPLY = 1;
    };
    

    c数据结构

应对大型项目

设计与实现技术

  1. 在大型项目中,软件生命周期的各个组成部分常常被划分为更小的任务进行处理,它们经常是软件代码库的一个组成部分。
  2. 大规模的软件开发工作必须使用一种合适的架构来构造所要创建的系统。这个架构一般指定系统的结构,控制的处理方式,以及如何对系统各个组成部分进行模块分解。大型的系统还可能会从框架(framework)、设计模式(design pattern)和特定领域的架构中汲取灵感,重用它们架构上的思想。
  3. 大型系统的复杂性经常可以使用面向对象的设计和实现技术加以控制。一般将对象组织成不同的层次。之后,可以使用继承来提取出公共行为,动态调度技术使得单一的代码体能够处理众多不同的对象
  4. 在更大的粒度上,大型系统的代码经常分解为对象模块库,可重用组件,甚至独立的进程
  5. 构建工具

代码阅读和实践笔记_第2张图片

配置

配置(configuration)可以控制的软件系统,允许开发者编译、维护和发展源代码的单一正式版本
根据依赖关系隔离的原则,配置信息一般分为几个文件。影响系统如何编译的配置信息(例如,安装目录、工具名称和路径、是否存在可执行文件中包括调试富豪、应用的优化级别、使用的库和目标文件),经常以变量定义的形式表示在项目的制作文件中。
代码阅读和实践笔记_第3张图片

修订控制

我们可以将系统的源代码想象成在空间和时间两个方向上的延伸。代码,组织成文件和目录的形式,占据空间;同时,同一代码还随着时间的推移不断演化。
修订控制--版本控制

测试

设计良好的项目,都会预先为测试系统的全部或部分功能提供相应的措施。这些措施可能隶属于一份经过深思熟虑,用来验证系统运作的计划,也可能是系统的开发者在实现系统的过程中实施的非正式测试活动的残余。
最简单的测试代码是一条生成日志(logging)或调试(debugging)输出的语句。跟踪语句所在的地点一般也是算法运行的重要部分。

编码规范和约定

[...]
软件系统并非知识代码。因此,许多编码指导原则都延伸到开发过程的其他领域,包括文档、生成和发布过程的组织。
至少,许多指导原则都会规定标准的文档,以及编写它们的格式。

文档

阅读一小时代码所得到的信息只不过相当于阅读一分钟文档

文档类型

列出几种最具代表的:
系统规格说明文档:详细叙述系统的目标、系统的功能需求、管理和技术上的限制、以及成本和日程等要素。通过系统的规格说明文档能够了解所阅读代码的实际运行环境。
软件需求规格说明:提供对用户需求和系统总体构架的高层描述,并且详细记述系统的功能和非功能性需求,比如数据处理、外部接口、数据库的逻辑模式以及设计上的各种约束。是阅读和评估代码的基准
设计规格说明:一般描述系统的架构、数据和代码结构,还有不同模块之间的接口。面向对象的设计会勾画出系统的基本类型以及公开方法。细化的设计规格一般还包括每个模块(或类)的具体信息,比如它执行的具体处理任务、提供的接口,以及与其他模块或类之间的关系。还会描述采用的数据结构,适用的数据库模式等。认知代码结构的路线图、阅读具体代码的指引
系统的测试规格说明:包括测试计划、具体的测试过程、以及实际的测试结果。每个测试过程都会详细说明它所针对的模块以及测试用例使用的数据。
许多用户文档:功能描述、安装说明、介绍性的导引、参考手册和管理员手册。而且常常是我们唯一有可能获得的文档。。。在接触一个未知系统时,功能性的描述和用户指南可以提供重要的背景信息,从而更好地理解阅读代码所处的上下文。从用户参考手册中,我们可以快速获取应用程序的外观与逻辑上的背景知识。从管理员手册可以得知代码的接口、文件格式和错误消息的详细信息。

文档的问题

文档有可能提供不恰当的信息,误导我们对源代码的理解。

系统架构

从系统的源代码洞悉系统的架构,不是一件容易的事。然而,在识别出重要的架构元素之后,那么,浏览整个系统,了解系统的结构和属性,以及规划增加、修改和重构活动都会变得更为容易。这是因为,一旦提取出系统的架构行特征,我们就立即与系统的创建者共享一套语义丰富的词汇。另外,对系统架构的理解,能够帮助我们了解交互的类型、通信模式和代码结构。

系统的结构

常见、重要的结构可以归类为少数迥然相异的架构类型:集中式存储库(centralized repository)、数据流(data-flow)、面向对象(object-oriented)或分层(layered)架构。

集中式存储库:web应用
面向对象:建立在维护自身状态并相互作用的对象上。系统的架构由不同的类或对象之间的关系,以及对象交互的方式来定义。UML来表达系统的模型。

这关心的层次是系统中的控制流程和数据流。分析系统架构时,可以关注:

  • 源代码在目录中的安排
  • 静态或动态过程的调用
  • namespace,package
  • 类和接口的继承关系
  • 内部类和嵌套过程
  • 异构数据结构和对象关联中的导航

切片:将程序片(program slice)看作能够影响变量的值的一段程序。(dashplayer修改原则,我的理解)

控制模型

事件驱动的系统
许多系统中,控制决策通过响应外部生成的事件来完成。(嵌入式开发,关系型数据库的触发器)
实现方式可以有许多种:

  1. 事件广播给一系列的事件侦听者

    for(int i = 0;i < list.length;i ++){
    ((ContainerListener)list[i]).containerEvent(event);
    }
    
  2. 硬件中断

  3. 围绕事件循环构建,该循环不断地查询事件并执行相应的处理

    while(XtAppPending(appCtx))
    XtAppProcessEvent(appCtx,XtIMALL);
    

基于类的事件处理给应用程序带来两个明显优点:
* 事件可以以属性的形式承载附加信息,消除了无类型、通用的事件参数
* 通过继承可以实现一个事件层次,事件层次又能够驱动事件分派策略 ??没搞懂

下面通过代码理据下(反正就这两句话我是不懂)

public abstract class ArgoEvent extends EventObject implements ArgoEventTypes{
    protected int _eventType = 0;
    public ArgoEvent(int eventType,Object src){
        super(src);
        _eventType = eventType;
    }
}
//上面的ArgoEvent类扩展了Java EventObject,ArgoEvent接下来又被ArgoModuleEvent和ArgoNotationEvent类所扩展

系统管理器
需要多个进程并发执行的系统,经常采用系统管理器控制模型。一个单独的系统组件起到集中式管理器的作用,负责启动、停止和协调其他系统进程和任务的执行。

状态变迁
代码阅读和实践笔记_第4张图片

元素封装

模块和命名空间
对象是一个运行期间的实体
范型(数据结构或算法)
抽象数据类型
是模块的有组织集合
进程和过滤器(过滤器是一种特殊的进程)
软件组件(程序构成中典型的自包含单元)(JavaBeans)

架构重用

许多系统在设计时就遵循已经确立的架构。框架
因为可重用的架构,因为要满足一系列各种各样的应用程序,所以会比量身定做的应用的结构更为复杂。

你可能感兴趣的:(代码阅读和实践笔记)