LK’s CodingStyle Notes(4-6)

 
Chapter 4: Naming 命名
 
重申一下,c是异常强大的语言(膜拜orz…),所以请对你的命名原则负责了,别像Modula-2 和 Pascal 程序员那样把变量变得太可爱了,像这样“ThisVariableIsATemporaryCounter”的名字,最好还是杜绝长字符命名了吧。事实上,在C程序员的习惯上,完全是可以写成“tmp”就好了。写成这样的目的是读写方便,不会晦涩难懂,毕竟谁都知道tmp就是Temporary的简写来着。
无论如何,混乱的命名都会让你皱眉头的,所以,在全局命名的问题上,必须加上适当的描述。

例如你有一个函式是"计算活跃用户数目",就可以写成这样:count_active_users(),别写成了cntusr()。
对在函式上加上类型描述是非常损害脑部的(类似匈牙利命名法…我以前还挺推崇的,这是Microsoft的官方指定命名规则~~),作者说这种命名法只会让人们感到混乱。他老人家还说,No wonder MicroSoft makes buggy programs.

局部变量的命名,必须短小精悍,把握重点。例如,如果你有一个整形变量的计数器,那么你只要把它命名为“i”就可以了。其实在局部变量中,没有必要写的过于复杂,如果对于上下文没有阅读障碍的话,把它叫做“loop_counter”是没有建设性的。

ps 如果你担心你把这些变量给弄混了,那就有另一个麻烦了,这就是“函数生长激素不均综合征”(function-growth-hormone-imbalance)…


=============================================
Chapter 5: Typedefs 类型定义

不要把类型定义命名类似"vps_t"。
如果在代码里看到
vps_t a;
天知道你的vps_t是什么鬼东西。

对比一下,如果是这样的。
struct virtual_container *a;
这样你就知道,哦,原来a是一个结构体指针。

大部分的人都认为类型定义是帮助可读性的,但是事实上并不是这样(即使你这样认为),它有以下几个用途:

(a) 很多时候被用于隐藏对象。例如,"pte_t",对于这个隐藏对象你就可以使用适当的存取函数了。

(b) 清除整型。这个抽象概念帮助消除混乱,不管是对于"long"还是"int"。例如u8/u16/u32(无符号x位整型变量),都是很好的类型定义方法。
    注意:这些都是有原因的,因为类似"unsigned long"这样的定义,没有理由让它变成
        typedef unsigned long myflags_t;
    但如果它有一个清晰的理由去解释为什么在某些情况下使用“unsigned long”,或者根据其它的配置可能让它定义为“unsigned long”,那么就得使用一切的手段在前面使用typedef.
    这里我想到Microsoft使用匈牙利命名法对于类型的定义,混乱的局面就很清晰的浮现出脑海了。

(c) 当你给类型检查使用稀疏文件(多线程下载经常用到)逐字的创建一个新类型的时候。

(d) 在某些情况下,以标准c99类型,新类型是相同的。(新标准出来后,使程序可以向上兼容)

(e) 用户空间的类型安全。固定的结构体对于用户空间是可见的,我们不能要求c99类型也不能让u32跑到类型定义前面去。因此,我们在共享用户空间上使用__u32或者类似的类型。

或许还有其它的案例让你使用类型定义,但是规则基本上都没有永久固定的要求你怎么去使用typedef,除非你可以非常清楚的和规则相匹配…

=============================================
Chapter 6: Functions 函数

函数应该是简短而甜蜜的,而且只做一件事情。我们知道ISO/ANSI屏幕大小为80×24,所以,函数一般只做一件事情并且要做好!
最大长度的函数对于其复杂性和排版等级是成反比的。因此,如果你有一个简单的函数,但是它有一个很长的事件语句(例如switch case),每个时间都处理不同的小事情。如果这样的话,那使用很大长度的函数是可以的。

无论如何,如果你有一个复杂的方法,而且你认为一个没有什么天赋的高中一年级学生可能不能明白这个函数是干什么用的,这时候你应该坚持“接近最大的限度”。对名字描述使用助手(如果你觉得执行危险,你可以告诉编译器把它们inline掉,这有利于你更好的完成工作)。

另外,数数你函数里的局部变量,它们不应该超过5-10个。它们如果发生了什么错误的话,重新审视一下你的函数,把它们分解成更小的部分(或者再写一个函数)。
人类的大脑大概可以同时跟踪7件不同的事情,更多了就会感觉到糊涂了,所以,变量定义的能少则少。

源码中,不同的函数之间应该用一个空行隔离开。
如果函数具有返回值,那么在这之后的宏中,应该紧贴上一个函数的尾部。
例如这样:
int system_is_up(void)
{
    return system_state == SYSTEM_RUNNING;
}
EXPORT_SYMBOL(system_is_up);

在函数的原型中应该包含了参数的名称和具有类型。
虽然这在C中是不要求的,这是为了Linux的完美。因为,这是一条简单的方法去给读者们(Linux内核阅读者)增加一些有用的信息。

                                                                     mrzenix post at 2008-7-24

Tags: , ,

打开了评论功能,但是需要被审核,所以请耐心等待。