读书人

那些条条框框真的重要么?反编码规范的

发布时间: 2012-01-15 22:57:49 作者: rapoo

那些条条框框真的重要么?反编码规范的做法的思考
今天整理文件,看到我早年写的一个编程规范的文档,随便写一点。欢迎大家讨论:

(1)对 for if while 等块结构加上花括号,无论是否只有一条语句;
(2)花括号占一行;
现在发现这两条很教条,有时候反而不利于代码的可读性。现在我倾向在每一行不超过屏幕的宽度上尽可能写多一些代码,而压缩行,使得一个方法,乃至一个类可以在一屏被显示。方块的代码比细长的更容易阅读,对比:

C# code
class Person{    public string Name    {        get;        set;    }    public int Age    {        get;        set;    }        public string Address    {        get;        set;    }    public string EMail    {        get;        set;    }    public string Phone    {        get;        set;    }        public DateTime Birthday    {        get;        set;    }    public Person()     {    }    public Person(        string name,         int age,         string address,         string email,         string phone,         DateTime birthday    )    {        Name = name;         Age = age;        Address = address;        EMail = email;        Phone = phone;         Birthday = birthday;    }}

C# code
class Person{    public string Name { get; set; }    public int Age { get; set; }    public string Address { get; set; }    public string EMail { get; set; }    public string Phone { get; set; }        public DateTime Birthday { get; set; }        public Person() { }    public Person(string name, int age, string address, string email,         string phone, DateTime birthday)    {        Name = name; Age = age; Address = address; EMail = email;        Phone = phone; Birthday = birthday;    }}


(3)避免编写过长的方法,方法体越小越好
这一条现在看来也不一定,因为过小的方法使得类的方法数过多,而方法可以单独测试,但是方法太多使得组合测试这些方法变得困难,最后过小过多的方法加大了人的理解难度,支离破碎的代码可读性更差。

随着Lambda表达式的引入,使得我们可以定义匿名方法,一个方法如果只在它内部使用,那么就不要公开,哪怕是 private 访问权限:
比如:
C# code
Func<int, int, int> IntPow = (x, y) => {               int r = x;               for (int i = 1; i < y; i++) r *= x;              return r;          }Console.WriteLine(IntPow(3, 2));


(4)使用接口降低耦合性
接口是一个很难用的东西,为了接口,我们不得不设计一个类,更糟糕的是,C#不支持匿名类实现接口,这使得接口的代码远离调用。
想象下我们经常为了排序而实现一个 ICompareable 的经历吧。

同样因为 Lambda 表达式,我们可以暴露委托代替接口,比如 OrderBy(),使用起来比 SortList 顺畅很多。

(5)使用泛型代替非泛型接口
我承认泛型有很多足够的优点,但是在设计API的时候,应该考虑使用非泛型的接口,或者保留一个兼容的非泛型版本,这样做好处很多,比如反射调用的时候,非泛型的实现简单很多,在Web Service序列化的时候也是如此。另外考虑到只有C# 4支持逆变和协变,提供向前兼容也是很必要的。

(6)注释很重要
打一个不恰当的比方,很多时候你回答csdn的问题发现,lz说了半天,不知道问什么,相反,他给出些输入输出,一看就懂了。所以,宁可多写测试用例,也不要乱写注释。不好的注释比没有注释更糟,如同2只手表不会给你带来更精确的时间,只会造成模糊。

(7)为专门的问题编写专门的算法
大多时候,Linq提供了我们需要的大部分算法——可能直观但是不直接。但是这不重要。在程序编写的初期,有很多不确定性,这时候获得可以运行和测试的代码,比起编写具体实现重要的多。自己尝试实现算法,浪费了很多时间,而且很可能发现这个功能需求修改,算法就白写了。而且自己实现的算法,可读性,可调试性很差,通用的算法基本可以假定它本身是正确的。虽然可能效率不高,也可以在后期调优的时候解决。越是细节的算法,越不重要。

(8)变量要用有意义的名字表示
随着重构工具的普及,费力想一个变量的名字越来越划不来。变量名需要慎重的地方包括:接口;可能被命名参数调用的参数;共有变量,除此之外,变量名越简单越好。

(9)关于方法重载
对于方法重载,特别要当心2点,一个是子类不正确的覆盖导致不可预料的情况,比如他们忘记调用 base.Method(),或者有的人喜欢先调用,再写覆盖的方法,有的人相反,所以NVI是一个很好的模式。另一个是特别注意在参数中使用类类型,尤其是有继承关系的类类型。
比如:
C# code
class FileSystem{    public virtual void SetInfo(FileSystemInfo info) { ... }}class Fat32FileSystem : FileSystem{    public virtual void SetInfo(Fat32FileSystemInfo info) { ... }}class class FileSystemInfo {    ...}class class Fat32FileSystemInfo : FileSystemInfo{    ...}


(10)使用聚合代替继承
这一条本身没有问题,可是因为 C# 有了扩展方法,所以应该修改为,首先考虑扩展方法,然后是聚合,最后是继承。当然,扩展方法也有一些副作用,比如当类的实现者加上了和扩展方法重名的方法,扩展方法会被忽略。比如滥用扩展方法导致代码可读性差等情况。

------解决方案--------------------


哪种规范不重要,重要的是风格保持一致,从头至尾坚持一种风格或者规范。
[解决办法]
没有规矩不能成方圆。。。这话不是没有道理的。。。
[解决办法]
除了那些让代码看起来整齐的规范应该无条件实行外,其他规范应该看效果,规范是用来解决问题的,如果没有这条规范也不会有明显的问题,就是不需要的规范,

规范是越少越好,少到刚好能够解决编程的瓶颈问题,
[解决办法]
前排支持。
[解决办法]
对你的第一条,属性和参数可以参考,但是我还是认为一行一句代码(一个分号)比较好。
[解决办法]
写得很好,支持,学习!
[解决办法]
编程之道,有常有变!
[解决办法]
小偷程序都能赚到百万的
[解决办法]
我之所以用 vim 而不用 vs 主要倒不是因为热键问题,而恰恰是排版问题。
vs 虽然可以略微设置,但排版总是不尽人意,我不喜欢那总老是自作聪明改变我的排版的编辑器。
[解决办法]
呵呵,选择适合自己的,适合团队的。 一切只是方便大家协同合作!
[解决办法]
如果是公司开发,还是要有规则的,但规则没必要那么死板。

如果是自己开发,就没有那么多条条框框了,有自己的规则就好。
[解决办法]
对于第一个,在某些情况下会产生错误的编译,我不知道 C# 中有没有这种情况存在,在 Java 中是有这种情况的:

Java code
for(int i = 0; i < 5; i++)    String str = "a";
[解决办法]
探讨
(8)变量要用有意义的名字表示
随着重构工具的普及,费力想一个变量的名字越来越划不来。变量名需要慎重的地方包括:接口;可能被命名参数调用的参数;共有变量,除此之外,变量名越简单越好。

[解决办法]
探讨
对于第一个,在某些情况下会产生错误的编译,我不知道 C# 中有没有这种情况存在,在 Java 中是有这种情况的:


Java code

for(int i = 0; i < 5; i++)
String str = "a";


为了不让编译器头晕,我建议不管一行还是多行,都得加上花括号,为了不产生歧义。

[解决办法]
至于方法体长度,我也不是很赞同,一个 main 就能完成逻辑了,那我们为什么还要分成这么多的类呢?为什么不把那几万,乃至数十万的代码写在一个类里呢?

可以看一下开源产品的源代码,在他们的代码中很多的方法体只有一行,而且还是一行委托其他类的调用。

面向对象的代码大多数都是在各种方法委托调用中完成业务逻辑的,而这些代码看上去啥都没做,只是从这是调到那里,而面向过程的代码则一眼就能看出是在做什么。既然这样那为什么不用面向过程的代码呢?

一般来说,工程中所有的代码,只要有一处的重复,那就得提炼。虽然这么说,但基本上很难做到这一点,我们只能逐步地接近。
[解决办法]
如果方法体很长,那势必会导致重复代码增加。

如果我们写的代码在完成之后就扔之大吉,那我们想咋写就咋写,但事难不以愿为,写好的代码是需要改动和维护的。

庞大的方法体会造成维护成本的增加,我不知道大家喜欢改大段的代码,还是喜欢改小段的代码?我是喜欢后者的,呵呵。
[解决办法]
探讨

哪种规范不重要,重要的是风格保持一致,从头至尾坚持一种风格或者规范。

[解决办法]
支持,不过现在的电脑屏幕越来越大,有时候断行也是有必要的,特别是字段属性名字比较长的时候,多个放在一行也不太利于阅读
同样的功能,C#比VB看起来已经舒服很多了
[解决办法]
个人不太喜欢这种方法定义,虽然在C++中很常见,总觉得容易和变量赋值混淆,用楼主的方式表达更舒服些。
C# code
 public Person(        string name,         int age,         string address,         string email,         string phone,         DateTime birthday    )
[解决办法]
对于你的最后一条,请牢记,聚合是has-a 继承是is-a 两者虽然在用法上可以互换
但是过于泛滥的聚合会导致维护性很差。
------解决方案--------------------


我记得曾经讨论过一个关于“三目运算”的例子.

C# code
//举个例子而已,别较真a>b?b:b>0?b:0
[解决办法]
C# code
class Person{    public string Name { get; set; }    public int Age { get; set; }    public string Address { get; set; }    public string EMail { get; set; }    public string Phone { get; set; }        public DateTime Birthday { get; set; }        public Person() { }    public Person(string name, int age, string address, string email, string phone, DateTime birthday)    {        Name = name;        Age = age;        Address = address;        EMail = email;        Phone = phone;        Birthday = birthday;    }}
[解决办法]
ding .
[解决办法]
java 工具 PMD 有很多值得借鉴的内容,看完那个再讨论吧
[解决办法]
微软也有 StyleCop,比 PMD 弱点
要知道考试都有卷面整洁分,看着一个穿着邋遢的人你什么感觉
规范格式除了便于阅读外,还有其他一些统计、检查工具用得着,早年作对日开发时见到一些
[解决办法]
探讨
我记得曾经讨论过一个关于“三目运算”的例子.

C# code

//举个例子而已,别较真
a>b?b:b>0?b:0


看了半天没有反应过来……
如果加上括号,逻辑就清晰多了。

C# code

(a>b)?b:((b>0)?b:0)



我不知道在代码中,各种括号会不会影响执行效率或者文件大小。
不过,因为我也不敢保证下次我还能看懂自己的逻辑。所以我坚……

[解决办法]
我会写为:
C# code
if(a>b || b>0)    x=b;else    x=0;
[解决办法]
加班?这么晚了还不睡?
来看看牛人,公司现在基本没规范
[解决办法]
这是个技术活
[解决办法]
同意1楼和2楼的意见
[解决办法]
学习 学习
[解决办法]
规范是要求,可以根据项目的实际情况制定。
[解决办法]
学习了
[解决办法]
反对,搞成什么玩意,一坨屎一样,好看吗? 除了要滚屏还有别的理由吗?
知道编译器有全屏功能么?
[解决办法]
public string Name { get; set; }
public int Age { get; set; }
public string Address { get; set; }
public string EMail { get; set; }
public string Phone { get; set; }
public DateTime Birthday { get; set; }


我比较喜欢这种写法
[解决办法]
很有参考价值

有些简单的参数检查,个人习惯用一行代码

if(...) return null;


[解决办法]
不要为了遵守规范而违背了当初制定规范的目的。
[解决办法]

还是习惯这么写

public string Name { get; set; }

public int Age { get; set; }

不过中间会留一个空行

读书人网 >C#

热点推荐