??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲午夜精品久久久久久app,www久久久天天com,亚洲中文字幕无码久久精品1 http://www.shnenglu.com/converse/archive/2010/08/08/122713.html那谁那谁Sun, 08 Aug 2010 15:44:00 GMThttp://www.shnenglu.com/converse/archive/2010/08/08/122713.htmlhttp://www.shnenglu.com/converse/comments/122713.htmlhttp://www.shnenglu.com/converse/archive/2010/08/08/122713.html#Feedback1http://www.shnenglu.com/converse/comments/commentRss/122713.htmlhttp://www.shnenglu.com/converse/services/trackbacks/122713.html
在这里已l写了快五年的博? 感谢cppblog q些q来一直提供的优质服务, 以至于我都忘了他们的存在--因ؓ实在没有什么不痛快的事情要投诉反馈?不过,g目前对chrome的支持ƈ不太? 我每ơ写博客都需要切换到Firefox上面,希望能有改善.




那谁 2010-08-08 23:44 发表评论
]]>
谈目前项目组的代码提交制?/title><link>http://www.shnenglu.com/converse/archive/2010/07/08/119660.html</link><dc:creator>那谁</dc:creator><author>那谁</author><pubDate>Wed, 07 Jul 2010 17:53:00 GMT</pubDate><guid>http://www.shnenglu.com/converse/archive/2010/07/08/119660.html</guid><wfw:comment>http://www.shnenglu.com/converse/comments/119660.html</wfw:comment><comments>http://www.shnenglu.com/converse/archive/2010/07/08/119660.html#Feedback</comments><slash:comments>20</slash:comments><wfw:commentRss>http://www.shnenglu.com/converse/comments/commentRss/119660.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/converse/services/trackbacks/119660.html</trackback:ping><description><![CDATA[(转蝲h明出?http://www.shnenglu.com/converse 那谁)<br><br>一直以来想找机会谈谈目前这个项目组内采用的代码提交制度,今天整理一?<br><br>分如下几个流E?<br>1) 在tracpȝ上徏立ticket,写好q个d的目?q且acceptq个ticket.<br>2) 修改代码,把相关的修改q的代码(一般还应包括相关的试用例的代?后面会加以说?提交到review board?<br>3) 在review board上填写如下几个必要的信息:<br>a)W?)步徏立的ticket的号?可以有好几个,也就是一ơ修改可以针对好几个d),以明这ơ提交针对的是哪个Q?<br>b)写下试了哪几个试用例,对这ơ的提交写一D|q?<br>c)写下l哪些h做review.reviewer的角色分ZU?一U是负责?另一U就是普通的l员.每一ơ提?必须保证reviewer中有臛_一个负责h,q且需要所有的reviewer都通过了这ơ修?才能向代码库提交代码.reviewer会针Ҏ交的代码q行Ҏ回复.<br>4)一般情况下,代码不会在第一ơ提交就能通过review,大多数情况会被打回修?于是2)-4)三个步骤@环进行下ȝC码通过review为止.<br>5) 提交了代码之?1)中徏立的ticket会被自动关闭,q且在ticket的回复自动写上本ơ提交修改的文g以及svn revision?q样以后再看hq道是哪次提交q且修改了哪些文仉对的又是哪个功能?<br>6) 有一台服务器专门作ؓbuildbot机器, q台机器在每ơ提交了代码之后, 自动清I原来的代码目录,更新最新的代码,重新~译,然后把里面的试用例全部跑一?我们的项目用的tcmalloc,会检查内存泄?所以在试用例试p|,以及有内存泄漏的时?buildbot都会p|.需要补充一点的?除了每次提交代码会导致buildbot重新~译新的代码,在每晚的一个固定时?即没有更新代码,也会做相同的动作.buildbot的存?是Z不断的清I编译文仉新编译再跑测试用?以大量的试消除随机性保证正?<br><br>以上是整个代码提交机制的大体程说明,下面谈里面的l节.<br><br>1)上面的第1)步中,建立trac的ticket?需要指定一个milestone,一般我们对必须做的事情是每周以日期命名建立一个milestone,q样,你做的Q务就会自然的变成每周可以去跟q的d.<br>2)W?)步中,写测试用例针对的是每个类或者每个头文g对外暴露的API接口,比如对外的API c使用内部的函数B,那么是没有办法对函数B~写试用例?我们的要求是, M的一个新增的API都需要写针对它进行测试的试用例,不一定只有一?因ؓ需要考虑的情况可能很?总而言?可能的考虑齐全.假如本次修改修改了内部函数B,那么依赖于函数B的API c它的试用例也就需要再试?q些试用的代码也会一q提交到代码库中,因ؓq样才能保证buildbot更新之后也按照最新的试用例q行试.<br>3) 代码提交到reviewboard之前,q需要过lintq一?对基本的代码风格q行?我们使用的是google c++ code style.<br>4) reviewer中的负责色很重要, L看门人的作用,M的一ơ修Ҏ?都必至经q一个负责h的review, 所以对他的要求q寚w些了,除了要完成自q工作?q需要认真review他h的代?而要review他h的代码ƈ且给出好的意见来,又要求他本h除了~码能力?q要在业务层面对别h的工作有大体的了?不然没法review?<br>5) 从前文可以看?review实在是一个繁杂的工作,很有可能在review阶段被打回修改代?我的经验而言,提交review的h要将提交的Q务尽量的划分的细一些就来的很重要了.在提交review的时?我一直坚持DOTDIW原则(Do One Thing,Do It Well).相反的例?我们l有个同?做了一个很大的功能,光是完成q个大的功能,p费好几周的时?提交review的时候代码量?有个几千行的,q样别hreviewh也慢,而且一旦不通过需要修?又是一个苦力活?q样一折腾,一个月旉q去?如果当时能对整体的功能有个把?懂得划分模块层次,逐个提交,也许会好?当然,大规模的代码提交有时q不能完全的避免,比如一个比较大的重?牵一发而动全n?我只是说如果可能,应尽量避免大规模代码的提?q且最重要的是:每次提交最好仅针对一个功能点.<br><br>以上是对程从整体到l节的描q?现在谈谈我的看法.<br>先来谈优?<br>1) 通过codereview制度,保证了项目组成员之间能够在代码层面上直接的进行交?我想q一Ҏ最重要?没有之一.<br>如果你是一个水q_一些的E序?那么有比你牛叉的人帮你review,相当于是M的时候有老师帮你阅卷修改作业,可以指正你的问题所?我在被hreview的过E中听C别hҎ很多的意?而如果是一个水q高的?是不是对水^差的行codereview是费他的旉了呢?我个?q个事情分怎么?从团队的角度?按照木桶理论,最短的短板往往军_了能辑ֈ的水q?M能指望所有的事情都由老鸟完成,所以老h在帮Chreview代码的时候间接的帮助了新人的成长,同时作ؓ目l中资历比较q?也应该对目多费一些时间进行把?我觉得这一Ҏ可厚?同时,即是新?通过阅读他h的代码ƈ且交?也可以学习到别h的思想.<br>codereview制度从上面的角度上保证了目成员可以直接通过代码q行交流,单的?谁写的代码质量如?一Creview,一目了?写的好的通过的快,写的不好被打回修改多了自׃会长记?q可以多看别人的代码q行学习.q样,在一定层面上可以佉K目组成员的能力尽可能的接q?我能力长了一U?相应的也会拉动项目组中的人升U?<br><br>2) 试用例.我之前提到的试驱动开?x来自于目l中~写试用例+buildbot执行试用例的做?如何证明一个API是确定无误的?我觉得这个问题似乎非帔R.除了一些可以通过数学上逻辑上证明的情况?q需要考虑很多其他的随机情?比如U程的切换是随机?某个文gҎ好存在是随机?{等.q些随机出现的问?很多时候不能在某一ơ测试中昄出来.但是如果有了buildbot,不停的更?~译,执行,M有暴露问题的一?另外,之前我也提到q?脑中如果有了试用例的概念存?每写一个API旉会考虑到针对它的用例应该是怎样?从另一个角?也帮助你的设?-你需要考虑q个API的输?输出,异常情况都有哪些,如何试?试用例的存?保证目量的做C"可控?.<br><br>~点:<br>1) 从上面的程可以看出,走完一个代码提交的程需要花费大量的_֊/旉(有一些还是他人的_֊/旉),所?也许q个制度q不适合于那U时间压力比较大的项?<br><br>2) 有几个地方很隑֝?比如codereview?有些reviewer会走q场,也没怎么看代码就直接通过?q样׃于形式?q有~写试用例,也是一件很耗时间的事情.<br><br>3) ׃codereview制度的存?lreview中的负责人带ȝ压力很大,因ؓ本n他有自己的工?又要量对他人的业务/代码q行了解,像那种负蝲很大的服务器一?有时候会不堪重负.q一点上,我的x?目l内的其他成?如果能积极主动一?多花旉了解别h的代?量分担review的Q?或者试着成长责hU别(降低单点故障?),也许是一个好办法.不过,q还得看Z.<br><br>整个代码提交程上的软g,目前我所知的都是使用的开源Y?SVN, google c++ code style lint,review board,buildbot,trac,试用例的编写上使用的是google的测试用例框架gtest.不过,整合赯些Y件搭建好q个程׃是那么容易了,用了一?半年左右的时?才让q个程基本E_下来.<br><br>M,q套机制?既有Zؓ的干?也有机器层面上的q涉,也许q不是最完美?但是了最大的力量M证项目的正确性和可控?<br><br>以正的方式正确的制度做?是将事情做好的一个关?<br><br> <img src ="http://www.shnenglu.com/converse/aggbug/119660.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/converse/" target="_blank">那谁</a> 2010-07-08 01:53 <a href="http://www.shnenglu.com/converse/archive/2010/07/08/119660.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++的流设计很糟p?/title><link>http://www.shnenglu.com/converse/archive/2010/07/06/119427.html</link><dc:creator>那谁</dc:creator><author>那谁</author><pubDate>Tue, 06 Jul 2010 05:04:00 GMT</pubDate><guid>http://www.shnenglu.com/converse/archive/2010/07/06/119427.html</guid><wfw:comment>http://www.shnenglu.com/converse/comments/119427.html</wfw:comment><comments>http://www.shnenglu.com/converse/archive/2010/07/06/119427.html#Feedback</comments><slash:comments>79</slash:comments><wfw:commentRss>http://www.shnenglu.com/converse/comments/commentRss/119427.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/converse/services/trackbacks/119427.html</trackback:ping><description><![CDATA[最q需要提供一个功?采用cMC++输出的格式输出一些日志信? 例如Log(FATAL) << "log to" .<br><br>我找了两个类似项目来研究,google?a >glog</a> ?<a >log4cpp</a>, 它们都支持以C++输出格式进行输?<br><br>但是研究到最?我发现最大的问题? 如果按照C++的流输出格式q行输出, 无法判定需要输出的信息到哪里是l束.比如log << "hello " << "world",是无法判断到底在输出"hello"q是"world"的时候上面的参数输入已经l束?上面两个目? 解决q个问题的办法大致是相同?以下面可~译q行代码Z说明它们的做?在linux g++下面~译通过):<br> <div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">#include </span><span style="color: #000000;"><</span><span style="color: #000000;">iostream</span><span style="color: #000000;">></span><span style="color: #000000;"><br>#include </span><span style="color: #000000;"><</span><span style="color: #000000;">sstream</span><span style="color: #000000;">></span><span style="color: #000000;"><br><br>#ifdef __DEPRECATED<br></span><span style="color: #008000;">//</span><span style="color: #008000;"> Make GCC quiet.</span><span style="color: #008000;"><br></span><span style="color: #000000;"> # undef __DEPRECATED<br> # include </span><span style="color: #000000;"><</span><span style="color: #000000;">strstream</span><span style="color: #000000;">></span><span style="color: #000000;"><br> # define __DEPRECATED<br></span><span style="color: #0000ff;">#else</span><span style="color: #000000;"><br> # include </span><span style="color: #000000;"><</span><span style="color: #000000;">strstream</span><span style="color: #000000;">></span><span style="color: #000000;"><br></span><span style="color: #0000ff;">#endif</span><span style="color: #000000;"><br><br></span><span style="color: #0000ff;">using</span><span style="color: #000000;"> </span><span style="color: #0000ff;">namespace</span><span style="color: #000000;"> std;<br><br></span><span style="color: #0000ff;">class</span><span style="color: #000000;"> LoggerStream : </span><span style="color: #0000ff;">public</span><span style="color: #000000;"> std::ostrstream {<br> </span><span style="color: #0000ff;">public</span><span style="color: #000000;">:<br>  LoggerStream(</span><span style="color: #0000ff;">char</span><span style="color: #000000;"> </span><span style="color: #000000;">*</span><span style="color: #000000;"> buf, </span><span style="color: #0000ff;">int</span><span style="color: #000000;"> len)<br>   : ostrstream(buf, len),<br>    buf_(buf),<br>    len_(len) {<br>  }<br><br>  </span><span style="color: #000000;">~</span><span style="color: #000000;">LoggerStream() {<br>    </span><span style="color: #008000;">//</span><span style="color: #008000;"> do the real fucking output</span><span style="color: #008000;"><br></span><span style="color: #000000;">    cout </span><span style="color: #000000;"><<</span><span style="color: #000000;"> buf_;<br>  }<br><br> </span><span style="color: #0000ff;">private</span><span style="color: #000000;">:<br>  </span><span style="color: #0000ff;">char</span><span style="color: #000000;"> </span><span style="color: #000000;">*</span><span style="color: #000000;">buf_;<br>  </span><span style="color: #0000ff;">int</span><span style="color: #000000;"> len_;<br>};<br><br></span><span style="color: #0000ff;">int</span><span style="color: #000000;"> main() {<br>  </span><span style="color: #0000ff;">char</span><span style="color: #000000;"> buf[</span><span style="color: #000000;">100</span><span style="color: #000000;">] </span><span style="color: #000000;">=</span><span style="color: #000000;"> {</span><span style="color: #000000;">'</span><span style="color: #000000;">\0</span><span style="color: #000000;">'</span><span style="color: #000000;">};<br><br>  LoggerStream(buf, </span><span style="color: #0000ff;">sizeof</span><span style="color: #000000;">(buf)) </span><span style="color: #000000;"><<</span><span style="color: #000000;"> </span><span style="color: #000000;">1</span><span style="color: #000000;"> </span><span style="color: #000000;"><<</span><span style="color: #000000;"> </span><span style="color: #000000;">"</span><span style="color: #000000;"> hello world\n</span><span style="color: #000000;">"</span><span style="color: #000000;">;<br><br>  cout </span><span style="color: #000000;"><<</span><span style="color: #000000;"> </span><span style="color: #000000;">"</span><span style="color: #000000;">buf = </span><span style="color: #000000;">"</span><span style="color: #000000;"> </span><span style="color: #000000;"><<</span><span style="color: #000000;"> buf </span><span style="color: #000000;"><<</span><span style="color: #000000;"> endl;<br><br>  </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> </span><span style="color: #000000;">0</span><span style="color: #000000;">;<br>}<br></span></div> <br>在上面的代码? 开始进行输出的时候首先初始化一个LoggerStream对象, 而在输出参数输入完毕的时候将调用它的析构函数,在这个析构函C才完成真正的输出动作.也就是说,׃对输入参数结束位|判断手D늚~失,C++中不得不采用q个手段在析构函C完成最l的输出工作.<br>q样的做?最大的问题?频繁的构?析构开销?而且每个"<<"操作W背后又需要调用ostream的operator<<,也就是假如你的输入参数有三个调用operator <<三次(当然是经q重载的,不一定都是同一个operator<<),因此,假如需要考虑多线E的?那么一ơ输入有多个函数函数中被调用,仍然是问??要用这门语a写出正确的程序来,需要了解底下多的l节?!<br><br>最?我向目l反映这个问?一致同意以C中类似sprintf可变参数的Ş式实现这个功?可变参数解决q个问题,我的感觉而言,是输入参数的时?E显复杂,需要用h定输入的格式.然?其实q个做法也有好处:作ؓ函数的用?你必L的知道你在做什么ƈ且反馈给你所使用的函?明确?无歧义的使用函数,而不是依靠所谓函数重载猜你的用意,我想也是避免问题的一个手D?gcc? 提供了对可变参数查的机制,?a >q里</a>.<br><br> <img src ="http://www.shnenglu.com/converse/aggbug/119427.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/converse/" target="_blank">那谁</a> 2010-07-06 13:04 <a href="http://www.shnenglu.com/converse/archive/2010/07/06/119427.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>向d国h低头http://www.shnenglu.com/converse/archive/2010/07/04/119287.html那谁那谁Sun, 04 Jul 2010 02:55:00 GMThttp://www.shnenglu.com/converse/archive/2010/07/04/119287.htmlhttp://www.shnenglu.com/converse/comments/119287.htmlhttp://www.shnenglu.com/converse/archive/2010/07/04/119287.html#Feedback4http://www.shnenglu.com/converse/comments/commentRss/119287.htmlhttp://www.shnenglu.com/converse/services/trackbacks/119287.html
作ؓ资深的已l喜Ƣ阿根h人十多年的h,昨晚看到0:2落后的时?我迅速走回自q戉K.我知道已l崩?然而比赛还有几十分钟的旉,以这个态势发展下去,l果q会更差.

但是,q了几分?我又走出来l看完剩下的比赛,0:3,0:4,阿根廷hg的无?映衬着德国人的L.德国Z及其L?或者说是对手阿根h最擅长的方?微笑着一刀一刀对手切?

德国人是世界杯历史上发挥最为稳定的一支球?没有之一),q个数据的得来根据是他们是迄今ؓ止进入世界杯八强最多的球队.

"E_"是什么意?E_是自己不犯?正常发挥自己的水q??0分打?0分的水^,?00分打?00分的水^.保证了自׃犯错,才能{待Ҏ的犯?

即?4,98两年世界?德国人由于整体h员的老化,没能取得好成l?他们也依然很"E_",因ؓ当时的h员能力也实只有那个水^?他们没有自我犯错,依然把自己最好的水^发挥出来.

看看其他的队伍吧,法国内讧,意大利固?巴西保守,阿根?我就不评价了).几乎都有各自的问?最l都倒在自己的脚?

球是一个充满偶然性的q动,一个擦w?探头,伸脚都可能造成q球.遇到一个几十年一见的天才,可以让球队呼风唤雨好多q?

但是,你不能L凭借着偶然?q气走的更远.好比?你不能L指望着出现贝利,马拉多纳,齐祖q样的天才能站出来一夫当x救球?我们提倡英?崇拜英雄,但是,英雄q不L存在?出现英雄q本w就是gq气十的事?

更多?应该是按照规律办?一丝不?严}求实.写下上面那句话时,我想C德国人在06q世界杯的对阿根廷互|点球时的小U条.德国除了贝肯鲍尔之外g没有出现公认的超U巨?然而就是能取得如此E_的成l?q本w已l是很好的解?

曄我迷恋巴?巴蒂那样的悲剧哥,上天l予他们天赋,却没有给他们好的l果.曄我在他们w上,怿有所谓的"命运".

我这么说,q不是说他们的结果完全的无外因所作用.只是我觉?当你把事情的l果q度的归咎于那些玄之又玄的东西时,人就会变得矫?文艺,不去反思自?

佛说,世间一切事,皆是因果报应.说的通俗?可怜之人必有其可恨之处.

所?M妈的<<阿根廷别为我哭泣>>?矫情和文艺ƈ不能让你的生zd此改?抬v头来面对现实反思自己吧.

向d国h低头,q个民族的字兔R没有"命运"一?



那谁 2010-07-04 10:55 发表评论
]]>
集成libevent,google protobuf的RPC框架http://www.shnenglu.com/converse/archive/2010/06/20/118310.html那谁那谁Sun, 20 Jun 2010 08:30:00 GMThttp://www.shnenglu.com/converse/archive/2010/06/20/118310.htmlhttp://www.shnenglu.com/converse/comments/118310.htmlhttp://www.shnenglu.com/converse/archive/2010/06/20/118310.html#Feedback4http://www.shnenglu.com/converse/comments/commentRss/118310.htmlhttp://www.shnenglu.com/converse/services/trackbacks/118310.htmlRemote Procedure Call),中文译是远E过E调?其实从原理来说这q不是一个新的概?我的理解? 不同的机器之间定义了一些接? 也有客户端和服务器端,客户端可以通过协商好的接口调用服务器端已经注册好的服务.说白?q是|络通信的那一套机?既然q是|络通信,那么Z么需要用RPC而不是自己去完成q样的一套工作呢?假如是自己做q样的事?需要考虑~解?|络?其很多l节需要去x:协议有哪?如何定义格式?涉及到整数的q要考虑|络和主机字节序{?如果逻辑E序员还需要关注这些细?昄太繁琐了.q有是,国内的公司开发很有文,假如查找问题时还需要通过M码才能知道协议中各个字段的含?q样寚w目的可维护性会有很大的影响.假如使用了RPC,通过RPC工具定义的格式来定义协议,可以一目了?而且,|络层就应该只关注网l层的工?逻辑层架构在|络层之上再完成逻辑的操?把网l和逻辑分开,也是清晰的架构设?

google protobuf 是google公开的一套用于网l通信时用于协议编解码的工具库,使用它定义的格式,你可以定义协议的字段,由它自带的编译器生成责编解码的代码文?可生成许多不同的语言文g).同时,它还包括了基本的RPC接口定义.但是,q个工具用在RPC上比较大的问题是它只负责生成代码文g,而如果要真正使用h做ؓ一个RPC框架,q需要对它进行网l层上的装,但是在它自己的官Ҏ上q没有给Z个demo告诉读者如何一步一步的来完成这样一个工?thrift是与google protobuf同样定位的一个工具库,除了具备google protobuf相同的功能外,如支持多语言,跨^?高效的编解码,q集成了|络通信?可以使用它完成所有RPC所需要完成的工作.?a >q个面?google protobufl出了一些已知的使用不同语言对它q行装的项?

chenshuo?a >evproto同样也是集成libevent与google protobuf的RPC框架,不过在对libevent的用上,q里的做法与他不相?
1) 他用了libevent自带的RPC功能, 而这里只使用到libevent对网lI/Oq行的封装的最基本的功?
2) 之所以有1)的考虑,是因为我认ؓ一个工h好应该是"do one thing, do it better"?也许从这点可以解释ؓ什么google protobuf没有像thrift那样自带|络?而是把这个工作留l了用户),libevent已经来大,除了对I/O,信号,定时器等的封装之?现在q有RPC,异步DNS,http协议的支持等{?说真?如果只是x到网lI/O的多路复用机?那么几乎M一个熟l的E序员都可以很快的自己做L一套东西来,使用libevent无非是Z后可能的跨^台做准备|了.随着我对libevent发展方向的不认同,q曾l想q用libev替代libevent,不过现在暂时不想折腾q个事情?

eventrpc目目前?a >avidya下的一个子目,avidya目的定位是实现一些分布式的玩Ll?比如google已经公开论文的chubby,mapreduce,GFS{?,也许以后不一定能被用?但是也要实践做一?׃有一个好用的RPC框架是做分布式的必需?所有首先实现eventrpcq个子项目了,以后也许q会实现其他语言的版?如python,java.

eventrpc的网l模型上,使用以前提到?a href="http://www.shnenglu.com/converse/archive/2010/03/11/109449.html">memcached的网l模?/a>, ȝE负责接收新的连? 再将q些新的q接交由副线E处?每个副线E自带I/O dispatcher.在samples目录?有一个实Cecho服务的客L和服务器端示?

在用之?L保libevent和google protobuf已经安装成功,当前只在linux下可?



那谁 2010-06-20 16:30 发表评论
]]>
试驱动开?/title><link>http://www.shnenglu.com/converse/archive/2010/06/10/117596.html</link><dc:creator>那谁</dc:creator><author>那谁</author><pubDate>Thu, 10 Jun 2010 15:19:00 GMT</pubDate><guid>http://www.shnenglu.com/converse/archive/2010/06/10/117596.html</guid><wfw:comment>http://www.shnenglu.com/converse/comments/117596.html</wfw:comment><comments>http://www.shnenglu.com/converse/archive/2010/06/10/117596.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/converse/comments/commentRss/117596.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/converse/services/trackbacks/117596.html</trackback:ping><description><![CDATA[<span style="font-size: 12pt;">有一本书叫<a ><<试驱动开?gt;></a> , 我没有看q?q里仅谈论我所理解?试驱动开?.<br><br>我对q句话的理解? <br>1) M一ơ提交新的代码都需要添加针对这些新功能的测试用?<br>2) 无论设计函数q是c? 对外暴露的接口都应该做到明确, 清晰, 不会lh模棱两可的感?提供的功能点可能的单一, do one thing, do it well.<br><br>而言? 我所理解?试驱动开?, 十分Ҏ口的设计, 以及针对q个接口所需要考虑的异常和试用例.接口是对外的保证, 而测试用例是验收? 每次的修? 都需要保证之前和现在的用例能利通过.<br><br>所? 对开发h员来? 如果有这?试驱动开?的观? 那么在设计编写代码的时候会很容易的形成几个好习? 比如他会反问自己以下几个问题:<br>1) 新增的代码提供的是什么功? 功能Ҏ否够的单一, 明确, 比如本次试的代码仅针对功能A, 下一ơ的仅针对功能B, 假如B功能q依赖于A功能, 那么首先要保证A功能Ҏ提?切忌万不得已的情况下不可以将多个功能Ҏ在一ơ提交中, q样, 以后回溯问题时会加大隑ֺ, 也会lcodereview{带来困?<br>2) 新增的功? 对外暴露的接口是哪些?有没有冗? 不明的接口设计?q些接口是不是刚刚好不多不少_?<br>3) Ҏ增的功能, 明确了对外应该提供什么接口之? q需要反问自?可能在哪些情况下出错, 每种出错的情况应该如何处? 如何通知调用? 代码的注释是不是对一些情况作了说?<br>4) 最? Ҏ增的功能, 考虑了哪些测试用? 试是否充分, 是否考虑了很多异常的情况?<br><br>所? 每次的代码提交都是一件很严肃的事? q意味着, 你对pȝ现有的代码做Z一些修? 可能是接口的修改, 可能是实现的修改.如何能保证你的修Ҏ有问? codereview是一? 好的codereview是一件很耗时的事? q需要reviewer负责?同时最好还要多对q部分代码有了解.如果reviewer能力较强, 又比较负? 那么一ơreview相当于是一个老师在阅M? 他会l出你一些徏?反之, 如果你作为reviewer去review一个高水^的h的代? 又可以从阅读中学习对方的思\.总而言? 我觉得做好codereview是一件能够迅速提?l验?的捷? 早前我阅读过许多开源项? 学习了很多别人的技巧思\, codereview比之更近了一?-因ؓ我还有机会与作者面寚w的一起交?另外, 除了codereview之外, 每次提交都有试用例, 也是保证代码质量的方式之一, 如果把代码比做一个球? 那么试用例是站在q个球场门口q行安检工作的保? 不论做了什么修? 只要保证试用例写的? 那么基本上都跑不q这个保安的掌心.有了试用例, 目的修Ҏ有了保证, 它所提供的功? 都是可控?有保证的.<br><br>另外, 每次提交的修改功能点量的单一也是很重要的一? 因ؓ假设你想做的事情很多, 比如做了A又想做B,发现做B功能需要实现C功能,实现C功能首先要做D功能....子子孙孙,无穷也.q样会导致你的代码提交codereview时被通过的时间慢(原因有很? 比如你需要提交测试用例多? 比如别h的codereview旉多了).q有一? 假如别h赶在你之前提交了代码, 而你的修攚w要依赖别人的代码, q样D了你需要合q别人的改动, q又是一件很ȝ的事?<br><br>所? 当接手一个Q务时, 如何按照层次序划分d, 每次提交都保证尽可能提交的功能? 而且又能保证每次的提交都有严格的试用例, 也是对开发h员的一个考验.当然,q些也许在动手的时候不能百分百的考虑清楚, 但是如果完全的没有考虑q? 上手做, q早都要q的.<br><br>另外, 有了同新增代码一h交测试用例的要求之后, "看上?每次提交的速度慢了, 因ؓq需要撰写测试用? 所以对d旉点的估计可能也需要改? 我个人的估计是写代码旉 : 试旉(包括写测试用?改bug) : Ҏcodereview修改代码的三者之间比例大概ؓ4:3:3, 所以如果一个Q务给我五个工作日的时间完? 也许以前我到了第四天才编码完? 而现在就要尽量做到第三天之内能完成编码了.不过q个比例q不定, 依个人的素质而定, 有的人写代码质量很高, 自己已经把很多情况在写的时候考虑q去? 所以后期测试和codereview时出现问题的Z? 反之, 有的人的代码质量较差? 可能l常在codereview的时候被打回去重?甚至于重?? 后面的比例就要增加了.以我而言, 如果能在保证代码质量的同? 减少后面两项的时间比? 那应该是说明了我的代码质量有了提高了.<br><br>总而言? 接口的设? d层次序的划? 都是很考验人经验的z? 语言的表达L苍白? 需要实实在在的d践体?<br><br>K.I.S.S<br> </span> <img src ="http://www.shnenglu.com/converse/aggbug/117596.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/converse/" target="_blank">那谁</a> 2010-06-10 23:19 <a href="http://www.shnenglu.com/converse/archive/2010/06/10/117596.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>解读google C++ code style谈对C++的理?/title><link>http://www.shnenglu.com/converse/archive/2010/05/29/116689.html</link><dc:creator>那谁</dc:creator><author>那谁</author><pubDate>Sat, 29 May 2010 12:34:00 GMT</pubDate><guid>http://www.shnenglu.com/converse/archive/2010/05/29/116689.html</guid><wfw:comment>http://www.shnenglu.com/converse/comments/116689.html</wfw:comment><comments>http://www.shnenglu.com/converse/archive/2010/05/29/116689.html#Feedback</comments><slash:comments>43</slash:comments><wfw:commentRss>http://www.shnenglu.com/converse/comments/commentRss/116689.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/converse/services/trackbacks/116689.html</trackback:ping><description><![CDATA[ C++是一门够复杂的语言.说它"_复杂",是因为C++提供了够多~程范式--泛型, 模板, 面向对象, 异常,{等.Z说说,我已l很久没有跟qC++的最新发展了(比如C++0x), 所以前面列丑և来的Ҏ应该只是C++所有特性的一个部分Ş?C++Ҏ过多很N驭好C++的原因之一.另一个原因是C++q于"自作聪明",在很多地Ҏ无声息的做了很多事情, 比如隐式的类型{? 重蝲, 模板推导{等.而很多时?q些动作难以察觉,有时候会在你意想不到的地方发?即是熟l的C++E序员也隑օ被误?(关于了解C++~译器自作聪明做了哪些事? <<深入理解C++物g模型>>是不错的选择).<br><br>世界上有很多问题, Z知道如何去解?但是, gq还不算是最高明?更高明的做法是学会避免问题的发生.而如何避免问题的发生, 需要经验的U篏--曄犯下错误,吃一堑长一?于是知道哪些事情是不该做的或者是不应该这么做?<br><br><a >google C++ code style</a>是google对外公布的一份google内部~写C++的代码规范文?与其他很多我曄看过的编码文一?里面有一些关于代码风格的规定,也就是代码的外观,q一部分不在q里q多讨论,毕竟代码如何才叫"观"是一个见仁见智的话题.在这里专门讨份文档中对一些C++Ҏ该如何使用的讨?最后再做一个ȝ.注意其中的序号ƈ不是文中的序号,如果要详l了?可以自己ȝq䆾文.<br><br><div style="background-color: rgb(238, 238, 238); font-size: 13px; border-left-color: rgb(204, 204, 204); padding-right: 5px; padding-bottom: 4px; padding-left: 4px; padding-top: 4px; width: 98%; word-break: break-all; "><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000; ">1</span><span style="color: #000000; ">) Static and Global Variables<br>   Static or global variables of </span><span style="color: #0000FF; ">class</span><span style="color: #000000; "> type are forbidden: they cause hard</span><span style="color: #000000; ">-</span><span style="color: #000000; ">to</span><span style="color: #000000; ">-</span><span style="color: #000000; ">find bugs due to indeterminate order of construction and destruction.</span></div>google明确止全局对象是类对象, 只能是所谓POD(Plain Old Data,如int char{?数据才行.因ؓC++标准中没有明规定全局对象的初始化序, 假设全局cd象A,B,其中A的初始化依赖于B的? 那么无法保证最后的l果.如果非要使用全局cd? 那么只能使用指针, 在main{函数入口统一q行初始?<br><br><div style="background-color: rgb(238, 238, 238); font-size: 13px; border-left-color: rgb(204, 204, 204); padding-right: 5px; padding-bottom: 4px; padding-left: 4px; padding-top: 4px; width: 98%; word-break: break-all; "><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000; ">2</span><span style="color: #000000; ">) Doing Work </span><span style="color: #0000FF; ">in</span><span style="color: #000000; "> Constructors<br>In general, constructors should merely </span><span style="color: #0000FF; ">set</span><span style="color: #000000; "> member variables to their initial values. Any complex initialization should go </span><span style="color: #0000FF; ">in</span><span style="color: #000000; "> an </span><span style="color: #0000FF; ">explicit</span><span style="color: #000000; "> Init() method. </span></div>文规定, 在类构造函C对类成员对象做基本的初始化操? 所有的复杂初始化操作集中一个比如Init()的函C,理由如下:<br> <ul> <li> There is no easy way for constructors to signal errors, short of using exceptions (which are <a >forbidden</a>). </li> <li> If the work fails, we now have an object whose initialization code failed, so it may be an indeterminate state. </li> <li> If the work calls virtual functions, these calls will not get dispatched to the subclass implementations. Future modification to your class can quietly introduce this problem even if your class is not currently subclassed, causing much confusion. </li> <li> If someone creates a global variable of this type (which is against the rules, but still), the constructor code will be called before <code>main()</code>, possibly breaking some implicit assumptions in the constructor code. For instance, <a >gflags</a> will not yet have been initialized. </li> </ul> 单的概括h也就?构造函数没有返回? 难以让用者感知错?假如在构造函C调用虚拟函数, 则无法按照用者的x调用到对应子cM实现的虚拟函?理由是构造函数还未完成意味着q个对象q没有被成功构造完?.<br><br><div style="background-color: rgb(238, 238, 238); font-size: 13px; border-left-color: rgb(204, 204, 204); padding-right: 5px; padding-bottom: 4px; padding-left: 4px; padding-top: 4px; width: 98%; word-break: break-all; "><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000; ">3</span><span style="color: #000000; ">) Default Constructors<br>You must define a </span><span style="color: #0000FF; ">default</span><span style="color: #000000; "> constructor </span><span style="color: #0000FF; ">if</span><span style="color: #000000; "> your </span><span style="color: #0000FF; ">class</span><span style="color: #000000; "> defines member variables and has no other constructors. Otherwise the compiler will </span><span style="color: #0000FF; ">do</span><span style="color: #000000; "> it </span><span style="color: #0000FF; ">for</span><span style="color: #000000; "> you, badly. </span></div>当程序员没有为类~写一个默认构造函数的时? ~译器会自动生成一个默认构造函?而这个编译器生成的函数如何实?比如如何初始化类成员对象)是不定?q样,假如出现问题时将l调试跟t带来困?所? 规范要求每个c都需要编写一个默认构造函数避免这U情늚出现.<br><br><div style="background-color: rgb(238, 238, 238); font-size: 13px; border-left-color: rgb(204, 204, 204); padding-right: 5px; padding-bottom: 4px; padding-left: 4px; padding-top: 4px; width: 98%; word-break: break-all; "><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000; ">4</span><span style="color: #000000; ">) Explicit Constructors<br>Use the C</span><span style="color: #000000; ">++</span><span style="color: #000000; "> keyword </span><span style="color: #0000FF; ">explicit</span><span style="color: #000000; "> </span><span style="color: #0000FF; ">for</span><span style="color: #000000; "> constructors with one argument.</span></div>假如构造函数只有一个参? 使用explicit避免隐式转换, 因ؓ隐式转换可能在你q不需要的时候出?<br> <br><div style="background-color: rgb(238, 238, 238); font-size: 13px; border-left-color: rgb(204, 204, 204); padding-right: 5px; padding-bottom: 4px; padding-left: 4px; padding-top: 4px; width: 98%; word-break: break-all; "><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000; ">5</span><span style="color: #000000; ">) Copy Constructors<br>Provide a copy constructor and assignment </span><span style="color: #0000FF; ">operator</span><span style="color: #000000; "> only when necessary. Otherwise, disable them with DISALLOW_COPY_AND_ASSIGN.</span></div>只有当必要的时候才需要定义拷贝构造函数和赋值操作符. 同上一条理׃? 避免一些隐式的转换.另一条理由是,"="难以跟踪,如果真的要实现类似的功能,可以提供比如名ؓCopy()的函?q样子一目了?不会像赋值操作符那样可能在每?="出现的地方出?<br><br><div style="background-color: rgb(238, 238, 238); font-size: 13px; border-left-color: rgb(204, 204, 204); padding-right: 5px; padding-bottom: 4px; padding-left: 4px; padding-top: 4px; width: 98%; word-break: break-all; "><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000; ">6</span><span style="color: #000000; ">) Operator Overloading<br>Do not overload operators except </span><span style="color: #0000FF; ">in</span><span style="color: #000000; "> rare, special circumstances.</span></div>不要重蝲操作W?同样, 也是避免莫名其妙的调用了一些函?同上一条一? 比如要提供对"=="的重? 可以提供一个名为Equal()的函? 如果需要提供对"+"的重? 可以提供一个名为Add()的函?<br><br><div style="background-color: rgb(238, 238, 238); font-size: 13px; border-left-color: rgb(204, 204, 204); padding-right: 5px; padding-bottom: 4px; padding-left: 4px; padding-top: 4px; width: 98%; word-break: break-all; "><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000; ">7</span><span style="color: #000000; ">) Function Overloading<br>Use overloaded functions (including constructors) only </span><span style="color: #0000FF; ">in</span><span style="color: #000000; "> cases where input can be specified </span><span style="color: #0000FF; ">in</span><span style="color: #000000; "> different types that contain the same information. Do not use function overloading to simulate </span><span style="color: #0000FF; ">default</span><span style="color: #000000; "> function parameters.</span></div>只有在不同的cd表示同样的信息的时? 可以使用重蝲函数.其他情况?一律不能?使用重蝲, 也可能出C些隐式出现的转换.所? 在需要对不同函数q行同样操作的时? 可以在函数名UCq行区分, 而不是用重?如可以提供针对stringcd的AppendString()函数, 针对intcd的AppendInt()函数,而不是对string和intcd重蝲Append()函数.另一个好处在? 在阅M码时,通过函数名称可以一目了?<br><br><div style="background-color: rgb(238, 238, 238); font-size: 13px; border-left-color: rgb(204, 204, 204); padding-right: 5px; padding-bottom: 4px; padding-left: 4px; padding-top: 4px; width: 98%; word-break: break-all; "><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000; ">8</span><span style="color: #000000; ">) Exceptions<br>We </span><span style="color: #0000FF; ">do</span><span style="color: #000000; "> not use C</span><span style="color: #000000; ">++</span><span style="color: #000000; "> exceptions.</span></div>不用异?理由如下:<br> <ul> <li>When you add a <code>throw</code> statement to an existing function, you must examine all of its transitive callers. Either they must make at least the basic exception safety guarantee, or they must never catch the exception and be happy with the program terminating as a result. For instance, if <code>f()</code> calls <code>g()</code> calls <code>h()</code>, and <code>h</code> throws an exception that <code>f</code> catches, <code>g</code> has to be careful or it may not clean up properly.</li> <li>More generally, exceptions make the control flow of programs difficult to evaluate by looking at code: functions may return in places you don't expect. This results maintainability and debugging difficulties. You can minimize this cost via some rules on how and where exceptions can be used, but at the cost of more that a developer needs to know and understand.</li> <li>Exception safety requires both RAII and different coding practices. Lots of supporting machinery is needed to make writing correct exception-safe code easy. Further, to avoid requiring readers to understand the entire call graph, exception-safe code must isolate logic that writes to persistent state into a "commit" phase. This will have both benefits and costs (perhaps where you're forced to obfuscate code to isolate the commit). Allowing exceptions would force us to always pay those costs even when they're not worth it.</li> <li>Turning on exceptions adds data to each binary produced, increasing compile time (probably slightly) and possibly increasing address space pressure. </li> <li>The availability of exceptions may encourage developers to throw them when they are not appropriate or recover from them when it's not safe to do so. For example, invalid user input should not cause exceptions to be thrown. We would need to make the style guide even longer to document these restrictions!</li> </ul> 上面提到的理׃, 我认Z用异常最大的宛_是:异常的用导致了E序无法按照代码所展现的流E去走的, 比如代码里面写了步骤一二三,但是假如有异常出? q就不好预知代码真正步进的步骤了, 在出现问题时, l调试和跟踪带来困难.<br>另外, 我更喜欢unix API的设?熟悉unix~程的h都知? unix API基本上都遵守下列规则:<br>a) q回0表示成功, 其他(一般是-1)表示p|.<br>b) 在失败时, 可以Ҏerrno判断p|的原? q些在man手册中都是会清楚的描q?<br><br>ȝ一? q䆾规范中规避的C++Ҏ大致分Z下几c?<br>a) 避免使用那些没有定行ؓ的特?如全局变量不能是类对象(初始化顺序不定), 不用编译器生成的默认构造函?构造行Z定), 异常(代码走向不确?.<br>b) 避免使用那些隐式发生的操?如声明单参数构造函Cؓexplict以避免隐式{? 不定义拷贝构造函数避免隐式的拯行ؓ, 不用操作符重蝲避免隐式的{?br>c) Ҏ׃可的Ҏ给予明的规定:不用函数重载而是定义Ҏ个类型明的函数.<br>d) 即出错了程序也有办法知? 比如不能在类构造函Cq行复杂的构造操? 这些移动到cInit()的函C.<br><br>同时, q䆾文档中描q的大部分C++Ҏ? 都是我之前所熟悉?除了RTTI之外, 不过q里提到它也是要说明不用它,另外q提到boost, 不过也是说的要对?有限?的?比如里面的智能指?.可以看到, 面对q样一门复杂同时还在不停的发展更新Ҏ的语言, google的态度是比?保守"?q与我之前对C++的理解也是接q的, 我一直认为C++中需要用到的特性有基本的面向对?STL够?l过最q的~码实践,我认得加个智能指?.我对q个"保守"态度的理解是, 以C++当前的应用场景来? q些Ҏ已l? 如果使用其他一些更加复杂的, 对h的要求提高了, 代码的可L以及以后的可维护性就下降?<br><br>前面说过, 避免问题的出现比解决问题来的更加高明? 而面对C++q一个提供了众多Ҏ? google C++ code stylel予了明的规定, 也就是每个行? 如果都能做到有明的动作, 同时l果也都是可以预知的, 那么会将出问题的概率最大可能的降低, 即Z问题, 也容易跟t?<br><br>上面描述的ƈ不是q䆾文中有关C++的所有内? 只不q我觉得q些更加有同感些, 详细的内? 可以参看q䆾文.都知道google的作?质量有保? 除了人的素质实高之? 有规范的制度保证也是重要的原? 毕竟只要是h׃犯错, Z最大限度的避免人犯? 有一份详的代码规范, 写好哪些该做哪些不该做哪些不该这么做, 也是制度上的保证.另外, 假如每个人都能以一个比较高的标准要求自己所写的代码, 久而久? 获得q步也是必然的结?<br><br>从这套规范里? 我的另一个感悟是, 不论是什么行? "学会如何正确的做事情", 都是十分必要?q个"正确的做事情", 具体到编码来? 是代码规范里面提到的那些要?而除ȝ? 做Q何的事情, 使用正确的方式做? 都是可能少的避免错误的Ҏ.但是, "???是相对而言? 没有之前"?的经? ׃好体会什么叫"?.所? "如何正确的做?, 说到了最? q得看个人的l验U篏, 有了之前"错误"的经?才能吃一堑长一? "错误"q不是一无是处的, 只不q? q不是谁都去试着从中学习.<br><br><br> <img src ="http://www.shnenglu.com/converse/aggbug/116689.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/converse/" target="_blank">那谁</a> 2010-05-29 20:34 <a href="http://www.shnenglu.com/converse/archive/2010/05/29/116689.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Callback在C\C++中的实现http://www.shnenglu.com/converse/archive/2010/04/19/113023.html那谁那谁Mon, 19 Apr 2010 14:45:00 GMThttp://www.shnenglu.com/converse/archive/2010/04/19/113023.htmlhttp://www.shnenglu.com/converse/comments/113023.htmlhttp://www.shnenglu.com/converse/archive/2010/04/19/113023.html#Feedback12http://www.shnenglu.com/converse/comments/commentRss/113023.htmlhttp://www.shnenglu.com/converse/services/trackbacks/113023.html阅读全文

那谁 2010-04-19 22:45 发表评论
]]>
Ҏ与工?/title><link>http://www.shnenglu.com/converse/archive/2010/04/15/112605.html</link><dc:creator>那谁</dc:creator><author>那谁</author><pubDate>Wed, 14 Apr 2010 16:57:00 GMT</pubDate><guid>http://www.shnenglu.com/converse/archive/2010/04/15/112605.html</guid><wfw:comment>http://www.shnenglu.com/converse/comments/112605.html</wfw:comment><comments>http://www.shnenglu.com/converse/archive/2010/04/15/112605.html#Feedback</comments><slash:comments>8</slash:comments><wfw:commentRss>http://www.shnenglu.com/converse/comments/commentRss/112605.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/converse/services/trackbacks/112605.html</trackback:ping><description><![CDATA[ 从最q遇到的几个故事说v.<br><br>故事一:<br>某天晚上和室友聊?谈到使用Vim阅读代码,室友也是使用Vim的h,他说用类似ctags的查扑֮位功能不?更多的时?他阅MD代?要定位一个功能点,首先是从阅读代码文g的组l?了解目的功能等入手,{这些都基本清楚?定位h׃快很?我虽然认?ctags实在是Vim里面一个很不错的功?不用q个实在可惜,但是他说的那套定位思\其实也是不错的方?其实我自q惯了ctagscȝ功能之后,阅读代码的时候也会用惰?更多的时候是要靠q些工具来帮我定?而不是通过自己d的思考和分析.<br><br>故事?<br>我的l验里面,写完一D代码之后的W一ơ编?如果~译器报错越?那么可以认ؓq段代码来可能出现bug的几率越?而言?我认Z码的质量与第一ơ编译的报错数量成反??不用拿helloworldcȝE序跟我ȝ角尖?).有些人写的代?哗哗的写了一大段,写之前不考虑?只想着到时候写的不对了可以在编译由~译器的报错来帮忙找问题,q个思\是不对的.~译报错少的代?说明了作者写的时候思\更清C?考虑的更周全一?所有的q些程上的步骤走的都不错了,所以才有最后编译报错少的结?~译报错应该是写代码的结果之一,而不应当当成了找代码问题的手D?q样的思\,本末倒置?<br><br>故事?<br>q入新项目组?l内对代码编码的程有比较严格的要求,包括写一个API之后需要写一个针对这个API的各U情늚试用例,提交代码的时?需要走codereview程,需要用cpplint验代码风?需要将对应的测试用例也提交上去.q一套流E走下来,提交代码的频率比之以?降低了很?但是不可否认的是,也确实提高了代码的质?假设一个功?由N个API构成,如果能对qN个API都做q详l的试,保证它们的输入和输出在各U情况下都能W合要求,那么很显然的,最后这个功能也应该是正的.反之,是C试阶段需要用类似gdbq样的调试器来定位问题的,会越让h不放?--因ؓ没有制度和流E的保证,谁也不能说将来可能在哪个点会出问?它可以帮你定位问?但是没有办法告诉你已l没有问题了,最后这一?最l还是要通过严格的单元测试等程来保证的.与第二个故事相同,我认?在测试阶D用gdb定位问题的次C与代码的质量成反?)<br><br>q几个故事综合v?惌表达的是,做一件事?需要有程,制度的保?当然也需要工?比如q几个故事里面提到的Vim,gcc,gdb),但是工具是工具,它只是一U手D?没有办法替代正确的思\,程和制度等,仅能在整个过E中起到辅助的作?而且,q分依赖工具,也会lh以惰?比如前面提到的用编译器~译代码来找?比如使用gdb来保证功能正性等).<br><br>所?更应该提倡的是正的程,制度,有了q些,目的质量才能有所保证.比如,在写一个功能点?需要具体分解ؓ哪几?每一步有哪几个API,针对它们的测试用例有哪些,试时的输入和输出有哪些,需要考虑的异常情冉|哪些,{等?q些都考虑清楚?再动手写,久而久?我想q方面的能力会慢慢的提高.<br><br><br><br><img src ="http://www.shnenglu.com/converse/aggbug/112605.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/converse/" target="_blank">那谁</a> 2010-04-15 00:57 <a href="http://www.shnenglu.com/converse/archive/2010/04/15/112605.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>memcached采用的网l模?/title><link>http://www.shnenglu.com/converse/archive/2010/03/11/109449.html</link><dc:creator>那谁</dc:creator><author>那谁</author><pubDate>Thu, 11 Mar 2010 12:30:00 GMT</pubDate><guid>http://www.shnenglu.com/converse/archive/2010/03/11/109449.html</guid><wfw:comment>http://www.shnenglu.com/converse/comments/109449.html</wfw:comment><comments>http://www.shnenglu.com/converse/archive/2010/03/11/109449.html#Feedback</comments><slash:comments>6</slash:comments><wfw:commentRss>http://www.shnenglu.com/converse/comments/commentRss/109449.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/converse/services/trackbacks/109449.html</trackback:ping><description><![CDATA[     摘要: memcached采用的网l模型是早前提到的半同步半异步的|络模型.  <a href='http://www.shnenglu.com/converse/archive/2010/03/11/109449.html'>阅读全文</a><img src ="http://www.shnenglu.com/converse/aggbug/109449.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/converse/" target="_blank">那谁</a> 2010-03-11 20:30 <a href="http://www.shnenglu.com/converse/archive/2010/03/11/109449.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss> <footer> <div class="friendship-link"> <p>лǵվܻԴȤ</p> <a href="http://www.shnenglu.com/" title="精品视频久久久久">精品视频久久久久</a> <div class="friend-links"> </div> </div> </footer> <a href="http://www.jianluanwang.cn" target="_blank">뾫Ʒþþþ</a>| <a href="http://www.1hkl.cn" target="_blank">˳˳ۺþþ</a>| <a href="http://www.gameforpeace.cn" target="_blank">޹ŷۺϾþ</a>| <a href="http://www.caifu580.cn" target="_blank">㽶þӰԺ</a>| <a href="http://www.aqbfrmi.cn" target="_blank">þˬ˾ƷƵ</a>| <a href="http://www.jvqn.cn" target="_blank">þһ</a>| <a href="http://www.8910wan.cn" target="_blank">ɫۺϾþۺۿ</a>| <a href="http://www.020xyk.cn" target="_blank">69þҹɫƷ69</a>| <a href="http://www.ppynw.cn" target="_blank">޾Ʒһþ</a>| <a href="http://www.top119.cn" target="_blank">97þþƷˬ</a>| <a href="http://www.ominimo.cn" target="_blank">þþþһëþþ</a>| <a href="http://www.lalaazg.cn" target="_blank">պŷۺϾþӰԺDs</a>| <a href="http://www.p7751.cn" target="_blank">þþþþþ</a>| <a href="http://www.huadublog.cn" target="_blank">þþ</a>| <a href="http://www.zjuny.cn" target="_blank">ǾþþƷ</a>| <a href="http://www.yrwe981.cn" target="_blank">Ʒþþþþù</a>| <a href="http://www.lakesys.com.cn" target="_blank">ҹƷþþþþž</a>| <a href="http://www.zzdls.cn" target="_blank">޹˾þþƷ99</a>| <a href="http://www.duteng888.com.cn" target="_blank">þۺ³³</a>| <a href="http://www.czcsbsb.com.cn" target="_blank">պƷþþվ</a>| <a href="http://www.nanling888.cn" target="_blank">WWWAVþþӰƬ</a>| <a href="http://www.smxqw.cn" target="_blank">þþƷAɫ</a>| <a href="http://www.xeqw.cn" target="_blank">޾ƷŮþþþ99С˵</a>| <a href="http://www.pnpxnc.cn" target="_blank">þþþþþþƷɫ</a>| <a href="http://www.netbirds.cn" target="_blank">þþƷavˮ</a>| <a href="http://www.cqhthj.com.cn" target="_blank">˾þô߽Ʒ</a>| <a href="http://www.zgsmkf.cn" target="_blank">&#228;v뾫Ʒþþ </a>| <a href="http://www.3828888.cn" target="_blank">þݺҹҹ2O2O</a>| <a href="http://www.www5303.cn" target="_blank">ƷþòҰ</a>| <a href="http://www.googledad.cn" target="_blank">þ99Ʒŷ</a>| <a href="http://www.c6t9.cn" target="_blank">þùAV䡪ٶ</a>| <a href="http://www.vqzt.cn" target="_blank">þۺϾþۺϾɫ</a>| <a href="http://www.wyhwan.cn" target="_blank">˳ɵӰվþ</a>| <a href="http://www.88177.com.cn" target="_blank">þ91Ʒ91þû</a>| <a href="http://www.lishi5.cn" target="_blank">һaƬþëƬ</a>| <a href="http://www.qian-mi.cn" target="_blank">ۺϾþþþ</a>| <a href="http://www.88815755.cn" target="_blank">ŷþһ</a>| <a href="http://www.51083114.cn" target="_blank">Ʒ99þѹۿ</a>| <a href="http://www.niluoya.cn" target="_blank">þֻоƷ߹ۿ</a>| <a href="http://www.whpcjs.cn" target="_blank">һձȾþۺ</a>| <a href="http://www.xsubmitter.cn" target="_blank">ھƷþþþӰԺ޹²</a>| <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body>