我没用过C++,所以不清楚和C++比的优劣。但Go是我见过的第一种结合C和Python的很多优点的语言,原生并行。尤其值得一提的是其interface设计及其优雅而高效,让我觉得所有程序语言都应该这样设计。Go是天生的服务器语言,但写本地程序一样很方便。
在我用过的主流语言中(C/Python/Java/Objective-C),Go是唯一一种让我觉得“程序就该这样写”的。
----------------------------------------------------------------------------------
Yours Sincerely
Kun
2011/10/21 HaoPeiQiang <HaoPe...@gmail.com>:
我当年学完OC的最大感触就是,要是Java有其一半优雅和高效就好了
我一直都是使用C语言,但是我却也很喜欢C++,喜欢面向对象。但是毕业后,由于工作都是Linux偏底层的开发,所以工作中都是C语言。
但是由于自己对C++的偏好,一直也没有放弃C++。
我个人觉得语言存在即有它的合理性,C++其实本身没有什么问题,也很好用。
它的缺点就是语法太复杂,太丰富了。不浸润个10年以上,说精通C++,纯属笑话。
而很多人并没有这个水平,滥用C++的特性和OOP的方法,结果写出来的东西根本没法维护,也很难看。
对于Scott Meyers,我认为他绝对是大师级的认为。一般的C++程序员如果能够真正理解其Effective系列的著作,写出的C++程序绝
对不会有大问题。
而C呢,正是因为其语法很简单,基本的语法和适用,一般人大概好好整个儿三五年的也很熟练了。基本上就不会犯一些愚蠢的错误。
当然C的细节其实也很多,前两天看了一遍C99标准,也找到了一些自己以前误解或者不甚清晰的地方。
下面针对楼主说的几个方面,我说说我的观点吧
1. 变量:
我以前的编程风格也是将变量放在函数入口。现在如果该变量的只是临时使用的话,我更喜欢就近定义;
2. 析构:
我还是比较喜欢C++的析构的。但是我要用它的话,基本上就是用析构去释放资源,用类封装资源的申请。
别的不说,现在我的代码中,我基本上可以保证很少有或者没有资源泄漏,可是你的同事,老的代码中呢?
以前我去检查一个内存泄漏问题,结果发现有很多处内存没有释放。检查内存泄漏固然可以用valgrind,但是它不是万能的,有时候确实需要
review代码才能找到问题。
这个工作量可不小。
3. 模板:
模板不能滥用,就如同C中的宏定义。但有时候又无法避免,那么使用模板的话,还会比宏多一些检查。
5. 类的封装:
这个东西不好说。就是一个度的把握。简单的结构,就用struct,复杂的该封装就封装。
上面是我的一些拙见,水平不高,仅供大家讨论。
最后再总结一句吧。个人认为C++语言不错,但是如果不懂其本质而滥用,写出的代码肯定没法看,但这不是C++的错。
我觉得楼主觉得C++不爽的原因,可能被一些味道不好的代码给郁闷了。
On Oct 22, 12:31 am, windstorm <likunarmstr...@gmail.com> wrote:
> Objective-C确实也挺好,但仅限于苹果平台。其实我觉得你可以去看看Rob Pike他们搞的Go。
>
> 我没用过C++,所以不清楚和C++比的优劣。但Go是我见过的第一种结合C和Python的很多优点的语言,原生并行。尤其值得一提的是其interface 设计及其优雅而高效,让我觉得所有程序语言都应该这样设计。Go是天生的服务器语言,但写本地程序一样很方便。
>
> 在我用过的主流语言中(C/Python/Java/Objective-C),Go是唯一一种让我觉得"程序就该这样写"的。
>
> --------------------------------------------------------------------------- -------
> Yours Sincerely
> Kun
>
> gplus.to/kunli
>
> 2011/10/21 HaoPeiQiang <HaoPeiQi...@gmail.com>:
>
>
>
>
>
>
>
> > 所以,你可以用Objective-C,试试吧,仍旧100%兼容C(C++不确保100%兼容C,如果你懂C++你就知道我说的啥意思),而且真的面向对象的 ,而且有一个非常棒的类库,没有C++的一切负担。
>
> > 2011/10/21 LeeoNix <leeoni...@gmail.com>
>
> >> 好久没在TopLanguage发表感慨了。唉,知道大师Dennis的去世那天,我久久盯着屏幕看。悲哀,继Dijkstra之后,又一位真正的大师走了,而 我面前所看到的虚拟的东西都源自那位大师。那天我写了不少C代码纪念大师,我认为除此之外没有其他形式值得做。
>
> >> 我很庆幸,我这半年多坚持不用C++只用纯C语言写东西。以前看云风写的Blog说C++的问题,而我也看了Eric
> >> Raymond的Unix编程艺术里面对C++的评价。一年多项目结束了,C++也用的熟的不能再熟了。可是我很多地方,真的感觉做了很多无用功。所以,我也效 仿马化腾,做出了一个艰难的决定:不用C++写东西,只用C语言。
>
> >> 而C语言好久没有用了。而从新开始用C,本来以为是简化的简单C++,用就是了。可惜我被很多C++习惯给"宠坏"了。
>
> >> 1、变量,该死的变量。
>
> >> 变量不能随意声明了,只能在花括号内声明需要的变量。可以说在C++内,变量随手写是个大优势,但碰到C编译器,它不让你过了,而且该死的编译器并没有直接告诉 我是变量的问题,而是其他的问题。起初写的一堆代码,最后发现30%编译不通过都是这个变量声明的问题。我重新审视我自己,我为什么要"随意"的声明变量?记得 和大富翁论坛的版主王昊(Soul)在某次聚餐之后,他谈到了过分依赖所谓的随缘最终变成了随便的问题,我很仔细的听他说完了这个有关禅的东西。是的,很多时候 把随意变成了随便了,我就像使用便民伞一样,随便拿了,没有还回去。无形中,其实我在做一种对编译器来说不道德的事情。
>
> >> 我用了很久的Delphi,而用Delphi的一个习惯就是变量必须在var关键字下。我一直都认为这是个好习惯,这样用C++就不会出太多问题。不过,我过于 乐观了,随意的,或者说"随便"声明的变量,根本不利于静态检查,过于依赖编译器。我花了大概1个星期多的时间,才修正了乱声明变量的习惯。而且像for
> >> (int i; i < 100: ++i)这样的i声明方式的习惯,太不容易修改了。
>
> >> 过了一阵子,一个朋友给了我一块C++代码。其实他逻辑写的不错,但是我用了一段时间C代码。看好几个随意声明的变量非常扎眼。我把变量清理到前面声明,然后发 现里面有3个变量就是随意声明的,其实作用是无意义的。早就听说过C++非常不利于"静态"检查,现在才明白。很多隐患实际就是坏习惯养成的。
>
> >> 2、析构函数,该死的析构函数。
>
> >> 我还有个坏习惯,就是听了那个Meyers的家伙,多用functor。呵呵,这是个玩笑。其实struct(class?)是个好东西,真的是个好东西,可以 在构造函数初始化,析构函数清理它。我很喜欢写一些简单的struct,在栈内存上用,可以随意return,资源什么可以被安全的被清理,不用担心遗忘什么。 注意,我又用了"随意"二字。其实......惭愧还是随便。是的虽然不担心资源了,但是大大影响了可读性,还有对返回值的检查。多个return就像筛子的洞一样。而 随意的return的根源,是我随意的使用了析构函数。
>
> >> 多个return造成很多地方都不好控制,虽然说我的重构能力还是不错的。用Extract
> >> Mothed方式很多地方都模块化了。但是多return的难维护程度超乎我想像,最初我加了goto,跳到最后去干清理的事情,没错就是那个臭名昭著的got o,后来想想goto还是算了......
>
> >> Delphi,注意,我又提到了Delphi了。呵呵。有个优势就是Result作为function的返回值被使用。其实这也是一个好习惯,有个具体存在的返 回值变量。我花了一段时间把很多乱return的地方修改了,主动声明个叫"result"的变量使用,赋值之后才根据情况return,我还把我的Lua代码 很多地方也做了类似的修改。数据的流向很容易被控制。
>
> >> 我看到别人转载的Jasone Tee写了一个文章A return to Good
> >> Code,看了英文原文才发现CSDN也翻译转载了。但可悲的是看看下面的评论,除了无聊的争吵还是无聊的争吵。看的我有个感觉,很多人就像我住的楼前的黄毛哈 巴狗一样,守着自己小小的地盘,对每一个路过的人去乱吠呢?怎么不去试试看写一些一个出口的代码试试看?
>
> >> 3、思念模板,但忍住不用。
>
> >> 3年来,我用C++期间,写了太多的模板的代码了。而且一直都感觉模板是个很好的东西,虽然现在感觉也是个好东西。但C语言没有,有的时候写比较类似的代码,弄 个模板就好了。其实是看了Stroustrup在The
> >> C++ Programming
> >> Language里面写的总结为模板的忠告养成的一个习惯。其实总想用模板的我,让我逐渐养成了"玩"模板的一个坏习惯。绞尽脑汁去想弄成个模板,成为耽误做正 事的一个根源,换句话说,真的可以划为奇技淫巧,而模板实际上并没有被用到真正该用到的地方。需要真正去考虑业务代码,而不是玩意儿。因为模板本身就成倍增加了 测试量,比单纯写个非模板的代码要麻烦数倍。
>
> >> 4、写个库,然后再写个工具去为库服务。
>
> >> 请看到这里的朋友不要太鄙视我,因为我已经很悲哀了。我编程的经历已经14年了,而且自认为对C/C++很了解了,可惜真的是可悲。针对"参数"这个,类似处理 "-c"
> >> "-a"这样的代码,我一直都是自己去写的代码去使用参数。我看到一些C的代码去学习之后才发现有这么个东西叫:getopt,我不但悲哀我一直用Window s,还悲哀我们国家这个封闭的环境,还悲哀自己没有去开放的学习。参数这个,Gnu很早就有个getopt的库,而且这个库的历史估计可以追寻到很久以前,你可 以手写代码轻易的使用,也可以用一个叫gengetopt的工具,根据某些配置去生成C的代码然后扔给编译器去用。而工具生成的使用getopt代码,是经得起 考验的。而工具本身,又是测试和验证库的有理凭据。我很仔细看了gengetopt的chm文档。
>
> >> 我在反复看的《程序设计实践》,Kernighan老家伙和Pike经典的阐述了"记法"这么一章,而这一章我反复看了有20遍以上。这个getopt不仅仅用 于main函数的那个argv,在设计简单的字符串记法上,同样有效。其实Lua有个工具叫tolua,还有个tolua++,而我沉迷于模板包装导出函数给L ua用,并没有仔细研究这个工具。
>
> >> 而这种,"写个库,然后写个工具"的东西,在很多古老的代码库里都能看到。而且他们到现在都工作的很好。真的对最初那些用C语言的老家伙们膜拜啊。
>
> >> 5、class的封装真的有那么好吗?
>
> >> Hub Scott曾经介绍如何肢解了最初的那份string代码。他评论了里面很多不应该写到string里面的方法。造成了string类的臃肿。
>
> >> 如果class仅仅是封装,而写一个class,需要那么多方法吗?我写了一个比较简单的gdi图形库,不用class封装,而是写一个struct封装数据, 写了一些内容是围绕这个struct处理的函数。函数的第一个参数传递这个struct指针,这样的写法其实与设计一个基本的class封装是等效的。而使用c lass的时候,那个隐藏的this,无形中会让人不知道什么该放进来,什么该扔出去。Python做的真的很好,self必须写,起初感觉很麻烦,多写个se lf干吗,逐渐我改变了这个看法,就应该写上,写上了才知道是不是属于这个类应该有的。而使用C++主动加this->的方式,已经被很多人提及是个好习惯了。
>
> >> 我回顾了以前的一些代码,发现很多类内容没多大关系的,也被我扔进去了。真的很不利于维护,而且有些地方明显是多余的。我要又一次提到随便了,为了随便去随便真 的不是个好习惯。
>
> >> Hub
> >> Scott介绍过另一个事情,是写一个栈的方式。他提到最好不要用继承,用内含。而最近我才看到,最初给Stroustrup提出加protected的那个人 ,其实他以后后悔了。
>
> >> 我自从我不用那些,什么多态啊,什么继承啊,什么封装啊之后,发现干活也没什么问题,地球也在转,我的程序也在转。而以前我为什么迷信这些呢,不是用OOP写的 东西,我就持怀疑甚至抨击的态度?真的是对OOP狂热痴迷到了病态。我反复看《Unix编程艺术》,Eric
> >> Raymond对C++的评价还是相对客观的,我最近才知道Alex
>
> ...
>
> read more >>
Linus Torvalds 曾经说过他不用C++在kernel programming的原因。除去他感情性的东西,技术性的两点是:
1)在kernel中无法handle exception
2)无法memory allocation
其实这两点都不是真实的"无法",但是不可否认,在kernel programming中,要做到exception handling
和memory allocation要付出的代价非常大(比如:怎么样用kalloc和free实现placement
new?),一个例子就是微软把kernel C++化的代价也非常大。
除了kernel programming,在user
land编程的话,我觉得C++还是有很大优势的。毕竟太多的功能和概念也提供了足够强大的优化能力。C++的门槛其实非常高,完全不是只用一两年就可以精通的。但是对于老手来说,任何其他语言可以实现的概念都可以相对简单地在C++实现,兼顾性能和结构。
2011/10/21 LeeoNix <leeo...@gmail.com>:
> 呵呵,有一个巨大的问题,就是用DirectX技术做游戏,而我又要做游戏。现在就算用gcc编译游戏的库绕弯子很麻烦,何况用其他的。C++做游戏有其优势,而方法也比较合适。语言适用。
>
> 在 2011年10月22日 上午12:15,HaoPeiQiang <HaoPe...@gmail.com>写道:
>>
>>
>> 所以,你可以用Objective-C,试试吧,仍旧100%兼容C(C++不确保100%兼容C,如果你懂C++你就知道我说的啥意思),而且真的面向对象的,而且有一个非常棒的类库,没有C++的一切负担。
>>
>> 2011/10/21 LeeoNix <leeo...@gmail.com>
>>>
>>>
>>> 好久没在TopLanguage发表感慨了。唉,知道大师Dennis的去世那天,我久久盯着屏幕看。悲哀,继Dijkstra之后,又一位真正的大师走了,而我面前所看到的虚拟的东西都源自那位大师。那天我写了不少C代码纪念大师,我认为除此之外没有其他形式值得做。
>>>
>>> 我很庆幸,我这半年多坚持不用C++只用纯C语言写东西。以前看云风写的Blog说C++的问题,而我也看了Eric
>>> Raymond的Unix编程艺术里面对C++的评价。一年多项目结束了,C++也用的熟的不能再熟了。可是我很多地方,真的感觉做了很多无用功。所以,我也效仿马化腾,做出了一个艰难的决定:不用C++写东西,只用C语言。
>>>
>>> 而C语言好久没有用了。而从新开始用C,本来以为是简化的简单C++,用就是了。可惜我被很多C++习惯给"宠坏"了。
>>>
>>> 1、变量,该死的变量。
>>>
>>>
>>> 变量不能随意声明了,只能在花括号内声明需要的变量。可以说在C++内,变量随手写是个大优势,但碰到C编译器,它不让你过了,而且该死的编译器并没有直接告诉我是变量的问题,而是其他的问题。起初写的一堆代码,最后发现30%编译不通过都是这个变量声明的问题。我重新审视我自己,我为什么要"随意"的声明变量?记得和大富翁论坛的版主王昊(Soul)在某次聚餐之后,他谈到了过分依赖所谓的随缘最终变成了随便的问题,我很仔细的听他说完了这个有关禅的东西。是的,很多时候把随意变成了随便了,我就像使用便民伞一样,随便拿了,没有还回去。无形中,其实我在做一种对编译器来说不道德的事情。
>>>
>>>
>>> 我用了很久的Delphi,而用Delphi的一个习惯就是变量必须在var关键字下。我一直都认为这是个好习惯,这样用C++就不会出太多问题。不过,我过于乐观了,随意的,或者说"随便"声明的变量,根本不利于静态检查,过于依赖编译器。我花了大概1个星期多的时间,才修正了乱声明变量的习惯。而且像for
>>> (int i; i < 100: ++i)这样的i声明方式的习惯,太不容易修改了。
>>>
>>>
>>> 过了一阵子,一个朋友给了我一块C++代码。其实他逻辑写的不错,但是我用了一段时间C代码。看好几个随意声明的变量非常扎眼。我把变量清理到前面声明,然后发现里面有3个变量就是随意声明的,其实作用是无意义的。早就听说过C++非常不利于"静态"检查,现在才明白。很多隐患实际就是坏习惯养成的。
>>>
>>> 2、析构函数,该死的析构函数。
>>>
>>>
>>> 我还有个坏习惯,就是听了那个Meyers的家伙,多用functor。呵呵,这是个玩笑。其实struct(class?)是个好东西,真的是个好东西,可以在构造函数初始化,析构函数清理它。我很喜欢写一些简单的struct,在栈内存上用,可以随意return,资源什么可以被安全的被清理,不用担心遗忘什么。注意,我又用了"随意"二字。其实......惭愧还是随便。是的虽然不担心资源了,但是大大影响了可读性,还有对返回值的检查。多个return就像筛子的洞一样。而随意的return的根源,是我随意的使用了析构函数。
>>>
>>> 多个return造成很多地方都不好控制,虽然说我的重构能力还是不错的。用Extract
>>> Mothed方式很多地方都模块化了。但是多return的难维护程度超乎我想像,最初我加了goto,跳到最后去干清理的事情,没错就是那个臭名昭著的goto,后来想想goto还是算了......
>>> 我继续重新审视以前写的代码。那个所谓封装的D3D的类,其结构严重违反干好一件事的原则,唉,越看越觉得,觉得......真的很难堪。
On Oct 22, 9:43 am, LeeoNix <leeoni...@gmail.com> wrote:
> 你说的所有的喜欢的地方。我也很喜欢,就因为喜欢,我才用了这么久,超过五年以上。
>
> 但我写这个的目的就是,你的喜欢是不是有益的。是不是真正值得考虑的。当你的喜欢不能用了,想想为什么你的喜欢不能存在于其他地方,而别的语言为什么不想要这种 "喜欢"?
>
> 前几天我和一个朋友交流,有时候在思考,为什么人不能随心所欲的或者呢?人有些嗜好和习惯是不是应该违逆自己的心情不要作?
>
> 比如我们喜欢的熬夜,晚起。喜欢的吸烟喝酒,喜欢的其他嗜好。
>
> The Pragmatic
> Programmer是一本好书,(注意我一直都很鄙视《程序员修炼之道》这个翻译书名,我很费解。)书的作者一开始就重点说不要总是习惯一种东西,而是理解不 同场合的优点,适时的更换思维才有益。这么久我才真正理解程序里面的某些对于习惯的依赖,真的是思维的巨大障碍。
> > 注意,我又用了"随意"二字。其实......惭愧还是随便。是的虽然不担心资源了,但是大大影响了可读性,还有对返回值的检查。多个return就像筛子的洞 一样。而
> > 随意的return的根源,是我随意的使用了析构函数。
>
> > > >> 多个return造成很多地方都不好控制,虽然说我的重构能力还是不错的。用Extract
>
> > Mothed方式很多地方都模块化了。但是多return的难维护程度超乎我想像,最初我加了goto,跳到最后去干清理的事情,没错就是那个臭名昭著的got
> > o,后来想想goto还是算了......
>
> > Delphi,注意,我又提到了Delphi了。呵呵。有个优势就是Result作为function的返回值被使用。其实这也是一个好习惯,有个具体存在的返
> > 回值变量。我花了一段时间把很多乱return的地方修改了,主动声明个叫"result"的变量使用,赋值之后才根据情况return,我还把我的Lua代码
> > 很多地方也做了类似的修改。数据的流向很容易被控制。
>
> > > >> 我看到别人转载的Jasone Tee写了一个文章A return to Good
>
> > Code,看了英文原文才发现CSDN也翻译转载了。但可悲的是看看下面的评论,除了无聊的争吵还是无聊的争吵。看的我有个感觉,很多人就像我住的楼前的黄毛哈
> > 巴狗一样,守着自己小小的地盘,对每一个路过的人去乱吠呢?怎么不去试试看写一些一个出口的代码试试看?
>
> > > >> 3、思念模板,但忍住不用。
>
> > 3年来,我用C++期间,写了太多的模板的代码了。而且一直都感觉模板是个很好的东西,虽然现在感觉也是个好东西。但C语言没有,有的时候写比较类似的代码,弄
> > 个模板就好了。其实是看了Stroustrup在The
> > > >> C++ Programming
>
> ...
>
> read more >>
On Oct 22, 9:43 am, LeeoNix <leeoni...@gmail.com> wrote:
> 你说的所有的喜欢的地方。我也很喜欢,就因为喜欢,我才用了这么久,超过五年以上。
>
> 但我写这个的目的就是,你的喜欢是不是有益的。是不是真正值得考虑的。当你的喜欢不能用了,想想为什么你的喜欢不能存在于其他地方,而别的语言为什么不想要这种 "喜欢"?
>
> 前几天我和一个朋友交流,有时候在思考,为什么人不能随心所欲的或者呢?人有些嗜好和习惯是不是应该违逆自己的心情不要作?
>
> 比如我们喜欢的熬夜,晚起。喜欢的吸烟喝酒,喜欢的其他嗜好。
>
> The Pragmatic
> Programmer是一本好书,(注意我一直都很鄙视《程序员修炼之道》这个翻译书名,我很费解。)书的作者一开始就重点说不要总是习惯一种东西,而是理解不 同场合的优点,适时的更换思维才有益。这么久我才真正理解程序里面的某些对于习惯的依赖,真的是思维的巨大障碍。
> > 注意,我又用了"随意"二字。其实......惭愧还是随便。是的虽然不担心资源了,但是大大影响了可读性,还有对返回值的检查。多个return就像筛子的洞 一样。而
> > 随意的return的根源,是我随意的使用了析构函数。
>
> > > >> 多个return造成很多地方都不好控制,虽然说我的重构能力还是不错的。用Extract
>
> > Mothed方式很多地方都模块化了。但是多return的难维护程度超乎我想像,最初我加了goto,跳到最后去干清理的事情,没错就是那个臭名昭著的got
> > o,后来想想goto还是算了......
>
> > Delphi,注意,我又提到了Delphi了。呵呵。有个优势就是Result作为function的返回值被使用。其实这也是一个好习惯,有个具体存在的返
> > 回值变量。我花了一段时间把很多乱return的地方修改了,主动声明个叫"result"的变量使用,赋值之后才根据情况return,我还把我的Lua代码
> > 很多地方也做了类似的修改。数据的流向很容易被控制。
>
> > > >> 我看到别人转载的Jasone Tee写了一个文章A return to Good
>
> > Code,看了英文原文才发现CSDN也翻译转载了。但可悲的是看看下面的评论,除了无聊的争吵还是无聊的争吵。看的我有个感觉,很多人就像我住的楼前的黄毛哈
> > 巴狗一样,守着自己小小的地盘,对每一个路过的人去乱吠呢?怎么不去试试看写一些一个出口的代码试试看?
>
> > > >> 3、思念模板,但忍住不用。
>
> > 3年来,我用C++期间,写了太多的模板的代码了。而且一直都感觉模板是个很好的东西,虽然现在感觉也是个好东西。但C语言没有,有的时候写比较类似的代码,弄
> > 个模板就好了。其实是看了Stroustrup在The
> > > >> C++ Programming
>
> ...
>
> read more >>
参考资料:
List of game engines: http://en.wikipedia.org/wiki/List_of_game_engines
--
Yili Zhao
其实c语言标准如果肯接受gcc的嵌套函数扩展,那就功德无量了。(VC 编译器如果还不跟进我就彻底把你枪毙了)
C++不容易用好。但对我而言,C++可以写出比C更灵活的、更安全、更紧凑、更具有表达力的代码。
语言是可以决定思维模式的。为什么C的代码最容易出现缓冲区溢出,就是因为C的程序员最容易使用固定缓冲区大小的方式——这对C来讲是最容易、最自然的方式。大部分其他语言都不是如此。
2011/10/22 rexfield <redwo...@gmail.com>:
--
Wu Yongwei
URL: http://wyw.dcweb.cn/
1.那个时代的deque的问题,特指vc6的std::deque实现效率较低。
2.ACE和QT,出生的年代都比STL早,有一套自己替代的系统很正常。至于为什么一直还保留这些不能用于stl算法的容器,二者给出的答案相同:为了兼容那些不提供stl的特殊编译环境。兄弟你不会没听说过android
ndk吧。
没事写c++库(高质量的库),是件很奢侈的事情。兄弟你太小看自己写c++库的难度了。
另外兄弟那些连续的反问句,读起来让人很迷糊。。。颇有外交部发言人之风。
On 10/22/11, LeeoNix <leeo...@gmail.com> wrote:
>>>>> Code<http://www.theserverside.com/tip/A-return-to-Good-Code>
>>>>> ,看了英文原文才发现CSDN也翻译转载 <http://sd.csdn.net/a/20110323/294448.html>
>>>>> 了。但可悲的是看看下面的评论,除了无聊的争吵还是无聊的争吵。看的我有个感觉,很多人就像我住的楼前的黄毛哈巴狗一样,守着自己小小的地盘,对每一个路过的人去乱吠呢?怎么不去试试看写一些一个出口的代码试试看?
>>>>>
>>>>> 3、思念模板,但忍住不用。
>>>>>
>>>>> 3年来,我用C++期间,写了太多的模板的代码了。而且一直都感觉模板是个很好的东西,虽然现在感觉也是个好东西。但C语言没有,有的时候写比较类似的代码,弄个模板就好了。其实是看了Stroustrup在The
>>>>> C++ Programming
>>>>> Language里面写的总结为模板的忠告养成的一个习惯。其实总想用模板的我,让我逐渐养成了“玩”模板的一个坏习惯。绞尽脑汁去想弄成个模板,成为耽误做正事的一个根源,换句话说,真的可以划为奇技淫巧,而模板实际上并没有被用到真正该用到的地方。需要真正去考虑业务代码,而不是玩意儿。因为模板本身就成倍增加了测试量,比单纯写个非模板的代码要麻烦数倍。
>>>>>
>>>>> 4、写个库,然后再写个工具去为库服务。
>>>>>
>>>>> 请看到这里的朋友不要太鄙视我,因为我已经很悲哀了。我编程的经历已经14年了,而且自认为对C/C++很了解了,可惜真的是可悲。针对“参数”这个,类似处理"-c"
>>>>> "-a"这样的代码,我一直都是自己去写的代码去使用参数。我看到一些C的代码去学习之后才发现有这么个东西叫:getopt,我不但悲哀我一直用Windows,还悲哀我们国家这个封闭的环境,还悲哀自己没有去开放的学习。参数这个,Gnu很早就有个getopt的库,而且这个库的历史估计可以追寻到很久以前,你可以手写代码轻易的使用,也可以用一个叫gengetopt的工具,根据某些配置去生成C的代码然后扔给编译器去用。而工具生成的使用getopt代码,是经得起考验的。而工具本身,又是测试和验证库的有理凭据。我很仔细看了gengetopt的chm文档。
>>>>>
>>>>>
>>>>> 我在反复看的《程序设计实践》,Kernighan老家伙和Pike经典的阐述了”记法“这么一章,而这一章我反复看了有20遍以上。这个getopt不仅仅用于main函数的那个argv,在设计简单的字符串记法上,同样有效。其实Lua有个工具叫tolua,还有个tolua++,而我沉迷于模板包装导出函数给Lua用,并没有仔细研究这个工具。
>>>>>
>>>>> 而这种,“写个库,然后写个工具”的东西,在很多古老的代码库里都能看到。而且他们到现在都工作的很好。真的对最初那些用C语言的老家伙们膜拜啊。
>>>>>
>>>>> 5、class的封装真的有那么好吗?
>>>>>
>>>>> Hub Scott曾经介绍如何肢解了最初的那份string代码。他评论了里面很多不应该写到string里面的方法。造成了string类的臃肿。
>>>>>
>>>>>
>>>>> 如果class仅仅是封装,而写一个class,需要那么多方法吗?我写了一个比较简单的gdi图形库,不用class封装,而是写一个struct封装数据,写了一些内容是围绕这个struct处理的函数。函数的第一个参数传递这个struct指针,这样的写法其实与设计一个基本的class封装是等效的。而使用class的时候,那个隐藏的this,无形中会让人不知道什么该放进来,什么该扔出去。Python做的真的很好,self必须写,起初感觉很麻烦,多写个self干吗,逐渐我改变了这个看法,就应该写上,写上了才知道是不是属于这个类应该有的。而使用C++主动加this->的方式,已经被很多人提及是个好习惯了。
>>>>>
>>>>>
>>>>> 我回顾了以前的一些代码,发现很多类内容没多大关系的,也被我扔进去了。真的很不利于维护,而且有些地方明显是多余的。我要又一次提到随便了,为了随便去随便真的不是个好习惯。
>>>>>
>>>>> Hub
>>>>> Scott介绍过另一个事情,是写一个栈的方式。他提到最好不要用继承,用内含。而最近我才看到,最初给Stroustrup提出加protected的那个人,其实他以后后悔了。
>>>>> 我自从我不用那些,什么多态啊,什么继承啊,什么封装啊之后,发现干活也没什么问题,地球也在转,我的程序也在转。而以前我为什么迷信这些呢,不是用OOP写的东西,我就持怀疑甚至抨击的态度?真的是对OOP狂热痴迷到了病态。我反复看《Unix编程艺术》,Eric
>>>>> Raymond对C++的评价还是相对客观的,我最近才知道Alex Stepanov竟然一直都持质疑态度。
>>>>>
>>>>> 6、干好一件事。
>>>>>
>>>>> Doug McIlroy说:让每个程序都干好一件事。如果有新任务,就重新开始,不要往原程序中加入新功能而搞的复杂。
>>>>> 简单性,是作程序起始,过来人都告诫,简单性的问题。可是一直对简单性有个真正的标准。而Doug
>>>>> McIlroy给了个标准,干好一件事。而坚持用C写代码,才重新审视这个干好一件事的问题。因为被OO狂热的洗脑后干什么都写个class让我习惯什么都得扔到一起,其实怪不得C++,是我的问题。
>>>>>
>>>>> FIXprotocol <http://www.fixprotocol.org/>
>>>>> 设计的是证券交易使用的传输协议。因为工作的缘故,接触了这个公司设计的FAST<http://www.fixprotocol.org/fast>
>>>>> 协议,现在上海的证券交易也是在使用这个。fixprotocol提供的fastapi的C代码库,写的真的干净优雅,认真的干好一件事而没做多余的事情,
>>>>> 这里 <http://www.fixprotocol.org/documents/2317/fastapi-1.0.zip>
C++能够存在这么久,自有他存在的道理。尽管他生存条件恶劣,后无商业公司给他扩展库,前有因为资格老,编译器兼容性更好的C(C的很多优点其实就源自出道早,说白了。C89出现前后,c一样有很多兼容性问题),自己的模板库更是因为源码开放,被人千夫所指(同样是库函数,大家就盯着vc6的std::deque效率,干嘛就没人去瞅瞅msvcrt库memmove的效率?指责c++的人有时其实根本没注意自己毫无比较的对象。做c++的模板库是个超吃力不讨好的事,永远有人来指责你效率没有做到最佳,哪里的实现很笨拙。不像c语言那样,实现的源码都封装起来,闭着眼睛,一了百了,不用拉倒)。
其实那个cstl效率很低的。。。真的。有的库名字取的很牛,未必真的很牛。还有一个叫s11n的家伙。
这些优势,可以在最能体现其特点的领域看到。如果去华尔街,大多数的公司,几乎所有的高频交易,都是用的C++,连java和C都不可以。因为他们非常在乎从5毫秒到3毫秒的优化,又必须快速编程,立刻用上。再比如现在很多的网络和存储器公司,如diligent(现在是ibm了)、netapp、equallogic(现在是dell)等,都是用的C++,因为他们需要大量的底层接口和运行效率。
C++的缺点,其实就在这些与其他语言的不同上面。也就是如你所说的,是这些庞大臃肿的概念和功能。因为这些其实是牛刀,如果去割鸡的话,很容易反而弄得一地鸡血。那些大牛对C++的批评,其实可以说都对,C++没有一个清晰明确的设计理念,甚至不能算是真正纯粹的面对对象。所以,所有其他语言都有其生存发展的空间,因为这才是常理:一种语言的设计原则,决定了这种语言的应用领域。C++并不适合web编程,但是有其适合的应用。
2011/10/21 LeeoNix <leeo...@gmail.com>:
On Oct 21, 12:15 pm, HaoPeiQiang <HaoPeiQi...@gmail.com> wrote:
> 所以,你可以用Objective-C,试试吧,仍旧100%兼容C(C++不确保100%兼容C,如果你懂C++你就知道我说的啥意思),而且真的面向对象的,而且有一个非常棒的类库,没有C++的一切负担。
>
> 2011/10/21 LeeoNix <leeoni...@gmail.com>
>
>
>
>
>
>
>
>
>
> > 好久没在TopLanguage发表感慨了。唉,知道大师Dennis的去世那天,我久久盯着屏幕看。悲哀,继Dijkstra之后,又一位真正的大师走了,而我面前所看到的虚拟的东西都源自那位大师。那天我写了不少C代码纪念大师,我认为除此之外没有其他形式值得做。
>
> > 我很庆幸,我这半年多坚持不用C++只用纯C语言写东西。以前看云风写的Blog说C++的问题,而我也看了Eric
> > Raymond的Unix编程艺术里面对C++的评价。一年多项目结束了,C++也用的熟的不能再熟了。可是我很多地方,真的感觉做了很多无用功。所以,我也效仿马化腾,做出了一个艰难的决定:不用C++写东西,只用C语言。
>
> > 而C语言好久没有用了。而从新开始用C,本来以为是简化的简单C++,用就是了。可惜我被很多C++习惯给"宠坏"了。
>
> > 1、变量,该死的变量。
>
> > 变量不能随意声明了,只能在花括号内声明需要的变量。可以说在C++内,变量随手写是个大优势,但碰到C编译器,它不让你过了,而且该死的编译器并没有直接告诉我是变量的问题,而是其他的问题。起初写的一堆代码,最后发现30%编译不通过都是这个变量声明的问题。我重新审视我自己,我为什么要"随意"的声明变量?记得和大富翁论坛的版主王昊(Soul)在某次聚餐之后,他谈到了过分依赖所谓的随缘最终变成了随便的问题,我很仔细的听他说完了这个有关禅的东西。是的,很多时候把随意变成了随便了,我就像使用便民伞一样,随便拿了,没有还回去。无形中,其实我在做一种对编译器来说不道德的事情。
>
> > 我用了很久的Delphi,而用Delphi的一个习惯就是变量必须在var关键字下。我一直都认为这是个好习惯,这样用C++就不会出太多问题。不过,我过于乐观了,随意的,或者说"随便"声明的变量,根本不利于静态检查,过于依赖编译器。我花了大概1个星期多的时间,才修正了乱声明变量的习惯。而且像for
> > (int i; i < 100: ++i)这样的i声明方式的习惯,太不容易修改了。
>
> > 过了一阵子,一个朋友给了我一块C++代码。其实他逻辑写的不错,但是我用了一段时间C代码。看好几个随意声明的变量非常扎眼。我把变量清理到前面声明,然后发现里面有3个变量就是随意声明的,其实作用是无意义的。早就听说过C++非常不利于"静态"检查,现在才明白。很多隐患实际就是坏习惯养成的。
>
> > 2、析构函数,该死的析构函数。
>
> > 我还有个坏习惯,就是听了那个Meyers的家伙,多用functor。呵呵,这是个玩笑。其实struct(class?)是个好东西,真的是个好东西,可以在构造函数初始化,析构函数清理它。我很喜欢写一些简单的struct,在栈内存上用,可以随意return,资源什么可以被安全的被清理,不用担心遗忘什么。注意,我又用了"随意"二字。其实......惭愧还是随便。是的虽然不担心资源了,但是大大影响了可读性,还有对返回值的检查。多个return就像筛子的洞一样。而随意的return的根源,是我随意的使用了析构函数。
>
> > 多个return造成很多地方都不好控制,虽然说我的重构能力还是不错的。用Extract
> > Mothed方式很多地方都模块化了。但是多return的难维护程度超乎我想像,最初我加了goto,跳到最后去干清理的事情,没错就是那个臭名昭著的goto,后来想想goto还是算了......
> ...
>
> read more >>
On Oct 21, 12:45 pm, windstorm <likunarmstr...@gmail.com> wrote:
> 如果专注点是苹果平台,OC当然是不二选择。
>
> 我当年学完OC的最大感触就是,要是Java有其一半优雅和高效就好了
>
> ----------------------------------------------------------------------------------
> Yours Sincerely
> Kun
>
> gplus.to/kunli
>
> 2011/10/21 HaoPeiQiang <HaoPeiQi...@gmail.com>:
>
>
>
>
>
>
>
> > Go我觉得不错,不过我还是更喜欢OC,哈哈
>
> > 2011/10/22 windstorm <likunarmstr...@gmail.com>
>
> >> Objective-C确实也挺好,但仅限于苹果平台。其实我觉得你可以去看看Rob Pike他们搞的Go。
>
> >> 我没用过C++,所以不清楚和C++比的优劣。但Go是我见过的第一种结合C和Python的很多优点的语言,原生并行。尤其值得一提的是其interface设计及其优雅而高效,让我觉得所有程序语言都应该这样设计。Go是天生的服务器语言,但写本地程序一样很方便。
>
> >> 在我用过的主流语言中(C/Python/Java/Objective-C),Go是唯一一种让我觉得"程序就该这样写"的。
>
> >> ----------------------------------------------------------------------------------
> >> Yours Sincerely
> >> Kun
>
> >> gplus.to/kunli
>
> >> 2011/10/21 HaoPeiQiang <HaoPeiQi...@gmail.com>:
>
> >> > 所以,你可以用Objective-C,试试吧,仍旧100%兼容C(C++不确保100%兼容C,如果你懂C++你就知道我说的啥意思),而且真的面向对象的,而且有一个非常棒的类库,没有C++的一切负担。
>
> >> > 2011/10/21 LeeoNix <leeoni...@gmail.com>
>
> >> >> 好久没在TopLanguage发表感慨了。唉,知道大师Dennis的去世那天,我久久盯着屏幕看。悲哀,继Dijkstra之后,又一位真正的大师走了,而我面前所看到的虚拟的东西都源自那位大师。那天我写了不少C代码纪念大师,我认为除此之外没有其他形式值得做。
>
> >> >> 我很庆幸,我这半年多坚持不用C++只用纯C语言写东西。以前看云风写的Blog说C++的问题,而我也看了Eric
>
> >> >> Raymond的Unix编程艺术里面对C++的评价。一年多项目结束了,C++也用的熟的不能再熟了。可是我很多地方,真的感觉做了很多无用功。所以,我也效仿马化腾,做出了一个艰难的决定:不用C++写东西,只用C语言。
>
> >> >> 而C语言好久没有用了。而从新开始用C,本来以为是简化的简单C++,用就是了。可惜我被很多C++习惯给"宠坏"了。
>
> >> >> 1、变量,该死的变量。
>
> >> >> 变量不能随意声明了,只能在花括号内声明需要的变量。可以说在C++内,变量随手写是个大优势,但碰到C编译器,它不让你过了,而且该死的编译器并没有直接告诉我是变量的问题,而是其他的问题。起初写的一堆代码,最后发现30%编译不通过都是这个变量声明的问题。我重新审视我自己,我为什么要"随意"的声明变量?记得和大富翁论坛的版主王昊(Soul)在某次聚餐之后,他谈到了过分依赖所谓的随缘最终变成了随便的问题,我很仔细的听他说完了这个有关禅的东西。是的,很多时候把随意变成了随便了,我就像使用便民伞一样,随便拿了,没有还回去。无形中,其实我在做一种对编译器来说不道德的事情。
>
> >> >> 我用了很久的Delphi,而用Delphi的一个习惯就是变量必须在var关键字下。我一直都认为这是个好习惯,这样用C++就不会出太多问题。不过,我过于乐观了,随意的,或者说"随便"声明的变量,根本不利于静态检查,过于依赖编译器。我花了大概1个星期多的时间,才修正了乱声明变量的习惯。而且像for
> >> >> (int i; i < 100: ++i)这样的i声明方式的习惯,太不容易修改了。
>
> >> >> 过了一阵子,一个朋友给了我一块C++代码。其实他逻辑写的不错,但是我用了一段时间C代码。看好几个随意声明的变量非常扎眼。我把变量清理到前面声明,然后发现里面有3个变量就是随意声明的,其实作用是无意义的。早就听说过C++非常不利于"静态"检查,现在才明白。很多隐患实际就是坏习惯养成的。
>
> >> >> 2、析构函数,该死的析构函数。
>
> >> >> 我还有个坏习惯,就是听了那个Meyers的家伙,多用functor。呵呵,这是个玩笑。其实struct(class?)是个好东西,真的是个好东西,可以在构造函数初始化,析构函数清理它。我很喜欢写一些简单的struct,在栈内存上用,可以随意return,资源什么可以被安全的被清理,不用担心遗忘什么。注意,我又用了"随意"二字。其实......惭愧还是随便。是的虽然不担心资源了,但是大大影响了可读性,还有对返回值的检查。多个return就像筛子的洞一样。而随意的return的根源,是我随意的使用了析构函数。
>
> >> >> 多个return造成很多地方都不好控制,虽然说我的重构能力还是不错的。用Extract
>
> >> >> Mothed方式很多地方都模块化了。但是多return的难维护程度超乎我想像,最初我加了goto,跳到最后去干清理的事情,没错就是那个臭名昭著的goto,后来想想goto还是算了......
>
> >> >> Delphi,注意,我又提到了Delphi了。呵呵。有个优势就是Result作为function的返回值被使用。其实这也是一个好习惯,有个具体存在的返回值变量。我花了一段时间把很多乱return的地方修改了,主动声明个叫"result"的变量使用,赋值之后才根据情况return,我还把我的Lua代码很多地方也做了类似的修改。数据的流向很容易被控制。
>
> >> >> 我看到别人转载的Jasone Tee写了一个文章A return to Good
>
> >> >> Code,看了英文原文才发现CSDN也翻译转载了。但可悲的是看看下面的评论,除了无聊的争吵还是无聊的争吵。看的我有个感觉,很多人就像我住的楼前的黄毛哈巴狗一样,守着自己小小的地盘,对每一个路过的人去乱吠呢?怎么不去试试看写一些一个出口的代码试试看?
>
> >> >> 3、思念模板,但忍住不用。
>
> >> >> 3年来,我用C++期间,写了太多的模板的代码了。而且一直都感觉模板是个很好的东西,虽然现在感觉也是个好东西。但C语言没有,有的时候写比较类似的代码,弄个模板就好了。其实是看了Stroustrup在The
> >> >> C++ Programming
>
> >> >> Language里面写的总结为模板的忠告养成的一个习惯。其实总想用模板的我,让我逐渐养成了"玩"模板的一个坏习惯。绞尽脑汁去想弄成个模板,成为耽误做正事的一个根源,换句话说,真的可以划为奇技淫巧,而模板实际上并没有被用到真正该用到的地方。需要真正去考虑业务代码,而不是玩意儿。因为模板本身就成倍增加了测试量,比单纯写个非模板的代码要麻烦数倍。
>
> >> >> 4、写个库,然后再写个工具去为库服务。
>
> >> >> 请看到这里的朋友不要太鄙视我,因为我已经很悲哀了。我编程的经历已经14年了,而且自认为对C/C++很了解了,可惜真的是可悲。针对"参数"这个,类似处理"-c"
>
> >> >> "-a"这样的代码,我一直都是自己去写的代码去使用参数。我看到一些C的代码去学习之后才发现有这么个东西叫:getopt,我不但悲哀我一直用Windows,还悲哀我们国家这个封闭的环境,还悲哀自己没有去开放的学习。参数这个,Gnu很早就有个getopt的库,而且这个库的历史估计可以追寻到很久以前,你可以手写代码轻易的使用,也可以用一个叫gengetopt的工具,根据某些配置去生成C的代码然后扔给编译器去用。而工具生成的使用getopt代码,是经得起考验的。而工具本身,又是测试和验证库的有理凭据。我很仔细看了gengetopt的chm文档。
>
> >> >> 我在反复看的《程序设计实践》,Kernighan老家伙和Pike经典的阐述了"记法"这么一章,而这一章我反复看了有20遍以上。这个getopt不仅仅用于main函数的那个argv,在设计简单的字符串记法上,同样有效。其实Lua有个工具叫tolua,还有个tolua++,而我沉迷于模板包装导出函数给Lua用,并没有仔细研究这个工具。
>
> >> >> 而这种,"写个库,然后写个工具"的东西,在很多古老的代码库里都能看到。而且他们到现在都工作的很好。真的对最初那些用C语言的老家伙们膜拜啊。
>
> >> >> 5、class的封装真的有那么好吗?
>
> >> >> Hub Scott曾经介绍如何肢解了最初的那份string代码。他评论了里面很多不应该写到string里面的方法。造成了string类的臃肿。
>
> >> >> 如果class仅仅是封装,而写一个class,需要那么多方法吗?我写了一个比较简单的gdi图形库,不用class封装,而是写一个struct封装数据,写了一些内容是围绕这个struct处理的函数。函数的第一个参数传递这个struct指针,这样的写法其实与设计一个基本的class封装是等效的。而使用class的时候,那个隐藏的this,无形中会让人不知道什么该放进来,什么该扔出去。Python做的真的很好,self必须写,起初感觉很麻烦,多写个self干吗,逐渐我改变了这个看法,就应该写上,写上了才知道是不是属于这个类应该有的。而使用C++主动加this->的方式,已经被很多人提及是个好习惯了。
>
> ...
>
> read more >>
本来我们要实现的各种算法逻辑都很复杂,哪有心思去搞什么C++的优化。而且,对于我们来说,C++和Java那点速度的差别根本可以忽略。我们只关心
一个算法是O(N^2), O(N)还是O(NlogN)。
On Oct 22, 7:58 pm, LeeoNix <leeoni...@gmail.com> wrote:
> 看到这里,我很质疑你说的"编程效率"的评价。但我对此不做评价,因为我已经不是面向对象的狂热者了,所谓的面向对象的效率,我这么多年没见有多好过。
>
> 说到这里又让我想起Linus的有关git的骂架了。其实Linus在那个有关git骂架里面,开始言辞激烈,后面却说得很中肯。
>
> 一句话总结:C++让人没有把心放到业务上。
>
> Linus为了设计git,甚至用Shell和Perl设计原型,然后逐渐替代这些代码。最初的git确实很不易用,但是git的核心很早就被设计好了,外面的修正为易用就好了。
>
> 那个骂架过去很久了,git现在很流行。而我越来越看Linus的骂架顺眼了,不是个人崇拜的相信,是经历过之后才感觉Linus其实不管是不是言辞激烈,说的都是真正的技术争论,而且说的中肯。
>
> 特别Linus批评的,"完全是屁话。字符串/内存管理根本无关紧要。
> 还是去看看源代码吧(我敢打赌你没有看过)。这不是重要的部分,而且也不复杂。唯一真正重要的部分是设计。"
>
> 我过了这么久才明白这个。Dmitry
> Kakurin和其他C++程序员一样,还是一个Coder,没有一个跳出去看项目的角度分析业务,看设计,而着眼于这些细节。
> 其实这就是C++程序员的通病,而我作为C++程序员的一员,其实也是如此。而分析业务,设计的能力,和Java程序员比起来,简直让人羞愧,我也曾经作为羞愧的C++程序员一员,去批评Java的效率问题,但Java效率再差也把项目漂亮的搞好了。
>
> 程序设计语言无形中影响了人的思维方式。
>
> Linus和Dmitry Kakurin说设计,而Dmitry
> Kakurin却在批评git的细节。然后我退一千步,做git的不是Linus,而是其他人,他的技术没有Linus那么牛,但是他很好的完成了git的核心业务,效率再差,也被快速开发为一个产品投放使用了,剩下的就是调优而已。何况Linus亲自操刀。
>
> 而实际的项目里,项目带头人唯技术先进的,毁了多少项目。比如我举个实际的例子,不是国外的。
>
> 阿里巴巴贸易通,以前就是个垃圾技术生成的IM,很多东西没做好实际上是用网页做的,虽然烂但是他快速投放市场了,大家接受这个产品了。而现在淘宝旺旺到阿里旺旺的版本,阿里巴巴在这方面做的很出色。而相比,盛大的圈圈项目,吹了那么久。就我在盛大的那段时间内,整整一年就没看到一个完整的东西出来,就是内部用的版本也是麻烦不断,我很是费解。现在你在世面上还看得到有人在用盛大圈圈吗?
>
> 反思啊。所以才艰难的决定就是:不用C++
>
> 在 2011年10月23日 上午12:30,Yuantai Du <yuantai...@gmail.com>写道:
>
>
>
>
>
>
>
> > C++的优势体现在其运行效率和编程效率的统一上。其他的大多数编程语言,从Smalltalk,java,
> > c#到Go,有足够高的编程效率,但是其编译后的运行效率则无法和C++相比,更不用说scripting
>
> > language了。这是由于这些高级语言的设计中,本身就已经包含了很多的masking,所以,在大多数时候,他们编程效率的提高隐含了运行峰值的下降。C++由于保留了C的大多数底层特性,所以保留了足够人工调整运行效率的空间。C语言有足够的运行效率,但是其编程效率比面对对象要差太多了。所以被局限在了底层编程。一个例外是苹果的ObjectiveC,
> > 使用了大量的宏来达到面对对象。不知以后objective c 能否扩展到其他领域。
>
> > 这些优势,可以在最能体现其特点的领域看到。如果去华尔街,大多数的公司,几乎所有的高频交易,都是用的C++,连java和C都不可以。因为他们非常在乎从5毫秒到3毫秒的优化,又必须快速编程,立刻用上。再比如现在很多的网络和存储器公司,如diligent(现在是ibm了)、netapp、equallogic(现在是dell)等,都是用的C++,因为他们需要大量的底层接口和运行效率。
>
> > C++的缺点,其实就在这些与其他语言的不同上面。也就是如你所说的,是这些庞大臃肿的概念和功能。因为这些其实是牛刀,如果去割鸡的话,很容易反而弄得一地鸡血。那些大牛对C++的批评,其实可以说都对,C++没有一个清晰明确的设计理念,甚至不能算是真正纯粹的面对对象。所以,所有其他语言都有其生存发展的空间,因为这才是常理:一种语言的设计原则,决定了这种语言的应用领域。C++并不适合web编程,但是有其适合的应用。
>
> > 2011/10/21 LeeoNix <leeoni...@gmail.com>:
>
> > C++的优势,自从我2002年用起到现在,就没感觉到有多大。真的,学习C++从惊喜到狂热,从狂热到冷静,从冷静到哀叹。不止一个牛人在反C++的立场上说反对C++的话了。这些人的话都是理智而且份量重,让我不得不重新审视为什么要用C++这个问题。
>
> > 就像会思考的人,总会突然有一天思考:人为什么活着。很多会继续思考人为什么存在与社会上(或者存在于地球上)。甚至会继续思考,人和宇宙的联系之类的。几年前,我和Cnpack开发组的朋友们在干锅居很深入的交流过人与宇宙的关系,大家发表感慨真的很踊跃,不亏都是程序员......而我当时都很异样为什么大家都在不同的时刻都往宇宙去考虑了呢,是全员不是个别......
>
> > 所谓反思使用C++的问题,起始和思考到人与宇宙的途经。有的时候感觉累了,就会胡思乱想一下。如果活的很开心,换言之用C++很开心的人,估计不会有我类似的想法。
>
> > > 痛定思痛大概如此了。
>
> > > 在 2011年10月22日 上午9:18,Yuantai Du <yuantai...@gmail.com>写道:
>
> > >> C在底层方面的优势是C++怎么都无法比拟的。
>
> > >> Linus Torvalds 曾经说过他不用C++在kernel programming的原因。除去他感情性的东西,技术性的两点是:
> > >> 1)在kernel中无法handle exception
> > >> 2)无法memory allocation
> > >> 其实这两点都不是真实的"无法",但是不可否认,在kernel programming中,要做到exception handling
> > >> 和memory allocation要付出的代价非常大(比如:怎么样用kalloc和free实现placement
> > >> new?),一个例子就是微软把kernel C++化的代价也非常大。
>
> > >> 除了kernel programming,在user
>
> > land编程的话,我觉得C++还是有很大优势的。毕竟太多的功能和概念也提供了足够强大的优化能力。C++的门槛其实非常高,完全不是只用一两年就可以精通的。但是对于老手来说,任何其他语言可以实现的概念都可以相对简单地在C++实现,兼顾性能和结构。
>
> > >> 2011/10/21 LeeoNix <leeoni...@gmail.com>:
>
> > 呵呵,有一个巨大的问题,就是用DirectX技术做游戏,而我又要做游戏。现在就算用gcc编译游戏的库绕弯子很麻烦,何况用其他的。C++做游戏有其优势,而方法也比较合适。语言适用。
>
> > >> > 在 2011年10月22日 上午12:15,HaoPeiQiang <HaoPeiQi...@gmail.com>写道:
>
> > 所以,你可以用Objective-C,试试吧,仍旧100%兼容C(C++不确保100%兼容C,如果你懂C++你就知道我说的啥意思),而且真的面向对象的,而且有一个非常棒的类库,没有C++的一切负担。
>
> > >> >> 2011/10/21 LeeoNix <leeoni...@gmail.com>
>
> > 好久没在TopLanguage发表感慨了。唉,知道大师Dennis的去世那天,我久久盯着屏幕看。悲哀,继Dijkstra之后,又一位真正的大师走了,而我面前所看到的虚拟的东西都源自那位大师。那天我写了不少C代码纪念大师,我认为除此之外没有其他形式值得做。
>
> > >> >>> 我很庆幸,我这半年多坚持不用C++只用纯C语言写东西。以前看云风写的Blog说C++的问题,而我也看了Eric
>
> > Raymond的Unix编程艺术里面对C++的评价。一年多项目结束了,C++也用的熟的不能再熟了。可是我很多地方,真的感觉做了很多无用功。所以,我也效仿马化腾,做出了一个艰难的决定:不用C++写东西,只用C语言。
>
> > >> >>> 而C语言好久没有用了。而从新开始用C,本来以为是简化的简单C++,用就是了。可惜我被很多C++习惯给"宠坏"了。
>
> > >> >>> 1、变量,该死的变量。
>
> > 变量不能随意声明了,只能在花括号内声明需要的变量。可以说在C++内,变量随手写是个大优势,但碰到C编译器,它不让你过了,而且该死的编译器并没有直接告诉我是变量的问题,而是其他的问题。起初写的一堆代码,最后发现30%编译不通过都是这个变量声明的问题。我重新审视我自己,我为什么要"随意"的声明变量?记得和大富翁论坛的版主王昊(Soul)在某次聚餐之后,他谈到了过分依赖所谓的随缘最终变成了随便的问题,我很仔细的听他说完了这个有关禅的东西。是的,很多时候把随意变成了随便了,我就像使用便民伞一样,随便拿了,没有还回去。无形中,其实我在做一种对编译器来说不道德的事情。
>
> ...
>
> read more >>
笑话,C就让人把心放到业务上了?没有RAII,没有对象,没有继承,容易发生内存泄漏和缓冲区溢出⋯⋯
一开始说C++不好,后来又说Nebula好,STL不好或者其实现不好。我觉得你自己思路有点不清。实现不好是可以提高的,特别是早期的实现不完善很正常——何况菜鸟程序员很可能做得更糟糕。方向正确才是重要的。
我是试过把C++的代码直接翻译成C的,缓冲区的管理放到C实在是很不方便,无怪乎C程序员习惯于使用固定大小的缓冲区。语言绝对可以影响思维。
如果你把太多力气放在玩C++上,这是你的问题。不要怪C++。有人已经说过了,这是把牛刀,用好不容易。反过来,用好了,就是绝对的利器。
2011/10/23 maydayzm <mayd...@gmail.com>:
On Oct 23, 8:12 am, LeeoNix <leeoni...@gmail.com> wrote:
> 抱歉。我看了下书,俩老家伙还是在Windows下测试了。
>
> 他们在测试后最后的总结是:"我们也认为,STL作为C++的一个新部分,仍然受到不成熟实现的损害。在使用STL的不同实现或使用不同数据结构时,导致的性能 变化是不可预测的。"
>
> 在 2011年10月23日 上午7:16,LeeoNix <leeoni...@gmail.com>写道:
>
On Oct 21, 11:49 pm, LeeoNix <leeoni...@gmail.com> wrote:
>
> 1、变量,该死的变量。
>
> 变量不能随意声明了,只能在花括号内声明需要的变量。可以说在C++内,变量随手写是个大优势,但碰到C编译器,它不让你过了,而且该死的编译器并没有直接告诉我是变量的问题,而是其他的问题。起初写的一堆代码,最后发现30%编译不通过都是这个变量声明的问题。我重新审视我自己,我为什么要"随意"的声明变量?记得和大富翁论坛的版主王昊(Soul)在某次聚餐之后,他谈到了过分依赖所谓的随缘最终变成了随便的问题,我很仔细的听他说完了这个有关禅的东西。是的,很多时候把随意变成了随便了,我就像使用便民伞一样,随便拿了,没有还回去。无形中,其实我在做一种对编译器来说不道德的事情。
c99 应该可以,不过即使是c89,你可以可以在你想要"随意"声明变量的地方用花括号形成语句块,这样就可以"随意"声明了
陈硕大家涵养真强啊。
我直接就不想理这种试图用月经贴或者不断引用名人名言来出名的“现代祢衡”,不管他是寻找明主还是就是想来发泄一通抑或是混个出名。
你的标题让我感觉你想向低级语言方向走,而你辩论的多数内容,让我感觉是在批判C++的低级性。
什么是高级语言的特征?设计特征更向subject
domain的内在概念关系靠拢,就是说,更容易概括问题领域的模型,而实现细节揭露得更少。而低级语言呢?更与机器的实现细节相关,因此较难有清晰的设计。
你批评的东西,最初的一篇中的弱类型和析构函数都可以照搬过来批评C,不用析构函数,难道用free_pages会更简单吗?应该相反,因为这其实是低级语言的特征之一。
如果你批评的是C++的可读性和编程效率,那么你更不应该换成C,因为C的这些缺点更明显。你应该换成高级语言方向,去用Go,
scala,或者Scripting language,他们对实现细节的披露更少,对问题模型的概括更好。
然后,问题领域的特征与设计的选择息息相关。在OS级别上,除了汇编和C/C++,我极少极少看到任何其他语言;在涉及硬件的应用程序方面,C++占了统治地位;在要求高性能单机运算的金融软件方面,C++占了统治地位;在web
programming上,人们越来越多地远离C/C++,甚至远离Java;在Hadoop等并行运算方面,函数编程有很大的优越性。所以,语言特性已经在这里了,关键是需求特征。
就拿你举的Linus关于git的评论来说吧,“完全是屁话。字符串/内存管理根本无关紧要。”为什么?因为git的问题领域是代码管理,不是操作系统。他还有另一个更早的著名辩论,是关于kernel是否用C++的:
1) the whole C++ exception handling thing is fundamentally broken.
It's _especially_ broken for kernels. 2) any compiler or language that
likes to hide things like memory allocations behind your back just
isn't a good choice for a kernel. 3) you can write object-oriented
code (useful for filesystems etc) in C, _without_ the crap that is
C++."
在这里,他的第二个抱怨则是内存管理在C++中比在C中难很多。对照关于git的评论你就可以知道,他说的是针对问题领域,不是solution domain。
所以,回到你对“编程效率”的质疑上来,批评C++没有问题,但是要知道各个语言之间的不同到底是什么。如果批评的是C++的运行性能,那么C是更好的选择;如果批评的是C++的编程效率,那么C更有可能变得更差。
2011/10/22 LeeoNix <leeo...@gmail.com>:
水木 C++ 版最近有个很火的帖子, http://www.newsmth.net/bbstcon.php?board=CPlusPlus&gid=333585
其中我非常同意 pEE 的观点: http://www.newsmth.net/bbscon.php?bid=335&id=333645
就基础数据结构而言,动态数组(vector),双向链表(list),平衡二叉树(set/map),开链式哈希表
(unordered_{map, set})
的性能没什么可挑剔的,通用的容器库最好也就能写成这样了。当然你也可以构造一些特殊的例子把 STL 性能比下去。
On Oct 23, 1:03 pm, LeeoNix <leeoni...@gmail.com> wrote:
> 1999年的书又如何?我不因为你是谁而相信你的权威性。1999年的书的经典性,也是我反复看的一个原因。
>
> 而我没有看到2011年有什么"新的"STL摆在我的面前,如果所谓新的STL,请你给我下载的地方,我去看看STL是不是真的有能统一为一个能用的东西给大家 用。string的效率是不是也足够通用的让我们能够在国际化上站住脚。
>
> 那个C++ 0x修正为C++2011之后,有什么值得让人称赞的地方,我还没看出来。
另外刚才那个结论是有信息论意义的:如果某个压缩算法能够把一个稳定无记忆信源的某些输出序列压缩得小于这个信源的熵,那么这个信源必定存在别的序列输出,被这个压缩算法压缩后大小大于信源的熵。(在压缩算法不知道信源确切输出前,他只能试图去逼近最佳性能;源自渐进均分定理)。很多算法的时空性能分布都可以用这个结论去描述。
On 10/23/11, Shuo Chen <gian...@gmail.com> wrote:
他并没有称自己为大家吧。
和我开始举的例子一样,你去质疑stl为什么不去质疑C库函数像memmove的实现效率呢?仅仅就是因为STL的源码必须公开在头文件?所谓的为了质疑而质疑,就是专拣软柿子捏?更何况前面(把你提出的问题:std::deque,
ACE, QT)都给你解释了,你还是照样不听,去搬出一堆古书和一堆“专家意见”来说明stl不靠谱。不想把你和那些想靠炒作来出名的人类比。
整天吵嚷语言优劣这些月经贴很无趣的。后生小子最近回学校陪女友,有一些观点希望和大家分享。
把你的idea翻译为代码是一个信息压缩的过程。
有时候你发现繁杂的idea,被X语言轻松的用几行代码表达了出来。这说明这种X语言压缩掉了idea中的某些冗余(这种冗余源自你脑海中使用母语对这个idea的编码过程)。
有时候你发现简单的idea,被Y语言写了上千行代码才表达出来,而且还总觉得犹有未尽之意。这说明Y语言在压缩你的idea的时候性能不佳,并且还有误码(如果你的idea有不能被压缩器表达的部分,我们认为压缩器输出长度为无穷大。比方说用JAVA写驱动,我们认为程序代码无穷长)。
等等,信息学渐进均分性定理告诉我们:任何压缩器把某个稳定无记忆的信源压缩输出的平均长度(再次强调:平均长度)必定是信源的熵。那么这也暗示我们,任何一种语言在用代码表达多个不同的idea时,必然同时存在好的结果与坏的结果(只要考察样本够大)。也就是说,任何语言都有他优与劣的地方。所以客观的从信息学的角度上讲,讨论编程语言的编程效率豪无意义!
但是,这个问题也并不是完全没有意义。好的语言(压缩器)可以:让最常见的idea性能尽可能的好,让性能不好的输出一定源自于不常见甚至无意义的输入idea。所以,我们的库函数啊,类库啊,就像压缩算法里的字典一样,让我们常见的idea编程效率最高。
然而什么是最常见的idea呢?我想这就是出现语言之争的时机了,linus说是内核以及系统设计,有的人说是web开发,有的人说是服务器编程,有的人说是游戏开发,还有的人说是嵌入式。。。。。有的人说某些idea无意义是IT民工才干的事情不值得压缩,有的人说有的idea天生比别的高贵(内核开发人员很常见的想法)压缩效率低也应该。
上面的例子我尽可能纯用数学上的东西来说明,直到最后才提到主观因素。大家真的不觉得语言之争其实很可笑吗?把CSDN的月经贴到处散步,很好玩吗?
如果大家有兴趣,我会继续写如何把软件重用与可记忆信源综合,需求变更与非稳定信源综合,最后给出一些定性的结论。
本来不想搭理,只是别人把指头戳到我脑袋上了。
语言而已-________-,至于吗?思想才是最重要的。
语言而已-________-,至于吗?思想才是最重要的。
2011/10/23 yuan zhu <zy49...@gmail.com>:
好久没在TopLanguage发表感慨了。唉,知道大师Dennis的去世那天,我久久盯着屏幕看。悲哀,继Dijkstra之后,又一位真正的大师走了,而我面前所看到的虚拟的东西都源自那位大师。那天我写了不少C代码纪念大师,我认为除此之外没有其他形式值得做。
我很庆幸,我这半年多坚持不用C++只用纯C语言写东西。以前看云风写的Blog说C++的问题,而我也看了Eric Raymond的Unix编程艺术里面对C++的评价。一年多项目结束了,C++也用的熟的不能再熟了。可是我很多地方,真的感觉做了很多无用功。所以,我也效仿马化腾,做出了一个艰难的决定:不用C++写东西,只用C语言。
而C语言好久没有用了。而从新开始用C,本来以为是简化的简单C++,用就是了。可惜我被很多C++习惯给“宠坏”了。
1、变量,该死的变量。
变量不能随意声明了,只能在花括号内声明需要的变量。可以说在C++内,变量随手写是个大优势,但碰到C编译器,它不让你过了,而且该死的编译器并没有直接告诉我是变量的问题,而是其他的问题。起初写的一堆代码,最后发现30%编译不通过都是这个变量声明的问题。我重新审视我自己,我为什么要“随意”的声明变量?记得和大富翁论坛的版主王昊(Soul)在某次聚餐之后,他谈到了过分依赖所谓的随缘最终变成了随便的问题,我很仔细的听他说完了这个有关禅的东西。是的,很多时候把随意变成了随便了,我就像使用便民伞一样,随便拿了,没有还回去。无形中,其实我在做一种对编译器来说不道德的事情。
我用了很久的Delphi,而用Delphi的一个习惯就是变量必须在var关键字下。我一直都认为这是个好习惯,这样用C++就不会出太多问题。不过,我过于乐观了,随意的,或者说“随便”声明的变量,根本不利于静态检查,过于依赖编译器。我花了大概1个星期多的时间,才修正了乱声明变量的习惯。而且像for (int i; i < 100: ++i)这样的i声明方式的习惯,太不容易修改了。
过了一阵子,一个朋友给了我一块C++代码。其实他逻辑写的不错,但是我用了一段时间C代码。看好几个随意声明的变量非常扎眼。我把变量清理到前面声明,然后发现里面有3个变量就是随意声明的,其实作用是无意义的。早就听说过C++非常不利于“静态”检查,现在才明白。很多隐患实际就是坏习惯养成的。
2、析构函数,该死的析构函数。
我还有个坏习惯,就是听了那个Meyers的家伙,多用functor。呵呵,这是个玩笑。其实struct(class?)是个好东西,真的是个好东西,可以在构造函数初始化,析构函数清理它。我很喜欢写一些简单的struct,在栈内存上用,可以随意return,资源什么可以被安全的被清理,不用担心遗忘什么。注意,我又用了“随意”二字。其实……惭愧还是随便。是的虽然不担心资源了,但是大大影响了可读性,还有对返回值的检查。多个return就像筛子的洞一样。而随意的return的根源,是我随意的使用了析构函数。
多个return造成很多地方都不好控制,虽然说我的重构能力还是不错的。用Extract Mothed方式很多地方都模块化了。但是多return的难维护程度超乎我想像,最初我加了goto,跳到最后去干清理的事情,没错就是那个臭名昭著的goto,后来想想goto还是算了……
Delphi,注意,我又提到了Delphi了。呵呵。有个优势就是Result作为function的返回值被使用。其实这也是一个好习惯,有个具体存在的返回值变量。我花了一段时间把很多乱return的地方修改了,主动声明个叫“result”的变量使用,赋值之后才根据情况return,我还把我的Lua代码很多地方也做了类似的修改。数据的流向很容易被控制。
我看到别人转载的Jasone Tee写了一个文章A return to Good Code,看了英文原文才发现CSDN也翻译转载了。但可悲的是看看下面的评论,除了无聊的争吵还是无聊的争吵。看的我有个感觉,很多人就像我住的楼前的黄毛哈巴狗一样,守着自己小小的地盘,对每一个路过的人去乱吠呢?怎么不去试试看写一些一个出口的代码试试看?
3、思念模板,但忍住不用。
3年来,我用C++期间,写了太多的模板的代码了。而且一直都感觉模板是个很好的东西,虽然现在感觉也是个好东西。但C语言没有,有的时候写比较类似的代码,弄个模板就好了。其实是看了Stroustrup在The C++ Programming Language里面写的总结为模板的忠告养成的一个习惯。其实总想用模板的我,让我逐渐养成了“玩”模板的一个坏习惯。绞尽脑汁去想弄成个模板,成为耽误做正事的一个根源,换句话说,真的可以划为奇技淫巧,而模板实际上并没有被用到真正该用到的地方。需要真正去考虑业务代码,而不是玩意儿。因为模板本身就成倍增加了测试量,比单纯写个非模板的代码要麻烦数倍。
4、写个库,然后再写个工具去为库服务。
请看到这里的朋友不要太鄙视我,因为我已经很悲哀了。我编程的经历已经14年了,而且自认为对C/C++很了解了,可惜真的是可悲。针对“参数”这个,类似处理"-c" "-a"这样的代码,我一直都是自己去写的代码去使用参数。我看到一些C的代码去学习之后才发现有这么个东西叫:getopt,我不但悲哀我一直用Windows,还悲哀我们国家这个封闭的环境,还悲哀自己没有去开放的学习。参数这个,Gnu很早就有个getopt的库,而且这个库的历史估计可以追寻到很久以前,你可以手写代码轻易的使用,也可以用一个叫gengetopt的工具,根据某些配置去生成C的代码然后扔给编译器去用。而工具生成的使用getopt代码,是经得起考验的。而工具本身,又是测试和验证库的有理凭据。我很仔细看了gengetopt的chm文档。
我在反复看的《程序设计实践》,Kernighan老家伙和Pike经典的阐述了”记法“这么一章,而这一章我反复看了有20遍以上。这个getopt不仅仅用于main函数的那个argv,在设计简单的字符串记法上,同样有效。其实Lua有个工具叫tolua,还有个tolua++,而我沉迷于模板包装导出函数给Lua用,并没有仔细研究这个工具。
而这种,“写个库,然后写个工具”的东西,在很多古老的代码库里都能看到。而且他们到现在都工作的很好。真的对最初那些用C语言的老家伙们膜拜啊。
5、class的封装真的有那么好吗?
Hub Scott曾经介绍如何肢解了最初的那份string代码。他评论了里面很多不应该写到string里面的方法。造成了string类的臃肿。
如果class仅仅是封装,而写一个class,需要那么多方法吗?我写了一个比较简单的gdi图形库,不用class封装,而是写一个struct封装数据,写了一些内容是围绕这个struct处理的函数。函数的第一个参数传递这个struct指针,这样的写法其实与设计一个基本的class封装是等效的。而使用class的时候,那个隐藏的this,无形中会让人不知道什么该放进来,什么该扔出去。Python做的真的很好,self必须写,起初感觉很麻烦,多写个self干吗,逐渐我改变了这个看法,就应该写上,写上了才知道是不是属于这个类应该有的。而使用C++主动加this->的方式,已经被很多人提及是个好习惯了。
我回顾了以前的一些代码,发现很多类内容没多大关系的,也被我扔进去了。真的很不利于维护,而且有些地方明显是多余的。我要又一次提到随便了,为了随便去随便真的不是个好习惯。
Hub Scott介绍过另一个事情,是写一个栈的方式。他提到最好不要用继承,用内含。而最近我才看到,最初给Stroustrup提出加protected的那个人,其实他以后后悔了。
我自从我不用那些,什么多态啊,什么继承啊,什么封装啊之后,发现干活也没什么问题,地球也在转,我的程序也在转。而以前我为什么迷信这些呢,不是用OOP写的东西,我就持怀疑甚至抨击的态度?真的是对OOP狂热痴迷到了病态。我反复看《Unix编程艺术》,Eric Raymond对C++的评价还是相对客观的,我最近才知道Alex Stepanov竟然一直都持质疑态度。
6、干好一件事。
Doug McIlroy说:让每个程序都干好一件事。如果有新任务,就重新开始,不要往原程序中加入新功能而搞的复杂。
简单性,是作程序起始,过来人都告诫,简单性的问题。可是一直对简单性有个真正的标准。而Doug McIlroy给了个标准,干好一件事。而坚持用C写代码,才重新审视这个干好一件事的问题。因为被OO狂热的洗脑后干什么都写个class让我习惯什么都得扔到一起,其实怪不得C++,是我的问题。
FIXprotocol设计的是证券交易使用的传输协议。因为工作的缘故,接触了这个公司设计的FAST协议,现在上海的证券交易也是在使用这个。fixprotocol提供的fastapi的C代码库,写的真的干净优雅,认真的干好一件事而没做多余的事情,这里可以下载看看。我看了这个给我的感觉是,我这些年到底做了些什么,怎么写的代码就没长进?
那什么才是“干好一件事”,还是Hub Scott写那个Stack例子,看完之后曾经和别人争论过Pop要不要返回值的事情。而STL也是这么做的,pop是pop,而top是top,传统介绍栈的描述,遵循了“弹出”这个概念,pop是有返回值。而现在用STL的栈,逐渐都接受了top结合pop的方式。
我继续重新审视以前写的代码。那个所谓封装的D3D的类,其结构严重违反干好一件事的原则,唉,越看越觉得,觉得……真的很难堪。
我不记得这个讨论。但我的印象里,这方面C++里的规则没什么复杂的:一个含
虚函数的类有一张虚表,每个含虚函数的对象里有一个指针指向这张虚表。虚表
应当是全局的,所以我不太理解“虚表清空”这样的问题(野指针?)。
虚继承会更复杂,但我想大部分人都不用吧。我从来没用过。
>
> 第三个问题,其实还是和第二个问题一类。我倾向于你对于第二个问题的总
> 结。就我而言,其实是大型系统经验导致的。其实这个有的中国国情的特色,
> 说老实话,起初编写代码的人,都是一些西部牛仔,单枪匹马的干,团队意识
> 薄弱。而中国对于代码会议的组织也偏弱,也因为面子问题或者其他问题,不
> 能踊跃的提出自己遇到的问题,而且程序员的普遍内向,要不就唯我独尊谁都
> 不服,两极分化的不得了。指出自己的错误,指出自己的错误,不仅仅能提高
> 自己也提高大家。
需要强制推行代码评审。我们的规定是不通过代码评审,只能签入到SVN的分枝
上。
>
> 我举个我的例子,隐含的类型转化的问题,有个同事就提到自己的问题,
> if (有符号数 <无符号数),这时候,有符号数会隐形的转化为无符号数,这
> 样符号位让有符号数的永远都比无符号数要大。而这个同事比较单纯,很勇敢
> 的把自己的问题说出来,我发现除了我这个什么书都看的人,在C专家编程那
> 里知道了这个问题。而除我之外在场的所有人都不知道这个地方,都以为,应
> 该是可以的。
这个正好知道。并不是都向无符号数转,而是往能表达更大正整数的类型转。
int和unsigned short比,结果是转成int比。int和unsigned int,当然是转成
unsigned int。
>
> 我组织过几次,其实效果很好,有的时候分配的工作找不到思路也可以大家讨
> 论一下,比如当时写魔法系统的,面对策划的变态条件,不知道如何是好了,
> 大家七嘴八舌的说了一些方案,虽然说可以被采纳的不多,但给他很有效的拓
> 展了思路。还有代码审查的制度并没有建立,没有一个可信的有经验的人去把
> 控提交到核心仓库的代码。
这才是关键。哪怕是三个臭皮匠一起看,也是好的。
>
> 而这点,其实还是你总结的问题,问题在语言之外。
这就是了。语言之外往往更关键。
--
Wu Yongwei
URL: http://wyw.dcweb.cn/
2 、析构函数,该死的析构函数。
理由 同 1
3、思念模板,但忍住不用。
再合适的地方使用。C++程序员常犯的错误就是。那个锤子,全世界都是钉子。玩熟了模板,什么地方都想用。
4、写个库,然后再写个工具去为库服务。
这个很赞同。
5、class的封装真的有那么好吗?
理由同3
遇到这种问题通常是没好好设计。
C++给了太多了自由,这种自由又纵容了程序员们。形成了OO流、stl流、模板流等等(参考C++的十大流派)
相比C语言提供语言级别的特性真的很少,所以写出来的代码风格差异比较小,这也是通常说的C程序员更注重流程。
C++程序员要么把C++当成C with class,要么在深入研究特性的路上。
能够解脱语言的禁锢,合理的使用C++的真是太少了。
On 10月21日, 下午11时49分, LeeoNix <leeoni...@gmail.com> wrote:
> 好久没在TopLanguage发表感慨了。唉,知道大师Dennis的去世那天,我久久盯着屏幕看。悲哀,继Dijkstra之后,又一位真正的大师走了,而我面前所看到的虚拟的东西都源自那位大师。那天我写了不少C代码纪念大师,我认为除此之外没有其他形式值得做。
>
> 我很庆幸,我这半年多坚持不用C++只用纯C语言写东西。以前看云风写的Blog说C++的问题,而我也看了Eric
> Raymond的Unix编程艺术里面对C++的评价。一年多项目结束了,C++也用的熟的不能再熟了。可是我很多地方,真的感觉做了很多无用功。所以,我也效仿马化腾,做出了一个艰难的决定:不用C++写东西,只用C语言。
>
> 而C语言好久没有用了。而从新开始用C,本来以为是简化的简单C++,用就是了。可惜我被很多C++习惯给“宠坏”了。
>
> 1、变量,该死的变量。
>
> 变量不能随意声明了,只能在花括号内声明需要的变量。可以说在C++内,变量随手写是个大优势,但碰到C编译器,它不让你过了,而且该死的编译器并没有直接告诉我是变量的问题,而是其他的问题。起初写的一堆代码,最后发现30%编译不通过都是这个变量声明的问题。我重新审视我自己,我为什么要“随意”的声明变量?记得和大富翁论坛的版主王昊(Soul)在某次聚餐之后,他谈到了过分依赖所谓的随缘最终变成了随便的问题,我很仔细的听他说完了这个有关禅的东西。是的,很多时候把随意变成了随便了,我就像使用便民伞一样,随便拿了,没有还回去。无形中,其实我在做一种对编译器来说不道德的事情。
>
> 我用了很久的Delphi,而用Delphi的一个习惯就是变量必须在var关键字下。我一直都认为这是个好习惯,这样用C++就不会出太多问题。不过,我过于乐观了,随意的,或者说“随便”声明的变量,根本不利于静态检查,过于依赖编译器。我花了大概1个星期多的时间,才修正了乱声明变量的习惯。而且像for
> (int i; i < 100: ++i)这样的i声明方式的习惯,太不容易修改了。
>
> 过了一阵子,一个朋友给了我一块C++代码。其实他逻辑写的不错,但是我用了一段时间C代码。看好几个随意声明的变量非常扎眼。我把变量清理到前面声明,然后发现里面有3个变量就是随意声明的,其实作用是无意义的。早就听说过C++非常不利于“静态”检查,现在才明白。很多隐患实际就是坏习惯养成的。
>
> 2、析构函数,该死的析构函数。
>
> 我还有个坏习惯,就是听了那个Meyers的家伙,多用functor。呵呵,这是个玩笑。其实struct(class?)是个好东西,真的是个好东西,可以在构造函数初始化,析构函数清理它。我很喜欢写一些简单的struct,在栈内存上用,可以随意return,资源什么可以被安全的被清理,不用担心遗忘什么。注意,我又用了“随意”二字。其实……惭愧还是随便。是的虽然不担心资源了,但是大大影响了可读性,还有对返回值的检查。多个return就像筛子的洞一样。而随意的return的根源,是我随意的使用了析构函数。
>
> 多个return造成很多地方都不好控制,虽然说我的重构能力还是不错的。用Extract
> Mothed方式很多地方都模块化了。但是多return的难维护程度超乎我想像,最初我加了goto,跳到最后去干清理的事情,没错就是那个臭名昭著的goto,后来想想goto还是算了……
>
> Delphi,注意,我又提到了Delphi了。呵呵。有个优势就是Result作为function的返回值被使用。其实这也是一个好习惯,有个具体存在的返回值变量。我花了一段时间把很多乱return的地方修改了,主动声明个叫“result”的变量使用,赋值之后才根据情况return,我还把我的Lua代码很多地方也做了类似的修改。数据的流向很容易被控制。
>
> 我看到别人转载的Jasone Tee写了一个文章A return to Good
> Code<http://www.theserverside.com/tip/A-return-to-Good-Code>
> ,看了英文原文才发现CSDN也翻译转载 <http://sd.csdn.net/a/20110323/294448.html>
> 了。但可悲的是看看下面的评论,除了无聊的争吵还是无聊的争吵。看的我有个感觉,很多人就像我住的楼前的黄毛哈巴狗一样,守着自己小小的地盘,对每一个路过的人去乱吠呢?怎么不去试试看写一些一个出口的代码试试看?
>
> 3、思念模板,但忍住不用。
>
> 3年来,我用C++期间,写了太多的模板的代码了。而且一直都感觉模板是个很好的东西,虽然现在感觉也是个好东西。但C语言没有,有的时候写比较类似的代码,弄个模板就好了。其实是看了Stroustrup在The
> C++ Programming
> Language里面写的总结为模板的忠告养成的一个习惯。其实总想用模板的我,让我逐渐养成了“玩”模板的一个坏习惯。绞尽脑汁去想弄成个模板,成为耽误做正事的一个根源,换句话说,真的可以划为奇技淫巧,而模板实际上并没有被用到真正该用到的地方。需要真正去考虑业务代码,而不是玩意儿。因为模板本身就成倍增加了测试量,比单纯写个非模板的代码要麻烦数倍。
>
> 4、写个库,然后再写个工具去为库服务。
>
> 请看到这里的朋友不要太鄙视我,因为我已经很悲哀了。我编程的经历已经14年了,而且自认为对C/C++很了解了,可惜真的是可悲。针对“参数”这个,类似处理"-c"
> "-a"这样的代码,我一直都是自己去写的代码去使用参数。我看到一些C的代码去学习之后才发现有这么个东西叫:getopt,我不但悲哀我一直用Windows,还悲哀我们国家这个封闭的环境,还悲哀自己没有去开放的学习。参数这个,Gnu很早就有个getopt的库,而且这个库的历史估计可以追寻到很久以前,你可以手写代码轻易的使用,也可以用一个叫gengetopt的工具,根据某些配置去生成C的代码然后扔给编译器去用。而工具生成的使用getopt代码,是经得起考验的。而工具本身,又是测试和验证库的有理凭据。我很仔细看了gengetopt的chm文档。
>
> 我在反复看的《程序设计实践》,Kernighan老家伙和Pike经典的阐述了”记法“这么一章,而这一章我反复看了有20遍以上。这个getopt不仅仅用于main函数的那个argv,在设计简单的字符串记法上,同样有效。其实Lua有个工具叫tolua,还有个tolua++,而我沉迷于模板包装导出函数给Lua用,并没有仔细研究这个工具。
>
> 而这种,“写个库,然后写个工具”的东西,在很多古老的代码库里都能看到。而且他们到现在都工作的很好。真的对最初那些用C语言的老家伙们膜拜啊。
>
> 5、class的封装真的有那么好吗?
>
> Hub Scott曾经介绍如何肢解了最初的那份string代码。他评论了里面很多不应该写到string里面的方法。造成了string类的臃肿。
>
> 如果class仅仅是封装,而写一个class,需要那么多方法吗?我写了一个比较简单的gdi图形库,不用class封装,而是写一个struct封装数据,写了一些内容是围绕这个struct处理的函数。函数的第一个参数传递这个struct指针,这样的写法其实与设计一个基本的class封装是等效的。而使用class的时候,那个隐藏的this,无形中会让人不知道什么该放进来,什么该扔出去。Python做的真的很好,self必须写,起初感觉很麻烦,多写个self干吗,逐渐我改变了这个看法,就应该写上,写上了才知道是不是属于这个类应该有的。而使用C++主动加this->的方式,已经被很多人提及是个好习惯了。
>
> 我回顾了以前的一些代码,发现很多类内容没多大关系的,也被我扔进去了。真的很不利于维护,而且有些地方明显是多余的。我要又一次提到随便了,为了随便去随便真的不是个好习惯。
>
> Hub
> Scott介绍过另一个事情,是写一个栈的方式。他提到最好不要用继承,用内含。而最近我才看到,最初给Stroustrup提出加protected的那个人,其实他以后后悔了。
> 我自从我不用那些,什么多态啊,什么继承啊,什么封装啊之后,发现干活也没什么问题,地球也在转,我的程序也在转。而以前我为什么迷信这些呢,不是用OOP写的东西,我就持怀疑甚至抨击的态度?真的是对OOP狂热痴迷到了病态。我反复看《Unix编程艺术》,Eric
> Raymond对C++的评价还是相对客观的,我最近才知道Alex Stepanov竟然一直都持质疑态度。
>
> 6、干好一件事。
>
> Doug McIlroy说:让每个程序都干好一件事。如果有新任务,就重新开始,不要往原程序中加入新功能而搞的复杂。
> 简单性,是作程序起始,过来人都告诫,简单性的问题。可是一直对简单性有个真正的标准。而Doug
> McIlroy给了个标准,干好一件事。而坚持用C写代码,才重新审视这个干好一件事的问题。因为被OO狂热的洗脑后干什么都写个class让我习惯什么都得扔到一起,其实怪不得C++,是我的问题。
>
> FIXprotocol <http://www.fixprotocol.org/>设计的是证券交易使用的传输协议。因为工作的缘故,接触了这个公司设计的
> FAST <http://www.fixprotocol.org/fast>
> 协议,现在上海的证券交易也是在使用这个。fixprotocol提供的fastapi的C代码库,写的真的干净优雅,认真的干好一件事而没做多余的事情,这里<http://www.fixprotocol.org/documents/2317/fastapi-1.0.zip>
我在上家公司也干过这事请,但似乎大家不领情。该咋办还咋办,出问题了找我,写出来的代码惨不忍睹啊。
> 后面有代码规范之余,我还在项目里维护了一个Wiki,题目就是,不能干XX,必须干XX,列举了一堆不能干,必须干的事情。出了某个问题我就加上,几个人我都是晚上手把手教必须怎么怎么写。可是怎么总是会出一些问题呢?其实这个一直是我反思的问题。其实这个是当初我们那个团队管理方面的一些问题。
>
> 围绕这个我这个WIki所说,组织一些会用C++,但C++技艺没那么好的人。真的有点累。可惜没的选择,只能用C++。
On 10月23日, 下午2时33分, LeeoNix <leeoni...@gmail.com> wrote:
> 有关编码效率的问题,我发现和你有分歧,所以多说一下我的看法。
>
> 首先我请你相信我是一个一年内在Windows和Linux都有几千行以上编写C++代码经验的程序员。
>
> 说老实话,编码效率,是"写"完代码的效率,还是一段时间"写"完"能用"的代码。这点值得商榷。
>
> 用C++或许你写代码写的很快,但是有时候一个很低级的错误,能让你半天摸不着头脑,是很让人气愤的,尤其写代码的不是你。所以这也是我开篇描述那么多习惯的焦点。
>
> 有时候,别人写的代码也是如此,说白了无非是编码习惯的问题。可是C++培训的良莠不齐,有时候项目里设立一个编码标准,也不一定能让人读懂。
>
> 促使我用CppCheck的一个原因,是有一次,我查了一个晚上的问题,最终发现竟然一个存在与class的变量没有初始化。而这个问题,半小时才可能出现一次。他们好几个人轮番找,最终找不到这个Bug,就找到我。所以我因此奋战了11个小时。找出问题之后,气得我砸桌子砸的手疼,我还不能朝写代码的人发火。
>
> 而像CppCheck这样的工具,静态找到的问题,也无非就是变量有没有初始化等等很基础的问题。有些比较复杂的问题,就查不出来了。如果再出现半小时才出现一次的问题,那头疼的不是我了,呵呵,我早就不在了。
>
> 静态检查,不知道有没有比CppCheck更好的工具,推荐一下。
>
> 后面有代码规范之余,我还在项目里维护了一个Wiki,题目就是,不能干XX,必须干XX,列举了一堆不能干,必须干的事情。出了某个问题我就加上,几个人我都是晚上手把手教必须怎么怎么写。可是怎么总是会出一些问题呢?其实这个一直是我反思的问题。其实这个是当初我们那个团队管理方面的一些问题。
>
> 围绕这个我这个WIki所说,组织一些会用C++,但C++技艺没那么好的人。真的有点累。可惜没的选择,只能用C++。
>
> 有的时候,某些人移交代码给别人做。然后本人干别的去了。代码风格泾渭分明的看的出来是两个人写的。
>
> 我为什么那么反感STL,就是很多人不熟悉STL,写很多使用STL的代码让我感到很无奈。像类似void push( std::set<int>
> section
> )这样的代码,当我看到说,为什么不用引用?他说,我看别人这么写,我就这么写了。我只能扶着额头,"勒令"他修改所有类似的代码,这不怪他,用和不用引用的效率是差一个档次的,而这个他不知道怪不得他。
>
> 而我在接触C语言代码,我才发现。用工具生成骨架代码,是避免一些问题的一个有效途经。但骨架代码的前提,就是有合适的库和框架支持。
>
> 可我到现在,真的不知道有什么更好的途经,能提高编码效率。让普通熟悉的C++程序员能更好的做事,而不需要知道边边角角的东西。
>
> 在 2011年10月23日 下午12:28,Yuantai Du <yuantai...@gmail.com>写道:
>
>
>
>
>
>
>
> > 在我们说完C++的缺点之后,我们要说未来的方向是什么----是向高级语言的方向走,还是向低级语言的方向走。
>
> > 你的标题让我感觉你想向低级语言方向走,而你辩论的多数内容,让我感觉是在批判C++的低级性。
>
> > 什么是高级语言的特征?设计特征更向subject
> > domain的内在概念关系靠拢,就是说,更容易概括问题领域的模型,而实现细节揭露得更少。而低级语言呢?更与机器的实现细节相关,因此较难有清晰的设计。
>
> > 你批评的东西,最初的一篇中的弱类型和析构函数都可以照搬过来批评C,不用析构函数,难道用free_pages会更简单吗?应该相反,因为这其实是低级语言的特征之一。
>
> > 如果你批评的是C++的可读性和编程效率,那么你更不应该换成C,因为C的这些缺点更明显。你应该换成高级语言方向,去用Go,
> > scala,或者Scripting language,他们对实现细节的披露更少,对问题模型的概括更好。
>
> > 然后,问题领域的特征与设计的选择息息相关。在OS级别上,除了汇编和C/C++,我极少极少看到任何其他语言;在涉及硬件的应用程序方面,C++占了统治地位;在要求高性能单机运算的金融软件方面,C++占了统治地位;在web
>
> > programming上,人们越来越多地远离C/C++,甚至远离Java;在Hadoop等并行运算方面,函数编程有很大的优越性。所以,语言特性已经在这里了,关键是需求特征。
>
> > 就拿你举的Linus关于git的评论来说吧,"完全是屁话。字符串/内存管理根本无关紧要。"为什么?因为git的问题领域是代码管理,不是操作系统。他还有另一个更早的著名辩论,是关于kernel是否用C++的:
> > 1) the whole C++ exception handling thing is fundamentally broken.
> > It's _especially_ broken for kernels. 2) any compiler or language that
> > likes to hide things like memory allocations behind your back just
> > isn't a good choice for a kernel. 3) you can write object-oriented
> > code (useful for filesystems etc) in C, _without_ the crap that is
> > C++."
> > 在这里,他的第二个抱怨则是内存管理在C++中比在C中难很多。对照关于git的评论你就可以知道,他说的是针对问题领域,不是solution
> > domain。
>
> > 所以,回到你对"编程效率"的质疑上来,批评C++没有问题,但是要知道各个语言之间的不同到底是什么。如果批评的是C++的运行性能,那么C是更好的选择;如果批评的是C++的编程效率,那么C更有可能变得更差。
>
> > 2011/10/22 LeeoNix <leeoni...@gmail.com>:
> > > 看到这里,我很质疑你说的"编程效率"的评价。但我对此不做评价,因为我已经不是面向对象的狂热者了,所谓的面向对象的效率,我这么多年没见有多好过。
>
> > > 说到这里又让我想起Linus的有关git的骂架了。其实Linus在那个有关git骂架里面,开始言辞激烈,后面却说得很中肯。
>
> > > 一句话总结:C++让人没有把心放到业务上。
>
> > Linus为了设计git,甚至用Shell和Perl设计原型,然后逐渐替代这些代码。最初的git确实很不易用,但是git的核心很早就被设计好了,外面的修正为易用就好了。
>
> > 那个骂架过去很久了,git现在很流行。而我越来越看Linus的骂架顺眼了,不是个人崇拜的相信,是经历过之后才感觉Linus其实不管是不是言辞激烈,说的都是真正的技术争论,而且说的中肯。
>
> > 特别Linus批评的,"完全是屁话。字符串/内存管理根本无关紧要。还是去看看源代码吧(我敢打赌你没有看过)。这不是重要的部分,而且也不复杂。唯一真正重要的部分是设计。"
>
> > > 我过了这么久才明白这个。Dmitry
>
> > Kakurin和其他C++程序员一样,还是一个Coder,没有一个跳出去看项目的角度分析业务,看设计,而着眼于这些细节。其实这就是C++程序员的通病,而我作为C++程序员的一员,其实也是如此。而分析业务,设计的能力,和Java程序员比起来,简直让人羞愧,我也曾经作为羞愧的C++程序员一员,去批评Java的效率问题,但Java效率再差也把项目漂亮的搞好了。
>
> > > 程序设计语言无形中影响了人的思维方式。
>
> > > Linus和Dmitry Kakurin说设计,而Dmitry
>
> > Kakurin却在批评git的细节。然后我退一千步,做git的不是Linus,而是其他人,他的技术没有Linus那么牛,但是他很好的完成了git的核心业务,效率再差,也被快速开发为一个产品投放使用了,剩下的就是调优而已。何况Linus亲自操刀。
>
> > > 而实际的项目里,项目带头人唯技术先进的,毁了多少项目。比如我举个实际的例子,不是国外的。
>
> > 阿里巴巴贸易通,以前就是个垃圾技术生成的IM,很多东西没做好实际上是用网页做的,虽然烂但是他快速投放市场了,大家接受这个产品了。而现在淘宝旺旺到阿里旺旺的版本,阿里巴巴在这方面做的很出色。而相比,盛大的圈圈项目,吹了那么久。就我在盛大的那段时间内,整整一年就没看到一个完整的东西出来,就是内部用的版本也是麻烦不断,我很是费解。现在你在世面上还看得到有人在用盛大圈圈吗?
>
> > > 反思啊。所以才艰难的决定就是:不用C++
>
> > > 在 2011年10月23日 上午12:30,Yuantai Du <yuantai...@gmail.com>写道:
>
> > >> C++的优势体现在其运行效率和编程效率的统一上。其他的大多数编程语言,从Smalltalk,java,
> > >> c#到Go,有足够高的编程效率,但是其编译后的运行效率则无法和C++相比,更不用说scripting
>
> > language了。这是由于这些高级语言的设计中,本身就已经包含了很多的masking,所以,在大多数时候,他们编程效率的提高隐含了运行峰值的下降。C++由于保留了C的大多数底层特性,所以保留了足够人工调整运行效率的空间。C语言有足够的运行效率,但是其编程效率比面对对象要差太多了。所以被局限在了底层编程。一个例外是苹果的ObjectiveC,
> > >> 使用了大量的宏来达到面对对象。不知以后objective c 能否扩展到其他领域。
>
> ...
>
> 阅读更多 >>
我自己的感觉:
如果要用 C/C++ 开发比较大的项目, 除非整个团队都有相当的经验, 并且稳定性很好, 否则这个项目要么是起步就会出问题, 要么就是做好以后
代码库腐化得非常快.
整个团队都有相当的经验:
可以向代码库中提交代码的人, C/C++ 基本技术要过关, 同时对系统的理解要足够, 否则什么样的乱子都会出, 而这些低级语言出乱子之后,
由于指针, array index 没有检查, 内存管理之类的问题, bug 会隐蔽扩散, 一个初级程序员弄出来的问题, 如果commit 代
码的时候没有检查出来, 混进了代码库, 多半最后可能需要一个资深程序员相当的时间才能解决.
团队稳定性很好:
由于C/C++ 底层库的缺乏, 各家多半都有不少自作的轮子, 这些自做的轮子, 内部很多时候隐藏着很多没有文档化的假设和约定, 更糟糕的时
候, 内部可能还存在一些不一致性, 使用起来需要有很多需要注意的地方, 而且, 很要命, 熟悉了这个系统的程序员, 已经习惯了这些做法, 可能
并没有意识到这些地方的风险性而将这些风险揭示出来.
在这种情况下, 每次新加入一个程序员, 就会带来相当多的风险给代码库引入很多隐患; 如果某一个时刻, 这个项目的老程序员离开了, 整个代码库
就面临极大的风险, 新入的程序员, 在"似乎" 已经搞清楚情况下的编程和重构, 可能已经破坏掉了原有代码的隐式约定, 造成bug 重重, 即使
后来经过辛苦的努力, 清除掉了这些 bug, 但是可能代码库又腐化了一大步.
Java, Python, C# 等语言, 由于基础类库比较齐备, 自造的轮子少很多, 同时处理的问题较高层, 很多时候有现成的框架可以
用, 使用现成的框架, 很多约定就是已经明确定义好了; 加上高层语言限制性较多, 很多时候做什么事情, 大家都用差不多的方法, 陷阱, 隐藏
约定等问题少很多, 团队成员的变化带来的风险也就小了很多.
> 2011/10/21 LeeoNix <leeoni...@gmail.com>
>
>
>
> > 好久没在TopLanguage发表感慨了。唉,知道大师Dennis的去世那天,我久久盯着屏幕看。悲哀,继Dijkstra之后,又一位真正的大师走了,而我面前所看到的虚拟的东西都源自那位大师。那天我写了不少C代码纪念大师,我认为除此之外没有其他形式值得做。
>
> > 我很庆幸,我这半年多坚持不用C++只用纯C语言写东西。以前看云风写的Blog说C++的问题,而我也看了Eric
> > Raymond的Unix编程艺术里面对C++的评价。一年多项目结束了,C++也用的熟的不能再熟了。可是我很多地方,真的感觉做了很多无用功。所以,我也效仿马化腾,做出了一个艰难的决定:不用C++写东西,只用C语言。
>
> > 而C语言好久没有用了。而从新开始用C,本来以为是简化的简单C++,用就是了。可惜我被很多C++习惯给"宠坏"了。
>
> > 1、变量,该死的变量。
>
> > 变量不能随意声明了,只能在花括号内声明需要的变量。可以说在C++内,变量随手写是个大优势,但碰到C编译器,它不让你过了,而且该死的编译器并没有直接告诉我是变量的问题,而是其他的问题。起初写的一堆代码,最后发现30%编译不通过都是这个变量声明的问题。我重新审视我自己,我为什么要"随意"的声明变量?记得和大富翁论坛的版主王昊(Soul)在某次聚餐之后,他谈到了过分依赖所谓的随缘最终变成了随便的问题,我很仔细的听他说完了这个有关禅的东西。是的,很多时候把随意变成了随便了,我就像使用便民伞一样,随便拿了,没有还回去。无形中,其实我在做一种对编译器来说不道德的事情。
>
> > 我用了很久的Delphi,而用Delphi的一个习惯就是变量必须在var关键字下。我一直都认为这是个好习惯,这样用C++就不会出太多问题。不过,我过于乐观了,随意的,或者说"随便"声明的变量,根本不利于静态检查,过于依赖编译器。我花了大概1个星期多的时间,才修正了乱声明变量的习惯。而且像for
> > (int i; i < 100: ++i)这样的i声明方式的习惯,太不容易修改了。
>
> > 过了一阵子,一个朋友给了我一块C++代码。其实他逻辑写的不错,但是我用了一段时间C代码。看好几个随意声明的变量非常扎眼。我把变量清理到前面声明,然后发现里面有3个变量就是随意声明的,其实作用是无意义的。早就听说过C++非常不利于"静态"检查,现在才明白。很多隐患实际就是坏习惯养成的。
>
> > 2、析构函数,该死的析构函数。
>
> ...
>
> read more >>
函数长度应尽量不超过50行,超过200行需要组长批准。一次评审代码长度不超过400行。
2011/10/24 akirya(坏[其实我不是什么所谓的坏人]) <aki...@gmail.com>:
> 1、变量,该死的变量。
> 随意定义变量也没啥不好,函数较长的话,随意定义变量的优势就体现出来。
> 但是如果一边想一边写代码的时候,充分证明了一个问题,写函数之前没好好规划,没想过。
> 随意定义变量也变相了纵容这种做法。
> 如果遇到这样的人,就算规定变量必须声明在函数开始,那么也是一边写,一边往前面添加变量声明。
> 见过一个函数前面有200多行的变量声明不?遇到这样的函数谁还有心看下去?
>
> 2 、析构函数,该死的析构函数。
> 理由 同 1
>
> 3、思念模板,但忍住不用。
> 再合适的地方使用。C++程序员常犯的错误就是。那个锤子,全世界都是钉子。玩熟了模板,什么地方都想用。
>
> 4、写个库,然后再写个工具去为库服务。
> 这个很赞同。
>
> 5、class的封装真的有那么好吗?
> 理由同3
> 遇到这种问题通常是没好好设计。
>
>
> C++给了太多了自由,这种自由又纵容了程序员们。形成了OO流、stl流、模板流等等(参考C++的十大流派)
> 相比C语言提供语言级别的特性真的很少,所以写出来的代码风格差异比较小,这也是通常说的C程序员更注重流程。
>
> C++程序员要么把C++当成C with class,要么在深入研究特性的路上。
> 能够解脱语言的禁锢,合理的使用C++的真是太少了。
--
2011/10/24 LeeoNix <leeo...@gmail.com>:
> 嗯,虚表会因为。比如在构造函数写入比较通用的:memset(this, 0,
> *this);这样的初始化方式被清空。而对于不存在虚表的struct或者class,这
> 个memset是清理的一个比较好的方法。还有一些其他的对于指针操作不当的问
> 题,会指向虚表而造成的虚表改写。反正就是“不正常”的技巧造成的,属于
> C++独有。
--
所以,你可以用Objective-C,试试吧,仍旧100%兼容C(C++不确保100%兼容C,如果你懂C++你就知道我说的啥意思),而且真的面向对象的,而且有一个非常棒的类库,没有C++的一切负担。
好久没在TopLanguage发表感慨了。唉,知道大师Dennis的去世那天,我久久盯着屏幕看。悲哀,继Dijkstra之后,又一位真正的大师走了,而我面前所看到的虚拟的东西都源自那位大师。那天我写了不少C代码纪念大师,我认为除此之外没有其他形式值得做。
我很庆幸,我这半年多坚持不用C++只用纯C语言写东西。以前看云风写的Blog说C++的问题,而我也看了Eric Raymond的Unix编程艺术里面对C++的评价。一年多项目结束了,C++也用的熟的不能再熟了。可是我很多地方,真的感觉做了很多无用功。所以,我也效仿马化腾,做出了一个艰难的决定:不用C++写东西,只用C语言。
而C语言好久没有用了。而从新开始用C,本来以为是简化的简单C++,用就是了。可惜我被很多C++习惯给“宠坏”了。
1、变量,该死的变量。
变量不能随意声明了,只能在花括号内声明需要的变量。可以说在C++内,变量随手写是个大优势,但碰到C编译器,它不让你过了,而且该死的编译器并没有直接告诉我是变量的问题,而是其他的问题。起初写的一堆代码,最后发现30%编译不通过都是这个变量声明的问题。我重新审视我自己,我为什么要“随意”的声明变量?记得和大富翁论坛的版主王昊(Soul)在某次聚餐之后,他谈到了过分依赖所谓的随缘最终变成了随便的问题,我很仔细的听他说完了这个有关禅的东西。是的,很多时候把随意变成了随便了,我就像使用便民伞一样,随便拿了,没有还回去。无形中,其实我在做一种对编译器来说不道德的事情。
我用了很久的Delphi,而用Delphi的一个习惯就是变量必须在var关键字下。我一直都认为这是个好习惯,这样用C++就不会出太多问题。不过,我过于乐观了,随意的,或者说“随便”声明的变量,根本不利于静态检查,过于依赖编译器。我花了大概1个星期多的时间,才修正了乱声明变量的习惯。而且像for (int i; i < 100: ++i)这样的i声明方式的习惯,太不容易修改了。
过了一阵子,一个朋友给了我一块C++代码。其实他逻辑写的不错,但是我用了一段时间C代码。看好几个随意声明的变量非常扎眼。我把变量清理到前面声明,然后发现里面有3个变量就是随意声明的,其实作用是无意义的。早就听说过C++非常不利于“静态”检查,现在才明白。很多隐患实际就是坏习惯养成的。
2、析构函数,该死的析构函数。
我还有个坏习惯,就是听了那个Meyers的家伙,多用functor。呵呵,这是个玩笑。其实struct(class?)是个好东西,真的是个好东西,可以在构造函数初始化,析构函数清理它。我很喜欢写一些简单的struct,在栈内存上用,可以随意return,资源什么可以被安全的被清理,不用担心遗忘什么。注意,我又用了“随意”二字。其实……惭愧还是随便。是的虽然不担心资源了,但是大大影响了可读性,还有对返回值的检查。多个return就像筛子的洞一样。而随意的return的根源,是我随意的使用了析构函数。
多个return造成很多地方都不好控制,虽然说我的重构能力还是不错的。用Extract Mothed方式很多地方都模块化了。但是多return的难维护程度超乎我想像,最初我加了goto,跳到最后去干清理的事情,没错就是那个臭名昭著的goto,后来想想goto还是算了……
Delphi,注意,我又提到了Delphi了。呵呵。有个优势就是Result作为function的返回值被使用。其实这也是一个好习惯,有个具体存在的返回值变量。我花了一段时间把很多乱return的地方修改了,主动声明个叫“result”的变量使用,赋值之后才根据情况return,我还把我的Lua代码很多地方也做了类似的修改。数据的流向很容易被控制。
我看到别人转载的Jasone Tee写了一个文章A return to Good Code,看了英文原文才发现CSDN也翻译转载了。但可悲的是看看下面的评论,除了无聊的争吵还是无聊的争吵。看的我有个感觉,很多人就像我住的楼前的黄毛哈巴狗一样,守着自己小小的地盘,对每一个路过的人去乱吠呢?怎么不去试试看写一些一个出口的代码试试看?
3、思念模板,但忍住不用。
3年来,我用C++期间,写了太多的模板的代码了。而且一直都感觉模板是个很好的东西,虽然现在感觉也是个好东西。但C语言没有,有的时候写比较类似的代码,弄个模板就好了。其实是看了Stroustrup在The C++ Programming Language里面写的总结为模板的忠告养成的一个习惯。其实总想用模板的我,让我逐渐养成了“玩”模板的一个坏习惯。绞尽脑汁去想弄成个模板,成为耽误做正事的一个根源,换句话说,真的可以划为奇技淫巧,而模板实际上并没有被用到真正该用到的地方。需要真正去考虑业务代码,而不是玩意儿。因为模板本身就成倍增加了测试量,比单纯写个非模板的代码要麻烦数倍。
4、写个库,然后再写个工具去为库服务。
请看到这里的朋友不要太鄙视我,因为我已经很悲哀了。我编程的经历已经14年了,而且自认为对C/C++很了解了,可惜真的是可悲。针对“参数”这个,类似处理"-c" "-a"这样的代码,我一直都是自己去写的代码去使用参数。我看到一些C的代码去学习之后才发现有这么个东西叫:getopt,我不但悲哀我一直用Windows,还悲哀我们国家这个封闭的环境,还悲哀自己没有去开放的学习。参数这个,Gnu很早就有个getopt的库,而且这个库的历史估计可以追寻到很久以前,你可以手写代码轻易的使用,也可以用一个叫gengetopt的工具,根据某些配置去生成C的代码然后扔给编译器去用。而工具生成的使用getopt代码,是经得起考验的。而工具本身,又是测试和验证库的有理凭据。我很仔细看了gengetopt的chm文档。
我在反复看的《程序设计实践》,Kernighan老家伙和Pike经典的阐述了”记法“这么一章,而这一章我反复看了有20遍以上。这个getopt不仅仅用于main函数的那个argv,在设计简单的字符串记法上,同样有效。其实Lua有个工具叫tolua,还有个tolua++,而我沉迷于模板包装导出函数给Lua用,并没有仔细研究这个工具。
而这种,“写个库,然后写个工具”的东西,在很多古老的代码库里都能看到。而且他们到现在都工作的很好。真的对最初那些用C语言的老家伙们膜拜啊。
5、class的封装真的有那么好吗?
Hub Scott曾经介绍如何肢解了最初的那份string代码。他评论了里面很多不应该写到string里面的方法。造成了string类的臃肿。
如果class仅仅是封装,而写一个class,需要那么多方法吗?我写了一个比较简单的gdi图形库,不用class封装,而是写一个struct封装数据,写了一些内容是围绕这个struct处理的函数。函数的第一个参数传递这个struct指针,这样的写法其实与设计一个基本的class封装是等效的。而使用class的时候,那个隐藏的this,无形中会让人不知道什么该放进来,什么该扔出去。Python做的真的很好,self必须写,起初感觉很麻烦,多写个self干吗,逐渐我改变了这个看法,就应该写上,写上了才知道是不是属于这个类应该有的。而使用C++主动加this->的方式,已经被很多人提及是个好习惯了。
我回顾了以前的一些代码,发现很多类内容没多大关系的,也被我扔进去了。真的很不利于维护,而且有些地方明显是多余的。我要又一次提到随便了,为了随便去随便真的不是个好习惯。
Hub Scott介绍过另一个事情,是写一个栈的方式。他提到最好不要用继承,用内含。而最近我才看到,最初给Stroustrup提出加protected的那个人,其实他以后后悔了。
我自从我不用那些,什么多态啊,什么继承啊,什么封装啊之后,发现干活也没什么问题,地球也在转,我的程序也在转。而以前我为什么迷信这些呢,不是用OOP写的东西,我就持怀疑甚至抨击的态度?真的是对OOP狂热痴迷到了病态。我反复看《Unix编程艺术》,Eric Raymond对C++的评价还是相对客观的,我最近才知道Alex Stepanov竟然一直都持质疑态度。
6、干好一件事。
Doug McIlroy说:让每个程序都干好一件事。如果有新任务,就重新开始,不要往原程序中加入新功能而搞的复杂。
简单性,是作程序起始,过来人都告诫,简单性的问题。可是一直对简单性有个真正的标准。而Doug McIlroy给了个标准,干好一件事。而坚持用C写代码,才重新审视这个干好一件事的问题。因为被OO狂热的洗脑后干什么都写个class让我习惯什么都得扔到一起,其实怪不得C++,是我的问题。
FIXprotocol设计的是证券交易使用的传输协议。因为工作的缘故,接触了这个公司设计的FAST协议,现在上海的证券交易也是在使用这个。fixprotocol提供的fastapi的C代码库,写的真的干净优雅,认真的干好一件事而没做多余的事情,这里可以下载看看。我看了这个给我的感觉是,我这些年到底做了些什么,怎么写的代码就没长进?
那什么才是“干好一件事”,还是Hub Scott写那个Stack例子,看完之后曾经和别人争论过Pop要不要返回值的事情。而STL也是这么做的,pop是pop,而top是top,传统介绍栈的描述,遵循了“弹出”这个概念,pop是有返回值。而现在用STL的栈,逐渐都接受了top结合pop的方式。
我继续重新审视以前写的代码。那个所谓封装的D3D的类,其结构严重违反干好一件事的原则,唉,越看越觉得,觉得……真的很难堪。
而干好一件事,和简单性。真的没个真正的标准,我还只是凭感觉判断。
----------------------
说到这里,没多少可说的了。C++的危险就是太多概念,太多“方便”的东西提供。优点和缺点并存。
Brain Kernighan和Rob Pike的《程序设计实践》真的是一本太好的书了,被我看了不知道多少遍了。在书里,一章提供CSV文件读写的代码里,他们用C++写了一个读写类。而且书里面介绍了C++比C语言优势的地方。《Hackers Delight》这本书开始就说,用C++而像用C一样。
坚持让自己用纯粹C语言的时候,我不断审视我以前用C++的问题所在。所谓OOP能一统天下的理论,还有被吹捧上了天的设计模式。这些年在中国被宣传的天花乱坠。虽然说OOP(OOD)还有设计模式我用的很熟,但该是被浇冷水的时候了。
写到这里,我的脸皮到早就没了,呵呵,欢迎拍砖。
新到一个公司,碰到一堆烂代码。要么继续烂下去,要么重构。
不过可惜的是重构在时间面前总是过于渺小,所以只好继续更加烂下去了,直到忍受不了了辞职。接下来接手的人也只好继续烂下去了。
同样的代码向好的地方维护很难,但想烂的地方维护很容易。再加上C++新手不友好的特性,再好的代码也能烂下去。
所以说嘛,最好的解决方案就是用C,或者严格限定只能使用哪用特性。同时做好培训,让团队中人员水平相当。
事实上,有人说,只要存在代码评审,代码的质量就会上一个台阶。毕竟,人都需要肯定,不希望给别人看问题多多的代码。
重构里有一条,可以把长的函数变成一个类,把函数里面的本地变量变成类成员。我试过一次,效果出乎意料的好。不仅代码的可读性得到了提高(没人会让类的成员叫a、b、m、n吧),测下来居然性能也提高了。后者尤其让我惊讶。
手段是有目的的。简单看来,把函数拆短可能可以等价为一样糟糕的代码。但从人性的角度来看,在函数里传大量的参数、或者使用糟糕的类成员名字,都是稍微聪明一些的程序员就不会做的。如果有谁看着这样的编码规范,硬要写出带20个参数的函数来,那还是请他回家的好。
2011/10/24 Royee Liu <roye...@gmail.com>:
> 不同意第一点,评审是简单易行却又非常有效的办法,用会议的形式大家一起评,有讨论和互动会更有效果,对新手的成长帮助非常大,每周搞一两次两三周就可以见效,如果有人两三个月还不长进把他开掉好了,没潜力。
> 同意第二点,强制要求函数长短没任何效果,把一个长函数拆成N个一次性使用的短函数只把逻辑打的更散更乱看着费解改着麻烦。
> 用C不是解决办法,菜鸟程序员用C写的代码更难看。
>
> 在 2011年10月24日 下午1:58,akirya(坏[其实我不是什么所谓的坏人]) <aki...@gmail.com>写道:
>>
>> 评审只是没办法的办法,总有人不遵守规则。
>> 就算能执行下去一个函数不超过50行,那么也很有可能看到支离破碎的N个50行的函数,理解起来还得合并起来理解。
>> 归根结底就是没好的习惯,想到哪里写到哪里,出了问题头痛医头,脚痛医脚。反正最后能用了就行。
>>
>> 新到一个公司,碰到一堆烂代码。要么继续烂下去,要么重构。
>> 不过可惜的是重构在时间面前总是过于渺小,所以只好继续更加烂下去了,直到忍受不了了辞职。接下来接手的人也只好继续烂下去了。
>> 同样的代码向好的地方维护很难,但想烂的地方维护很容易。再加上C++新手不友好的特性,再好的代码也能烂下去。
>>
>> 所以说嘛,最好的解决方案就是用C,或者严格限定只能使用哪用特性。同时做好培训,让团队中人员水平相当。
代码美感
a) 不能有嵌套的if-for-switch-while出现
b) 不能有非常复杂的条件判断表达式(用于if-while之类)
c) 足够的注释,对于复杂操作,对于条件判断,可以注释。尽量让代码自己说明自己。
d) 如果代码不能在短时间内理解,或者稍作解释就可以理解,应该看看能否有更简洁的方式
e) 函数不要过长,不能超过一屏显示,最多不应该超过2-3屏。
f)经常问自己是否有更好的办法,更简洁明了的代码形势
g) 一个函数只做一件事,如果需要多个功能,再写一个
h) 少用boolean 作为参数切换功能,用withXXXcase, usingXXXcondition函数名字来自说明。道理同g)
i) 少用重载功能,没必要类似函数用一个名字,既然有不同函数实现,那么应该有不同条件描述,可参考h)的命名
j) 抽象层次不要过多,不要过早和过多考虑设计模式/抽象/抽取通用功能这些事情,这些在代码重构阶段可以修改调整
所以我是赞成楼主说尽量多用Python这样的高级语言的,但不敢苟同回到C。用C写出高效且容易维护的代码,事实上对功力的要求极高。虽然不像C++一样需要语言层面的多年学习,但需要很强的设计能力。如果团队里没有很强的架构师能够在函数接口层面给出指导,还是免了吧。
2011/10/24 Zhangming Niu <niuzha...@gmail.com>:
C 的问题在于语言功能实在是弱得捶地, 说白了就是一无所有. 没办法, 复杂只能靠简单堆起来, 看看标准库里面 qsort 这货, 一个排序算
法的接口可以搞成这个鬼样子, 这让开发者怎么下手呢? 尤其又不支持嵌套函数, 所以凡是这种要用到 functor 的地方, 无论多么简单一次性
的 functor, 都得先另求一块风水宝地去定义一个 (有名字, 搞不好会污染全局空间的) 函数, 然后再来用着. 这只是一个小例子, 其它
需要一些现代流行的特性, 亦是悲剧得让人恨不得喊爹, 再比如多态, Python 解释器里面有个 PyEval_EvalFrameEx, 这东
西如果能有个多态 (就算是 C++ 虚表这么虚的东西) 支持一下, 这一个函数里的代码也不至于多得变态吧.
C 的优点在于它真的够简单, 瞧 C Programming Language 薄称那样, 还没有一本 Linux API 厚, 都不好意思拿
出去卖钱了. 基本上有脑程序员学会指针就可以写得风生水起了, 至于漏内存漏文件句柄啥的, 耗点体力总是能查出来的, 一个人查不出来还有同僚审议
呢.
C++ 除了出笔试题之外, 还可以作一般开发之用, 这确实是当代编程语言中为数不多的好东西. 有心看一下 C++ 标准一路的发展就知道, 标委
会那帮宅男根本不介意 C++ 程序员 (或者 C 程序员++) 怎么去骂它们, C++ 这东西其实整个就是一语言特性瞎掰实验室, 像
RAII 这种高级货, 用 C 还没玩过吧; 还有最新进来的 rvalue reference, 不用 C++ 的怎么可能体会到被复制构造虐了
十几年然后像从性奴地牢重获新生的这种感觉呢; 等等. 反正特性在那里, 至于你们用不用, 反正最后投票通过被加入标准就行了.
确实, C++ 特性太多, 屠龙之技已有不少, 不过多也不能算问题吧, 况且标准也说了, 眼不见, 心不烦, 运行效率也不受拖累. 只不过
呢, 有些程序员是见不得其它程序员这样那样, 这应该是团队合作的部分, 算是 leader 的职责吧.
话说, 现代编程语言要是没有垃圾回收, 封装, 多态这三件神器, 还真的不好意思拿出来显摆. 对于 C 而言, 这三个特性的解决方案分别是人
肉, 人肉, 人肉. 对于 C++ 呢, 分别是 RAII, OOP, OOP. RAII 也算是独树一帜的好方法吧 (当然 C++ 甚至连
RAII 都不是强求的, 比如 Qt 就是用的树形关系模型来管理对象的), 而且还能隐藏对象状态临界点, 写一些文件之类的资源操作代码要简洁许
多.
至于 OOP, 真算是槽点爆表的设计方式, 尤其对于 C++ 这货来说. 本来 C 系列语言分离头文件和 c(pp) 文件目的之一是为了解耦
ABI, C++ 用上 OOP 结果又给耦回去了, 这一来让搞动态库的厂商纷纷不高兴了, 以前 C 里面函数都只有声明, struct 给个前
置声明也中, 成员访问都做成 setter getter 就行了; 可 C++ 不行啊, 这 class 前置一声明, 虚表不就玩完了么, 可
是整个的把 class 丢在头文件里面, 成员顺序也不能改了, 虚函数也不能随便加了, 这还好意思谈扩展性? 于是一些奇怪的方法陆续登场, 比
如 Qt 就用了 private implement 来搞, 看起来还有模有样的, 幸好如此, 否则靠 LGPL 养着的企业还不都得回家卖烧饼
去了.
说到 ABI 那毫无疑问是 C++ 的一道坎 (这当然也是标委会不负责任的表现之一, 连 STL 算法的时间复杂度都要规定, 却把这么重要的实
践需求忽略了, 学院派嘴脸一览无余), 这一扯就得扯到 C++ 两道靓丽的风景线: STL 和 boost. 这俩家伙且不说类成员什么的, 连
函数实现都不得不给丢进头文件了. 这下就不得了了, 敢在动态库接口上锚一个泛型容器? 哼哼, 只要其它机器上的库实现有一丁点不一样, 立马崩给
你看.
所以 C++ 在这种三不管的地方还是不要贸然使用的好. 学习一门语言呢, 能用上当然好, 能不上呢也不能强求, 最重要的是体会一下其中的思
想, 然后仰角 45 度看看天空, 挺好的.