概述

不管在那个开发团队中每个人的编写风格往往是千差万别能力也有高低,如何让别人快速看懂自己的代码维护你的代码。尽量避免不必要的简单错误,为编写代码作一定的约束是必不可少的。
如果你说我一个人不需要规范,其实不然。个人的代码风格能看出你的实际能力。犹如写文章一样杂乱有章,别人看都不愿意看,再精彩的故事也没用。日后自己维护也会头大。

因此有一份简单的代码编写约束是非常有必要的,不仅能提高可读性而且能提高代码质量。

1.    创建分析工程

打开软件后,有显示向导界面(默认关闭的,可以通过File菜单下的Run Wizard打开)在工程选择界面上选要分析的工程(如下图所示)

(图1)

选择工程后下一步,选择Delphi版本,选择后,在分析设置界面,我们可以选(Main File And Used Units),不用包括DFM文件,路径和条件设置界面中,可以把所有的选项都不选(这些可以在后面调整),选项确认后,会提示保存,可以选择保存(也可以不保存),选择后,工具进入分析阶段(需等一会儿),分析完,生成分析报告(如下图所示)

(图2)

也可以在进入界面后,直接新建工程(File菜单下的New Project 或工具条新建),新建后点击分析中的运行。

分析的工程文件(. dpr)不需要编译通过的,可以根据分析需要创建只包括需要分析的单元,这里要注意最好有工程同名的配置文件(.dof)。

2.    工程选项设置

在打开已有工程或新建工程后,选择工程属性(或通过New Project方式打开)

在这里需要关注的主要有:

a)         工程版本(Target version),该选项按实际情况选择(暂不确认对分析有什么影响)

b)        包含文件必须存在(Include Files must Exist),该选项可以不选(特别是有某些目录被排除的情况下,选择会导致分析报错并中断)

c)         使用工程设置(Use Delphi Project options if found),如果进行全工程分析时,可以选择此选择,选择此选项后,分析工具会使用工程中的搜索路径,分析的单元会很多。

d)        Delphi环境路径(Append Delphi library path 和Browsing path)该选项建议不选。

e)         分析排除路径(Exclude search path),有设置时,分析工具将不分析排除路径下的单元,因工程经常会携带一下第3方的控件,这种情况下,把这些控件目录及子目录排除,会减少不必要的分析(注意排除路径可能不支持相对路径,最好使用绝对路径,或直接通过向导设置)。

3.    分析报告解读

该工具的分析报告内容比较多,根据一段时间的使用和分析,感觉以下分析项目意义较大:

Warnings(警告方面):

Ambiguous unit references(重要)

Interfaces passed as parameters without "const" directive(重要)

Constructors/destructors without calls to inherited(重要)

Function result not set(重要)

Interfaced identifiers that are used, but not outside of unit(一般)

Interfaced class identifiers that are public/published, but not used outside of unit(一般)

Dangerous Exit-statements(一般)

Empty finally-block(一般)

Possible bad object creation(一般)

Ambiguous references in with-blocks(一般)

Optimization(优化方面):

Missing "const" for unmodified string parameter(重要)

Local subprograms with references to outer local variables(一般)

Memory(内存方面):

Local objects with unprotected calls to Free(一般)

Unbalanced Create/Free(一般)

Code Reduction(代码精简方面):

Local identifiers that are set and referenced once(一般)

Local long strings that are initialized to empty string(一般)

Boolean assignment can be shortened(一般)

Convention Compliance(习惯约定方面)

Local identifiers that "shadow" outer scope identifiers(一般)

Inconsistent Case(大小写不一致方面)

Inconsistent case for same identifier(一般)

下面对这些关注方面进行简要说明,方便理解。

警告提示(Warnings)

重要关注方面

a)         不明确的引用关系(Ambiguous unit references)

该提示说明,使用的常量、函数、过程有重名现象,这些需要分析,尽量消除。

b)        接口类型参数未加const 声明(Interfaces passed as parameters without "const" directive)

function Save(ADB: IBaseDBIntf): Boolean; virtual;

接口作为参数传递,未加const 声明时,编译器在调用时 会加上 _AddRef 调用结束后会加上 _Release,这在频繁调用时会降低效率。

c)         解构/析构未继承调用(Constructors/destructors without calls to inherited)

如果类继承父类,解构时未继承调用可能会导致父类未初始化;析构时未继承调用可能会导致内存泄漏。类似的还包括(Destructors without override 未声明覆盖)。

d)        函数未设置返回值(Function result not set)

function TdlgInputHuanSuanLv.ActOkNotify: Boolean;
begin
DoOk;
end;

该情况Delphi编译时,通常也有警告提示,函数未设置返回值可能会导致不可预料的结果。

一般关注方面

a)         对外定义(包括类、函数等声明)被使用了,但只在本单元内(Interfaced identifiers that are used, but not outside of unit)

简单示例如function BoolToInt

function BoolToInt(ABoolValue: Boolean): Integer;

implementation

{$R *.dfm}

function BoolToInt(ABoolValue: Boolean): Integer;
begin
Result := Integer(ABoolValue);
end; procedure TForm1.Button2Click(Sender: TObject);
begin
ShowMessage(IntToStr(BoolToInt(False)));
end;

这个提示可以列出一些不必要公布的函数或类,对这些函数或类进行一些分析后,可能会有新的归类和设计。

b)        对外公布类的公共属性和方法,只在本单元使用了(Interfaced class identifiers that are public/published, but not used outside of unit)

这个提示可以用来帮助精简对外公用的属性和方法

c)         危险的退出(Dangerous Exit-statements)

在一个过程、函数中,如果开头有Exit 就会提示该信息,这通常有两种情况:一是该过程不使用了,建议删除该过程;另一种是调试时增加的代码,但忘记删除了,这个需要确认核实。

d)        空的强制执行模块(Empty finally-block)

有该提示的 Try … finally结构可以删除,提高代码效率。

e)         可能是错误类创建过程(Possible bad object creation)

procedure Proc;
var
Bmp : TBitmap;
begin
Bmp.Create; //错误
end;
procedure Proc2;
begin
TNode.Create(Parent);//内存泄漏
end;

有这样提示的代码可能或导致错误或内存泄漏。

f)         危险的块声明引用(Ambiguous references in with-blocks)

procedure TForm1.Button1Click(Sender: TObject);
begin
with Button1 do
begin
Caption := 'test';
end;
end;

这种提示通常发生在 块定义的类实例和过程所属的类有同名的属性或过程(如上图代码 Caption),这在复杂逻辑中往往会导致问题。

优化建议(Optimization)

重要关注方面

a)         未发生修改的字符串参数未声明为const (Missing "const" for unmodified string parameter)

function LoadSQL(ACondition: string; AOnlyStruct: Boolean = False): 

因字符串有引用计数,在明确知道不需要修改的字符串参数前,请加上 const,这样可以提高效率。类似的参数还有 record、array、Interface等。

一般关注方面

a)         子过程使用过程外的变量(Local subprograms with references to outer local variables)

procedure TSelectTextHelper.InitFields(AFields: TSerializableFields; AItem: TSerializeItem);
var
i: Integer;
aField: TSerializableField;
procedure InnerAddField(AIdx: Integer);
begin
aField := TSerializableField(AFields.Append);
aField.FieldName := aField.FieldItem.ClassFieldName;
aField.DataType := TypeKindToFieldType(aField.FieldItem.DataType);
end;
begin
AFields.Clear;
if AItem <> nil then
begin
i := AItem.ObjFieldsMap.IndexByName(AItem.KeyField);
InnerAddField(i);
end;
end;

如上面的代码所示,子过程使用外面的 aField,这种情况需要尽量避免(特别是影响效率的代码段),建议子过程尽量放在 变量声明前面。

内存建议(Memory)

一般关注方面

a)         过程内的对象未在保护结构内释放(Local objects with unprotected calls to Free)

var
aList: TList;
begin
aList := TList.Create;
;//省略逻辑过程
aList.Free;

对象释放过程没有在保护结构时,如果释放前有异常抛出或提前退出时,会导致内存泄漏,建议释放过程尽量使用 try … finall结构。

b)        不对称的创建释放(Unbalanced Create/Free)

procedure LocalProc;
var
Obj: TMyClass;
begin
Obj := TmyClass.Create;
Obj.DoSomething;
end;

不对称释放,往往会导致内存泄漏,但分析工具对一些加入列表的、全局对象等判断不够,导致很多误报。另外还有下面这种情况也不提倡使用,最好把返回对象作为参数传入,这样可能避免疏忽引起的泄漏

function TForm1.GetList: TStringList;
begin
;//省略逻辑
Result := TStringList.Create;
end;
//建议改成
procedure TForm1.GetList(Alist: TstringList);
begin
;//省略逻辑
end;

代码精简建议(Code Reduction)

一般关注方面

a)         过程内本地变量只使用一次(Local identifiers that are set and referenced once)

var
aData: TSearchResult_Data;
begin
if FDataList <> nil then
begin
aData := TSearchResult_Data(FDataList.Items[AIndex]);
if not aData.Valid then
Value := cst_Invalid_Price;
end;
end; //可精简为
begin
if FDataList <> nil then
begin
if not TSearchResult_Data(FDataList.Items[AIndex]).Valid then
Value := cst_Invalid_Price;
end;
end;

不在循环体内的只使用一次的变量往往可以精简,如上图,这种情况要具体情况具体分析,有很多时候,分析报告这方面的提示是不正确的。类似的还有Local identifiers that possibly are set and referenced once,这里不另外列举。

b)        过程内字符串变量初始化为空(Local long strings that are initialized to empty string)

var
s: string;
begin
s := '';
;//省略逻辑

如上例所示,s设置为空是没有必要的,编译器已经自动初始化了。

c)         布尔赋值可以更精简(Boolean assignment can be shortened)

       if CheckedCount > 0 then
NewState := True
else
NewState := False; //可以精简为
NewState := CheckedCount > 0;

该类提示往往是代码使用了条件判断再赋值的方式,该类代码可以优化另外也可以关注(Unneeded boolean comparisons)。

习惯约定建议(Convention Compliance)

一般关注方面

a)         参数重名情况Local identifiers that "shadow" outer scope identifiers

procedure TfrmMessageDlg.showButton(flags, timeCount: Integer);

  function GetButtons(Flags: integer): TMsgDlgButtons;
begin
;//省略逻辑
end; begin
;//省略逻辑
end;

该情况一般发生在过程下有子过程中,如上面的代码所示,建议不要重名现象,重名会导致易读性下降。

大小写不一致建议(Inconsistent Case)

一般关注方面

a)         相同定义大小写不一致Inconsistent case for same identifier

  procedure DoSaveEvent(ATotal, ACur: Integer);
begin
if Assigned(FSaveEvent) then
FSaveEvent(aTotal, aCur);
end;

如上面的代码所示,参数位大写,在使用时为小写,这个不符合编码规范,建议关注这方面的提示,使代码更规范。

4.    结束语

在团队合作中统一的代码规范是非常有必要的。提高代码质量、提高代码可读性等起到一定作用,上面只是列举了部分内容,分析报告中的General分支下还有很多好的建议,我们日常工作中都能应用到,另外该工具的帮助文档虽然简单,但各项建议的含义都有说明,大家不妨读一下。

http://www.cnblogs.com/gleam/archive/2013/05/08/3066679.html

Pascal Analyzer 4 代码分析使用简要说明的更多相关文章

  1. 使用Memory Analyzer tool(MAT)分析内存泄漏(二)

    转载自:http://www.blogjava.net/rosen/archive/2010/06/13/323522.html 前言的前言 写blog就是好,在大前提下可以想说什么写什么,不像投稿那 ...

  2. 使用Memory Analyzer tool(MAT)分析内存泄漏

    前言的前言 写blog就是好,在大前提下可以想说什么写什么,不像投稿那么字字斟酌.上周末回了趟成都办事,所以本文来迟了.K117从达州经由达成线往成都方向走的时候,发现铁路边有条河,尽管我现在也不知道 ...

  3. Android4.0图库Gallery2代码分析(二) 数据管理和数据加载

    Android4.0图库Gallery2代码分析(二) 数据管理和数据加载 2012-09-07 11:19 8152人阅读 评论(12) 收藏 举报 代码分析android相册优化工作 Androi ...

  4. 免费的Lucene 原理与代码分析完整版下载

    Lucene是一个基于Java的高效的全文检索库.那么什么是全文检索,为什么需要全文检索?目前人们生活中出现的数据总的来说分为两类:结构化数据和非结构化数据.很容易理解,结构化数据是有固定格式和结构的 ...

  5. 虚拟机创建流程中neutron代码分析(二)

    前言: 当nova服务发送了创建port的restful调用信息之后,在neutron服务中有相应的处理函数来处理调用.根据restful的工作原理,是按照 paste.ini文件中配置好的流程去处理 ...

  6. 虚拟机创建流程中neutron代码分析(三)

    前言: 当neutron-server创建了port信息,将port信息写入数据库中.流程返回到nova服务端,接着nova创建的流程继续走.在计算节点中neutron-agent同样要完成很多的工作 ...

  7. Hive metastore整体代码分析及详解

    从上一篇对Hive metastore表结构的简要分析中,我再根据数据设计的实体对象,再进行整个代码结构的总结.那么我们先打开metadata的目录,其目录结构: 可以看到,整个hivemeta的目录 ...

  8. 2018-2019-2 20165312《网络攻防技术》Exp4 恶意代码分析

    2018-2019-2 20165312<网络攻防技术>Exp4 恶意代码分析 知识点总结 1.有关schtasks schtacks的作用:安排命令和程序定期运行或在指定时间内运行.从计 ...

  9. 20155208徐子涵 Exp4 恶意代码分析

    20155208徐子涵 Exp4 恶意代码分析 实践目标 1.1是监控你自己系统的运行状态,看有没有可疑的程序在运行. 1.2是分析一个恶意软件,就分析Exp2或Exp3中生成后门软件:分析工具尽量使 ...

随机推荐

  1. IOS 表视图(UITableVIew)的使用方法(3)名单的索引显示

    当数据量特别大时,简单地以role进行分段,对实际查找的效率提升并不大.就像上一节开头所说,开发者可以根据球员名字的首字母进行分段,且分成26段.由于段数较多,可以使用UITableView的索引机制 ...

  2. css 一些事

    1.两个div左边的固定宽度右边的自动填充的css <div id="main" style="width:98%;"> <div id=&q ...

  3. IM与工作信息流整合

    IM与工作信息流整合,希望减轻用户“信息”负担   从36氪此前的<“明道”现在推出个人免费版本,是怎样的逻辑?>一 文中,我们可以了解到,国内现在的协作产品设计思路主要有两种:一种是像t ...

  4. java学习之JDBC

    之前学习了数据库原理,上学期也学了oracle数据库,我的学习视频上是讲的mysql数据库,其实都差不多,复习了下sql知识,数据库的学习就没有写下来了,就从Java怎么操作数据库开始吧. 因为这年过 ...

  5. HDOJ Sudoku Killer(dfs)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1426 思路分析:该问题为数独问题,明显解是唯一的,所有采用dfs搜索效果更好: 在搜索时,可以通过3个 ...

  6. Uber 叫车时,弹出以下代码导致无法打车(An email confirmation has been sent to...),解决办法

    ”鄙人用了虚拟信用卡+广西的手机号码+163邮箱申请了Uber的新帐号...然后输入mastercn优惠码,上网查询只有这个优惠码,应该就能免费的使用一次用车,限额200元.但在点用车时  弹出窗口提 ...

  7. hdu1281结题报告

    哎哎...自己刚刚一看到这个题目居然.....什么都想不到...看了一下别人的解题报告说最大匹配...于是就自己开始构思啦... 对于这个棋盘,有K个可以放棋子的位置....那么 首先我们开始可以求出 ...

  8. 利用Linux命令行进行文本按行去重并按重复次数排序

    最近杂事太多,正事进展缓慢.Fighting! linux命令行提供了非常强大的文本处理功能,组合利用linux命令能实现好多强大的功能.本文这里举例说明如何利用Linux命令行进行文本按行去重并按重 ...

  9. linux shell: 搜索字符串,剔除包含特定字符的行

    搜索代码中出现CONFIG_BOOTARGS的行,但又不希望有#define和#undef, 暂时不知带如何直接用一个语句做到,因此用了如下三个语句. find . -type f | xargs g ...

  10. BZOJ 1711: [Usaco2007 Open]Dingin吃饭( 最大流 )

    将牛拆成两个点 i 和 i' 并连弧 , S 向每种 food 连边 , 每种 drink 向 T 连边 , 每种 food 向喜欢他的 cow 连边 到 i , 每种 drink 从喜欢它的 cow ...