[编程好习惯] 屏蔽编程语言特性
来源:李云 责任编辑:栏目编辑 发表时间:2013-07-02 06:12 点击:次
定义数组是做软件开发经常需要用到的最基本的编程语言功能之一,下面示例了采用数组保存一个会话ID的一段简化代码。
如果仔细观察将能发现上面的示例代码中存在的一个bug,这个bug是当_length的值的大小刚好是SESSION_ID_LEN_MAX,即246时,就会造成数组写越界。为了修复这一bug,可能会采用以下的方法。其中改动的出发点是判断当_length的大小为SESSION_ID_LEN_MAX时,让程序返回错误。
这段代码从功能上来说没有任何的问题,但其中存在一个可维护性的问题。这个问题就是改动后的“>=”造成的。
先抛开编程语言的语法,如果某个数学变量的最大值是Y,那么Y是这个变量的有效值吗?笔者的理解是:这个值应当是变量的有效取值。现在回头看一看前面的改动,其中将最大值当作是一个无效的取值,这显然违背了通常意义上对最大值的理解。
为什么要指出这个“小小”的最大值问题呢?要知道一个好的编程习惯应尽可能地让所编写的程序的语义不会与读者的常识相悖。对于上面更改后的代码,当程序的读者读到“>=”时,很可能停下来思考一下“为什么不能等于最大值呢?”。可以想象到的是,读者得查看一下g_SessionId数组的大小是多少,然后“哦,这是因为数组的大小是SESSION_ID_LEN_MAX,但数组的定义将字符串中的结束符‘\0’也计算在内的,所以_length的大小不能等于SESSION_ID_LEN_MAX,否则,最后的那个结束符没有地方放了”。
前面的程序所存在的一根本问题是将通常的公共语言与编程语言揉在了一起,从而造成所编写出来的程序不容易理解,进而有可能造成维护上的麻烦。试想想,SESSION_ID_LEN_MAX应当包括最后的那个结束符吗?我认为不应当包括,最后的结束符是从C语言的层面去看而存在的。那如何对程序做进一步的更改,从而提高可读(维护)性呢?下面是推荐的更好方法。
#define SESSION_ID_LEN_MIN 1
#define SESSION_ID_LEN_MAX 256
char g_SessionId [SESSION_ID_LEN_MAX];
int save_session_id (char *_session_id, int _length)
{
if (_length < SESSION_ID_LEN_MIN ||
_length > SESSION_ID_LEN_MAX) {
return ERROR;
}
memcpy (g_SessionId, _session_id, _length);
g_SessionId [_length] = '\0';
return SUCCESS;
}
#define SESSION_ID_LEN_MAX 256
char g_SessionId [SESSION_ID_LEN_MAX];
int save_session_id (char *_session_id, int _length)
{
if (_length < SESSION_ID_LEN_MIN ||
_length > SESSION_ID_LEN_MAX) {
return ERROR;
}
memcpy (g_SessionId, _session_id, _length);
g_SessionId [_length] = '\0';
return SUCCESS;
}
如果仔细观察将能发现上面的示例代码中存在的一个bug,这个bug是当_length的值的大小刚好是SESSION_ID_LEN_MAX,即246时,就会造成数组写越界。为了修复这一bug,可能会采用以下的方法。其中改动的出发点是判断当_length的大小为SESSION_ID_LEN_MAX时,让程序返回错误。
#define SESSION_ID_LEN_MIN 1
#define SESSION_ID_LEN_MAX 256
char g_SessionId [SESSION_ID_LEN_MAX];
int save_session_id (char *_session_id, int _length)
{
if (_length < SESSION_ID_LEN_MIN ||
_length >= SESSION_ID_LEN_MAX) {
return ERROR;
}
memcpy (g_SessionId, _session_id, _length);
g_SessionId [_length] = '\0';
return SUCCESS;
}
#define SESSION_ID_LEN_MAX 256
char g_SessionId [SESSION_ID_LEN_MAX];
int save_session_id (char *_session_id, int _length)
{
if (_length < SESSION_ID_LEN_MIN ||
_length >= SESSION_ID_LEN_MAX) {
return ERROR;
}
memcpy (g_SessionId, _session_id, _length);
g_SessionId [_length] = '\0';
return SUCCESS;
}
这段代码从功能上来说没有任何的问题,但其中存在一个可维护性的问题。这个问题就是改动后的“>=”造成的。
先抛开编程语言的语法,如果某个数学变量的最大值是Y,那么Y是这个变量的有效值吗?笔者的理解是:这个值应当是变量的有效取值。现在回头看一看前面的改动,其中将最大值当作是一个无效的取值,这显然违背了通常意义上对最大值的理解。
为什么要指出这个“小小”的最大值问题呢?要知道一个好的编程习惯应尽可能地让所编写的程序的语义不会与读者的常识相悖。对于上面更改后的代码,当程序的读者读到“>=”时,很可能停下来思考一下“为什么不能等于最大值呢?”。可以想象到的是,读者得查看一下g_SessionId数组的大小是多少,然后“哦,这是因为数组的大小是SESSION_ID_LEN_MAX,但数组的定义将字符串中的结束符‘\0’也计算在内的,所以_length的大小不能等于SESSION_ID_LEN_MAX,否则,最后的那个结束符没有地方放了”。
前面的程序所存在的一根本问题是将通常的公共语言与编程语言揉在了一起,从而造成所编写出来的程序不容易理解,进而有可能造成维护上的麻烦。试想想,SESSION_ID_LEN_MAX应当包括最后的那个结束符吗?我认为不应当包括,最后的结束符是从C语言的层面去看而存在的。那如何对程序做进一步的更改,从而提高可读(维护)性呢?下面是推荐的更好方法。
#define SESSION_ID_LEN_MIN&n
相关新闻>>
- 发表评论
-
- 最新评论 更多>>