千万不要把 bool 当成函数参数

2013-12-13  来源:本站原创  分类:管理  人气:1 

我们有很多Coding Style 或 代码规范。但这一条可能会经常被我们所遗忘,就是我们经常会在函数的参数里使用bool参数,这会大大地降低代码的可读性。不信?我们先来看看下面的代码。

当你读到下面的代码,你会觉得这个代码是什么意思?


1

widget->repaint(false);

是不要repaint吗?还是别的什么意思?看了文档后,我们才知道这个参数是immediate, 也就是说,false代表不立即重画,true代码立即重画。

Windows API中也有这样一个函数:InvalidateRect,当你看到下面的代码,你会觉得是什么意思?


1

InvalidateRect(hwnd, lpRect, false);

我们先不说InvalidateRect这个函数名取得有多糟糕,我们先说一下那个false参数?invalidate意为“让XXX无效”,false是什么意思?双重否定?是肯定的意思?如果你看到这样的代码,你会相当的费解的。于是,你要去看一下文档,或是InvalidateRect的函数定义,你会看到那个参数是 BOOL bErase,意思是,是否要重画背景。

这样的事情有很多,再看下面的代码,想把str中的”%USER%”替换成真实的用户名:


1

str.replace("%USER%", user, false); // Qt 3

TNND,那个false是什么意思?不替换吗?还是别的什么意思,看了文档才知道,false代码大小写不敏感的替换。

其实,如果你使用枚举变量/常量,而不是bool变量,你会让你的代码更易读,如:


1

2

3

4

5

6

widget->repaint(PAINT::immediate);

widget->repaint(PAINT::deffer);

InvalidateRect(hwnd, lpRect, !RepantBackground);

str.replace("%USER%", user, Qt::CaseInsensitive); // Qt 4

如果对这个事不以为然的话,我们再来看一些别的示例,你不妨猜猜看看下面的代码:


1

component.setCentered(true, false);

这什么玩意儿啊?看了文档你才知道,这原来是 setCentered(centered, autoUpdate);


1

new Textbox(300, 100, false, true);

这又是什么啊?看了文档才知道,这是创建一个文本框,第三个参数是是否要滚动条,第四个是是否要自动换行。TNND。

上面的情况还不算最差,看看下面的双重否定。


1

2

component.setDisabled(false);

filter.setCaseInsensitive(false)

再来一个,如果你读到下面的代码,相信你会和我一样,要么石化了,要么凌乱了。


1

2

event.initKeyEvent("keypress", true, true, null, null,

false, false, false, false, 9, 0);

看完这篇文章,我希望你再也不要把bool为作为函数参数了。除非两个原因:

  1. 你100%确认不会带来阅读上的问题,比如Java的 setVisible (bool).
  2. 你100%确认你想去写出无法维护很难阅读的代码。

【更新2011/9/8】当然,别的参数也会有一样的问题,比如:new Textbox(300, 100, false, true);中的300 和 100,不知道是坐标还是长宽,只不过,一般长度或坐标这样的参数都不会被hard code,都会有变量名,而bool这种参数经常性地被传成true 和 false。 bool参数表现得更为明显一些罢了。

所以,程序中不要出现magic number,true/false 也是一种 magic number

最后,如果你想设计一个好的API,强烈推荐你读一下Nokia的Qt的《API Design Principles》,本文就是其中的“Boolean Trap”。

相关文章
  • 千万不要把 bool 当成函数参数 2013-12-13

    我们有很多Coding Style 或 代码规范.但这一条可能会经常被我们所遗忘,就是我们经常会在函数的参数里使用bool参数,这会大大地降低代码的可读性.不信?我们先来看看下面的代码. 当你读到下面的代码,你会觉得这个代码是什么意思? 1 widget->repaint(false); 是不要repaint吗?还是别的什么意思?看了文档后,我们才知道这个参数是immediate, 也就是说,false代表不立即重画,true代码立即重画. Windows API中也有这样一个函数:Invali

  • bool当成函数参数错误理解 2014-10-23

    经常会在函数的参数里使用bool参数,这会大大地降低代码的可读性 我们有很多 Coding Style 或 代码规范. 但这一条可能会经常被我们所遗忘,就是我们 经常会在函数的参数里使用bool参数,这会大大地降低代码的可读性. 不信?我们先来看看下面的代码. 当你读到下面的代码,你会觉得这个代码是什么意思? widget->repaint(false);是不要 repaint 吗?还是别的什么意思? 看了文档后,我们才知道这个参数是 immediate,也就是说,false 代表不立即重画,t

  • Python函数参数类型*.**的区别 2014-07-12

    这篇文章主要介绍了Python函数参数类型*.**的区别,本文用实例讲解它们的区别,并讲解了闭包的相关知识,需要的朋友可以参考下 刚开始学习python,python相对于java确实要简洁易用得多.内存回收类似hotspot的可达性分析, 不可变对象也如同java得Integer类型,with函数类似新版本C++的特性,总体来说理解起来比较轻松.只是函数部分参数的"*"与"**",闭包等问题,着实令人迷糊了一把,弄清概念后写下此文记录下来,也希望本文能够帮助其他初

  • JavaScript String.replace函数参数实例说明 2015-01-07

    JavaScript String.replace函数作用是将源自符串中的match替换为replacement并返回替换后的字符串,使用介绍如下,不会的朋友可以了解下哈 Email:longsu2010 at yeah dot net js String的replace函数的函数签名如下: replace(match/* 字符串OR正则表达式 */, replacement/* 字符串OR函数 */) 作用是将源自符串中的match替换为replacement并返回替换后的字符串. 如果第一参

  • [转][C/C++]函数参数的入栈顺序 2014-07-02

    #include <iostream> #include <cstdio> void foo(int x, int y, int* z) { printf("x = %d at [0x%x]\n", x, &x); printf("y = %d at [0x%x]\n", y, &y); printf("z = 0x%x at [0x%x]\n", z, &z); } int main(int ar

  • C++函数参数取默认值的深入详解 2013-10-02

    本篇文章是对C++中函数参数取默认值进行了详细的分析介绍,需要的朋友参考下 一般情况下,在函数调用时形参从实参那里取得值,因此实参的个数应与形参相同.有时多次调用同一函数时用同样的实参,C++提供简单的处理办法,给形参一个默认值,这样形参就不必一定要从实参取值了.如有一函数声明 float area(float r=6.5); 指定r的默认值为6.5,如果在调用此函数时,确认r的值为6.5,则可以不必给出实参的值,如 area( ); //相当于area(6.5); 如果不想使形参取此默认值,则

  • PowerShell中对函数参数的命名建议 2013-11-14

    这篇文章主要介绍了PowerShell中对函数参数的命名建议,本文罗列了PowerShell中的一些参数名称,用来给参数命名时做一参考,需要的朋友可以参考下 PowerShell自定义函数的参数没有具体的命名规则,那么怎么做才能让参数的命名更加科学可持续. 我们应该怎么来命名函数的参数名称呢?有没有一个可供参考的列表?当然微软没有给出来.但是我们可以来理一个列表出来.微软自带了大量的cmdlet,这些cmdlet使用的参数有什么规律呢?我们用下面一段命令来统计一下. Get-Command -C

  • c++将引用或者是指针作为函数参数实现实参的运算 2014-01-08

    这篇文章主要介绍了c++将引用或者是指针作为函数参数实现实参的运算,需要的朋友可以参考下 C++增加引用类型, 主要是把它作为函数参数,以扩充函数传递数据的功能,较指针参数来得更加安全直观.将引用作为参数传递的时候,实参初始化形参的时候不分配内存空间,也不调用拷贝构造函数,因此更加能够提高运算的性能.所以我们应该尽可能地使用引用,而非指针,但是应该要注意,因为局部变量具有自己短暂的生命周期,因此不能够返回对一个局部变量的引用. 引用通常是在被定义的时候被初始化,但是当它作为参数的时候,则是在被调

  • javascript获取函数名称.函数参数.对象属性名称的代码实例 2014-01-13

    这篇文章主要介绍了javascript获取函数名称.函数参数.对象属性的代码实例,需要的朋友可以参考下 一.获取函数名称的3种实现方法 实例1: 在js权威指南中看到的一个方法: Function.prototype.getName = function(){ return this.name || this.toString().match(/function\s*([^(]*)\(/)[1] } 实例2: 如果当前函数是有名函数,则返回其名字,如果是匿名函数则返回被赋值的函数变量名,如果是闭

  • PowerShell定义函数参数的2种方法和传参方法实例 2014-02-24

    这篇文章主要介绍了PowerShell定义函数参数的2种方法和使用方法实例,简洁易懂的好文,需要的朋友可以参考下 本文介绍PowerShell自定义函数定义参数的两种方法,一种是将参数列表放到函数名之后,就跟其它语言定义函数参数一样:另一种则是PowerShell独有的方式,那就是使用param关键词. 先来看看第一种定义参数的方式--将参数列表放到函数名之后 举个例子先看看: function Test-Function($参数名1='默认参数值1', $参数名2='默认参数值2') { Wr

  • 解析sizeof, strlen, 指针以及数组作为函数参数的应用 2014-03-16

    本篇文章是对sizeof, strlen, 指针以及数组作为函数参数的应用进行了详细的分析介绍,需要的朋友参考下 代码如下所示: typedef struct st_test { int id; char *pName; char class[10]; }Student; void fn(Student *pStud) { pStud->id = 10; pStud->pName = "Tom Simith"; strcpy(pStud->class, "C

  • JavaScript 函数参数是传值(byVal)还是传址(byRef) 分享 2014-03-23

    这篇文章主要介绍了在JS中函数参数是传值(byVal)还是传址(byRef)的误区我们通过实例说明一下,有需要的朋友可以参考 对于"JavaScript 函数参数是传值(byVal)还是传址(byRef)"这个问题,普遍存在一个误区:number,string等"简单类型"是传值,Number, String, Object, Array等"复杂类型"是传址. 这样不对吗?为什么会有这样的误区?看一下这两段代码: //造成传值假象的代码 func

  • 关于数组做函数参数的问题集合汇总 2014-03-26

    本文是对关于数组做函数参数的问题进行了详细的汇总,需要的朋友可以过来参考下.希望对大家有所帮助 首先是数组元素作为函数的实参,这和直接用多个变量作为函数的实参在用法上没有什么差别. 作为例子的代码: #include<iostream> using namespace std; int main(){ int max(int a,int b); int a[2],m; a[0]=1; a[1]=2; m=max(a[0],a[1]); cout<<m; return 0; } in

  • JavaScript函数参数使用带参数名的方式赋值传入的方法 2014-05-15

    这篇文章主要介绍了JavaScript函数参数使用带参数名的方式赋值传入的方法,实例分析了javascript函数传递参数的使用技巧,具有一定参考借鉴价值,需要的朋友可以参考下 本文实例讲述了JavaScript函数参数使用带参数名的方式赋值传入的方法.分享给大家供大家参考.具体分析如下: 这里其实就是在给函数传递参数的时候,可以使用 参数名:参数值的方式传递,这样不会传递错.不过下面的代码是通过字典来实现的,不像python原封就支持这样的方法 function foo({ name:name

  • 结构体类型数据作为函数参数(三种方法) 2014-06-22

    将一个结构体中变量中的数据传递给另一个函数,有以下三种方法.需要的朋友可以过来参考下,希望对大家有所帮助 (1)用结构体变量名作为参数. #include<iostream> #include<string> using namespace std; struct Student{ string name; int score; }; int main(){ Student one; void Print(Student one); one.name="千手";

  • PowerShell函数参数指定数据类型实例 2014-07-05

    这篇文章主要介绍了PowerShell函数参数指定数据类型实例,即强制参数的数据类型例子,需要的朋友可以参考下 本文介绍在PowerShell创建自定义函数时,为必选参数设置强类型有什么好处,应该如何设置. 为了提高必选参数的安全性,PowerShell函数定义的最佳实践告诉我们,要为必选参数设置强类型.这是为什么呢,我们来看一个例子. function Test-Me { param ( [Parameter(Mandatory=$true, HelpMessage='Enter number

  • c++将数组名作为函数参数对数组元素进行相应的运算 2014-07-07

    这篇文章主要介绍了c++将数组名作为函数参数对数组元素进行相应的运算,需要的朋友可以参考下 用数组名做函数参数与用数组元素作实参有几点不同: (1)用数组元素作实参时,只要数组类型和函数的形参变量的类型一致,那么作为下标变量的数组元素的类型也和函数形参变量的类型是一致的.因此,并不要求函数的形参也是下标变量.换句话说,对数组元素的处理是按普通变量对待的.用数组名作函数参数时,则要求形参和相应的实参都必须是类型相同的数组,都必须有明确的数组说明.当形参和实参两者类型不一致时,将会发生错误. (2)

  • PowerShell函数参数使用智能提示功能例子 2014-08-17

    这篇文章主要介绍了PowerShell函数参数使用智能提示功能例子,这个功能一般需要在PowerShell集成开发环境ISE中才会显示智能提示,需要的朋友可以参考下 本文介绍在自定义PowerShell函数时,如何设置函数可以智能提示参数值.参数值的智能提示这个功能是在PowerShell 3.0中出现的新功能. 在PowerShell 3.0版本中,出现了一项新的功能,那就是参数值的智能提示.当然,不是随便在哪里都会智能提示参数值,而是只能在ISE中.当然,所谓的ISE就是PowerShell

  • Shell 函数参数 2014-10-16

    这篇文章主要为大家分享了Shell 函数参数,方便学习shell脚本的朋友 在shell中,调用函数时可以向其传递参数.在函数体内部,通过 $n 的形式来获取参数的值,例如,$1表示第一个参数,$2表示第二个参数... 带参数的函数示例: #!/bin/bash funWithParam(){ echo "The value of the first parameter is $1 !" echo "The value of the second parameter is $

  • 浅谈JavaScript函数参数的可修改性问题 2014-12-14

    这篇文章主要是对JavaScript函数参数的可修改性进行了详细的介绍,需要的朋友可以过来参考下,希望对大家有所帮助 一道笔试题思考而来的,通常情况下没人会在函数内部修改参数值.这里仅拿出来讨论,有三种方式可以修改. 1,直接修改函数声明时的形参 function f1(a) { alert(a); a = 1;//修改形参a alert(1 === a); alert(1 === arguments[0]); } f1(10); 函数f1定义了参数a,调用时传参数10,先弹出10,修改a为1,