读书摘要——《凌波微步-软件开发警戒案例集》
p15.
"将void,int,float等基本数据类型通过typedef重新命名,可以在最大程度上保证代码的可移植性——例如从16位程序至32位程序的移植问题即可通过此方法简单解决。
例如WIN32 SDK中大量出现的UINT ,DWORD等定义均属此列。
"
p18.
"匈牙利命名法存在很多严重的问题,其中之一是:一旦要修改变量类型,也就必须同时修改变量名称。这一问题,反映在必须保证接口稳定的WIN32 API上,更为棘手。"
p31.
"几乎所有现代C/C++编译器在处理内存中的数据结构以及sizeof运算符时,默认情况下,都会把类或结构占用的空间大小在8字节边界处对齐,以优化代码的执行速度。
可以通过预编译命令 #pragma pack (1)来取消这种默认对齐"
p42.
"定义和实际存储相关的数据结构时,最好不要使用int这种"可变长"的数据类型——int在16位、32位、64位计算机上的字节长度是不同的——相反,使用诸如DWORD这样的定长类型是个不错的选择。"
p66.
"assert()宏仅在NDEBUG宏无效的情况下才发挥作用,即若定义了NDEBUG宏(软件的releass版本),则assert()宏相当于空语句;若未定义NDEBUG宏(Debug版本),则assert检查参数,参数为假时,输出错误信息并终止程序。
assert()宏的最大问题是其在软件的release版本中将变为空语句,不起任何作用。
因此,不要在assert()中写入任何影响程序运行状态的语句,如assert(fp=fopen()),这种用法是错误的。
另外,对于外部参数(用户输入)不应该用assert()宏来检查有效性,assert()宏应用来检查内部参数(确定因素)。
MFC中特别提供了一个VERIFY宏,除了能完成assert()的验证功能外,其最大的特点是无论在Debug版还是Release版本中,都永远有效。"
p91.
"面向对象编程中不容忽视的一个问题:类的构造函数是没有返回值的。
这个特点使得如果在构造函数中进行资源分配,就必须采取一定办法将分配失败的情况通知调用者,否则就有可能造成内存访问异常。
解决方法通常有两种:
一是干脆不在构造函数中进行资源分配,而是在类中实现Initialize()和Uninitialize(),由这两个函数负责资源的释放和分配,返回值类型为bool。
二是利用对象的异常处理机制,当构造函数发生分配错误时,就跑出异常,一旦捕获异常,就不进行后续的工作。"
p131.
"属性是一种高级的面向对象特征,它与成员变量、方法一样,是编写类库或组件的常用方法。
属性的最大优点在于保证数据机器相关操作的完整和统一。"
成员变量易于定义比较单纯的数据元素,方法适于实现功能操作,属性则用于定义与某些功能操作关系紧密的元素。 "
p172.
"sendmessage()这个API的功能被定义为向窗口发送消息,并调用目标窗口的窗口过程函数来处理该消息,直到消息被处理完前函数保持阻塞状态。
postmessage()的功能与sendmessage()类似,区别在于postmessage()在将消息放入目标窗口的消息队列后立即返回,即是非阻塞的。"
p175.
"黑板擦问题
不应该将执行耗时操作的代码放置在需要负责处理用户消息的窗口线程中。"
p236.
" 版本控制的最重要目标和原则就是尽量避免不同版本代码中的重复内容,因为重复意味着重复工作,意味着重复错误。
而为了避免重复,应当将代码中共用的部分尽量提取出来,并且尽量让同一功能的代码集中在同一代码文件中。"
p246.
"全面质量管理(TQM:Total Quality Management)
p235
"被测实现(IUT:Implementation Under Testing)
测试中最重要的概念和原理是:
1.测试无法证明被测实现(IUT)的正确性。
2.测试只能证明被测实现(IUT)中包含错误。
p309.
"好的测试都是自动测试。测试计划和测试用例由人设计,但实际的测试操作确实由程序或者自动化工具完成的。
好的测试都是基于模型的。
最常用的测试模型包括组合模型和面向对象模型。"
p366.
"使用面向对象语言不等于基于面对对象的思想设计和开发软件。
面向对象设计(OOD)的基础是面向对象分心(OOA)。
面向对象分析的关键侍从应用中抽象出操作和数据的统一体。
面向对象分析的结果应该用UML(Unified Modeling Language)语言来描述。
UML只是一种描述模型的标准语言,而不是一种面向对象的分析方法。
无论我们使用和何种面向对象的分析方法,最终模型化的结果应该用UML语言来描述,因为这是面向对象世界的通用语言。"
p374.
"简化设计和增强复用性,这两条原则在软件的总体设计中至关重要。"
p15.
"将void,int,float等基本数据类型通过typedef重新命名,可以在最大程度上保证代码的可移植性——例如从16位程序至32位程序的移植问题即可通过此方法简单解决。
例如WIN32 SDK中大量出现的UINT ,DWORD等定义均属此列。
"
p18.
"匈牙利命名法存在很多严重的问题,其中之一是:一旦要修改变量类型,也就必须同时修改变量名称。这一问题,反映在必须保证接口稳定的WIN32 API上,更为棘手。"
p31.
"几乎所有现代C/C++编译器在处理内存中的数据结构以及sizeof运算符时,默认情况下,都会把类或结构占用的空间大小在8字节边界处对齐,以优化代码的执行速度。
可以通过预编译命令 #pragma pack (1)来取消这种默认对齐"
p42.
"定义和实际存储相关的数据结构时,最好不要使用int这种"可变长"的数据类型——int在16位、32位、64位计算机上的字节长度是不同的——相反,使用诸如DWORD这样的定长类型是个不错的选择。"
p66.
"assert()宏仅在NDEBUG宏无效的情况下才发挥作用,即若定义了NDEBUG宏(软件的releass版本),则assert()宏相当于空语句;若未定义NDEBUG宏(Debug版本),则assert检查参数,参数为假时,输出错误信息并终止程序。
assert()宏的最大问题是其在软件的release版本中将变为空语句,不起任何作用。
因此,不要在assert()中写入任何影响程序运行状态的语句,如assert(fp=fopen()),这种用法是错误的。
另外,对于外部参数(用户输入)不应该用assert()宏来检查有效性,assert()宏应用来检查内部参数(确定因素)。
MFC中特别提供了一个VERIFY宏,除了能完成assert()的验证功能外,其最大的特点是无论在Debug版还是Release版本中,都永远有效。"
p91.
"面向对象编程中不容忽视的一个问题:类的构造函数是没有返回值的。
这个特点使得如果在构造函数中进行资源分配,就必须采取一定办法将分配失败的情况通知调用者,否则就有可能造成内存访问异常。
解决方法通常有两种:
一是干脆不在构造函数中进行资源分配,而是在类中实现Initialize()和Uninitialize(),由这两个函数负责资源的释放和分配,返回值类型为bool。
二是利用对象的异常处理机制,当构造函数发生分配错误时,就跑出异常,一旦捕获异常,就不进行后续的工作。"
p131.
"属性是一种高级的面向对象特征,它与成员变量、方法一样,是编写类库或组件的常用方法。
属性的最大优点在于保证数据机器相关操作的完整和统一。"
成员变量易于定义比较单纯的数据元素,方法适于实现功能操作,属性则用于定义与某些功能操作关系紧密的元素。 "
p172.
"sendmessage()这个API的功能被定义为向窗口发送消息,并调用目标窗口的窗口过程函数来处理该消息,直到消息被处理完前函数保持阻塞状态。
postmessage()的功能与sendmessage()类似,区别在于postmessage()在将消息放入目标窗口的消息队列后立即返回,即是非阻塞的。"
p175.
"黑板擦问题
不应该将执行耗时操作的代码放置在需要负责处理用户消息的窗口线程中。"
p236.
" 版本控制的最重要目标和原则就是尽量避免不同版本代码中的重复内容,因为重复意味着重复工作,意味着重复错误。
而为了避免重复,应当将代码中共用的部分尽量提取出来,并且尽量让同一功能的代码集中在同一代码文件中。"
p246.
"全面质量管理(TQM:Total Quality Management)
p235
"被测实现(IUT:Implementation Under Testing)
测试中最重要的概念和原理是:
1.测试无法证明被测实现(IUT)的正确性。
2.测试只能证明被测实现(IUT)中包含错误。
p309.
"好的测试都是自动测试。测试计划和测试用例由人设计,但实际的测试操作确实由程序或者自动化工具完成的。
好的测试都是基于模型的。
最常用的测试模型包括组合模型和面向对象模型。"
p366.
"使用面向对象语言不等于基于面对对象的思想设计和开发软件。
面向对象设计(OOD)的基础是面向对象分心(OOA)。
面向对象分析的关键侍从应用中抽象出操作和数据的统一体。
面向对象分析的结果应该用UML(Unified Modeling Language)语言来描述。
UML只是一种描述模型的标准语言,而不是一种面向对象的分析方法。
无论我们使用和何种面向对象的分析方法,最终模型化的结果应该用UML语言来描述,因为这是面向对象世界的通用语言。"
p374.
"简化设计和增强复用性,这两条原则在软件的总体设计中至关重要。"
p15.
"将void,int,float等基本数据类型通过typedef重新命名,可以在最大程度上保证代码的可移植性——例如从16位程序至32位程序的移植问题即可通过此方法简单解决。
例如WIN32 SDK中大量出现的UINT ,DWORD等定义均属此列。
"
p18.
"匈牙利命名法存在很多严重的问题,其中之一是:一旦要修改变量类型,也就必须同时修改变量名称。这一问题,反映在必须保证接口稳定的WIN32 API上,更为棘手。"
p31.
"几乎所有现代C/C++编译器在处理内存中的数据结构以及sizeof运算符时,默认情况下,都会把类或结构占用的空间大小在8字节边界处对齐,以优化代码的执行速度。
可以通过预编译命令 #pragma pack (1)来取消这种默认对齐"
p42.
"定义和实际存储相关的数据结构时,最好不要使用int这种"可变长"的数据类型——int在16位、32位、64位计算机上的字节长度是不同的——相反,使用诸如DWORD这样的定长类型是个不错的选择。"
p66.
"assert()宏仅在NDEBUG宏无效的情况下才发挥作用,即若定义了NDEBUG宏(软件的releass版本),则assert()宏相当于空语句;若未定义NDEBUG宏(Debug版本),则assert检查参数,参数为假时,输出错误信息并终止程序。
assert()宏的最大问题是其在软件的release版本中将变为空语句,不起任何作用。
因此,不要在assert()中写入任何影响程序运行状态的语句,如assert(fp=fopen()),这种用法是错误的。
另外,对于外部参数(用户输入)不应该用assert()宏来检查有效性,assert()宏应用来检查内部参数(确定因素)。
MFC中特别提供了一个VERIFY宏,除了能完成assert()的验证功能外,其最大的特点是无论在Debug版还是Release版本中,都永远有效。"
p91.
"面向对象编程中不容忽视的一个问题:类的构造函数是没有返回值的。
这个特点使得如果在构造函数中进行资源分配,就必须采取一定办法将分配失败的情况通知调用者,否则就有可能造成内存访问异常。
解决方法通常有两种:
一是干脆不在构造函数中进行资源分配,而是在类中实现Initialize()和Uninitialize(),由这两个函数负责资源的释放和分配,返回值类型为bool。
二是利用对象的异常处理机制,当构造函数发生分配错误时,就跑出异常,一旦捕获异常,就不进行后续的工作。"
p131.
"属性是一种高级的面向对象特征,它与成员变量、方法一样,是编写类库或组件的常用方法。
属性的最大优点在于保证数据机器相关操作的完整和统一。"
成员变量易于定义比较单纯的数据元素,方法适于实现功能操作,属性则用于定义与某些功能操作关系紧密的元素。 "
p172.
"sendmessage()这个API的功能被定义为向窗口发送消息,并调用目标窗口的窗口过程函数来处理该消息,直到消息被处理完前函数保持阻塞状态。
postmessage()的功能与sendmessage()类似,区别在于postmessage()在将消息放入目标窗口的消息队列后立即返回,即是非阻塞的。"
p175.
"黑板擦问题
不应该将执行耗时操作的代码放置在需要负责处理用户消息的窗口线程中。"
p236.
" 版本控制的最重要目标和原则就是尽量避免不同版本代码中的重复内容,因为重复意味着重复工作,意味着重复错误。
而为了避免重复,应当将代码中共用的部分尽量提取出来,并且尽量让同一功能的代码集中在同一代码文件中。"
p246.
"全面质量管理(TQM:Total Quality Management)
p235
"被测实现(IUT:Implementation Under Testing)
测试中最重要的概念和原理是:
1.测试无法证明被测实现(IUT)的正确性。
2.测试只能证明被测实现(IUT)中包含错误。
p309.
"好的测试都是自动测试。测试计划和测试用例由人设计,但实际的测试操作确实由程序或者自动化工具完成的。
好的测试都是基于模型的。
最常用的测试模型包括组合模型和面向对象模型。"
p366.
"使用面向对象语言不等于基于面对对象的思想设计和开发软件。
面向对象设计(OOD)的基础是面向对象分心(OOA)。
面向对象分析的关键侍从应用中抽象出操作和数据的统一体。
面向对象分析的结果应该用UML(Unified Modeling Language)语言来描述。
UML只是一种描述模型的标准语言,而不是一种面向对象的分析方法。
无论我们使用和何种面向对象的分析方法,最终模型化的结果应该用UML语言来描述,因为这是面向对象世界的通用语言。"
p374.
"简化设计和增强复用性,这两条原则在软件的总体设计中至关重要。"
p15.
"将void,int,float等基本数据类型通过typedef重新命名,可以在最大程度上保证代码的可移植性——例如从16位程序至32位程序的移植问题即可通过此方法简单解决。
例如WIN32 SDK中大量出现的UINT ,DWORD等定义均属此列。
"
p18.
"匈牙利命名法存在很多严重的问题,其中之一是:一旦要修改变量类型,也就必须同时修改变量名称。这一问题,反映在必须保证接口稳定的WIN32 API上,更为棘手。"
p31.
"几乎所有现代C/C++编译器在处理内存中的数据结构以及sizeof运算符时,默认情况下,都会把类或结构占用的空间大小在8字节边界处对齐,以优化代码的执行速度。
可以通过预编译命令 #pragma pack (1)来取消这种默认对齐"
p42.
"定义和实际存储相关的数据结构时,最好不要使用int这种"可变长"的数据类型——int在16位、32位、64位计算机上的字节长度是不同的——相反,使用诸如DWORD这样的定长类型是个不错的选择。"
p66.
"assert()宏仅在NDEBUG宏无效的情况下才发挥作用,即若定义了NDEBUG宏(软件的releass版本),则assert()宏相当于空语句;若未定义NDEBUG宏(Debug版本),则assert检查参数,参数为假时,输出错误信息并终止程序。
assert()宏的最大问题是其在软件的release版本中将变为空语句,不起任何作用。
因此,不要在assert()中写入任何影响程序运行状态的语句,如assert(fp=fopen()),这种用法是错误的。
另外,对于外部参数(用户输入)不应该用assert()宏来检查有效性,assert()宏应用来检查内部参数(确定因素)。
MFC中特别提供了一个VERIFY宏,除了能完成assert()的验证功能外,其最大的特点是无论在Debug版还是Release版本中,都永远有效。"
p91.
"面向对象编程中不容忽视的一个问题:类的构造函数是没有返回值的。
这个特点使得如果在构造函数中进行资源分配,就必须采取一定办法将分配失败的情况通知调用者,否则就有可能造成内存访问异常。
解决方法通常有两种:
一是干脆不在构造函数中进行资源分配,而是在类中实现Initialize()和Uninitialize(),由这两个函数负责资源的释放和分配,返回值类型为bool。
二是利用对象的异常处理机制,当构造函数发生分配错误时,就跑出异常,一旦捕获异常,就不进行后续的工作。"
p131.
"属性是一种高级的面向对象特征,它与成员变量、方法一样,是编写类库或组件的常用方法。
属性的最大优点在于保证数据机器相关操作的完整和统一。"
成员变量易于定义比较单纯的数据元素,方法适于实现功能操作,属性则用于定义与某些功能操作关系紧密的元素。 "
p172.
"sendmessage()这个API的功能被定义为向窗口发送消息,并调用目标窗口的窗口过程函数来处理该消息,直到消息被处理完前函数保持阻塞状态。
postmessage()的功能与sendmessage()类似,区别在于postmessage()在将消息放入目标窗口的消息队列后立即返回,即是非阻塞的。"
p175.
"黑板擦问题
不应该将执行耗时操作的代码放置在需要负责处理用户消息的窗口线程中。"
p236.
" 版本控制的最重要目标和原则就是尽量避免不同版本代码中的重复内容,因为重复意味着重复工作,意味着重复错误。
而为了避免重复,应当将代码中共用的部分尽量提取出来,并且尽量让同一功能的代码集中在同一代码文件中。"
p246.
"全面质量管理(TQM:Total Quality Management)
p235
"被测实现(IUT:Implementation Under Testing)
测试中最重要的概念和原理是:
1.测试无法证明被测实现(IUT)的正确性。
2.测试只能证明被测实现(IUT)中包含错误。
p309.
"好的测试都是自动测试。测试计划和测试用例由人设计,但实际的测试操作确实由程序或者自动化工具完成的。
好的测试都是基于模型的。
最常用的测试模型包括组合模型和面向对象模型。"
p366.
"使用面向对象语言不等于基于面对对象的思想设计和开发软件。
面向对象设计(OOD)的基础是面向对象分心(OOA)。
面向对象分析的关键侍从应用中抽象出操作和数据的统一体。
面向对象分析的结果应该用UML(Unified Modeling Language)语言来描述。
UML只是一种描述模型的标准语言,而不是一种面向对象的分析方法。
无论我们使用和何种面向对象的分析方法,最终模型化的结果应该用UML语言来描述,因为这是面向对象世界的通用语言。"
p374.
"简化设计和增强复用性,这两条原则在软件的总体设计中至关重要。"