代码猴子与童子军军规

Posted: 八月 25th, 2009 | Author: | Filed under: X-Files, 胡编 | 3 Comments »

2007年3月,我在SD West 2007技术大会上聆听了Robert C. Martin(Uncle Bob)题为Craftsmanship and the Problem of Productivity: Secrets for Going Fast without Making a Mess的主题演讲。一身休闲打扮的Uncle Bob,以一曲嘲笑低水平编码者的Code Monkey(代码猴子)开场。

是的,我们就是一群代码猴子,上蹿下跳,自以为领略了编程的真谛。可惜,当我们抓着几个酸桃子,得意洋洋坐到树枝上,却对自己造成的胡乱熟视无睹。那堆“可以运行”的乱麻程序,就在我们的眼皮底下慢慢腐坏。

从听到那场以TDD为主题的演讲之后,我就一直关注Uncle Bob,还有他在TDD和整洁代码方面的言论。去年,人民邮电出版社计算机分社拿一本书给我看,封面上赫然写着Robert C. Martin的大名。看完原书序和前言,我已经按捺不住,接下了翻译此书的任务。这本书名为Clean Code(《整洁代码》),乃是Object Mentor(Uncle Bob开办的技术咨询和培训公司)一干大牛在编程方面的经验累积。按Uncle Bob的话来说,就是“Object Mentor整洁代码派”的说明。

正如Coplien在序中所言,宏大建筑中最细小的部分,比如关不紧的门、有点儿没铺平的地板,甚至是凌乱的桌面,都会将整个大局的魅力毁灭殆尽。这就是整洁代码之所系。Coplien列举了许多谚语,证明整洁的价值,中国也有修身齐家治国平天下之语。整洁代码的重要性毋庸置疑,问题是如何写出真正整洁的代码。

本书既是整洁代码的定义,亦是如何写出整洁代码的指南。Uncle Bob认为,“写整洁代码,需要遵循大量的小技巧,贯彻刻苦习得的‘整洁感’。这种‘代码感’就是关键所在。……它不仅让我们看到代码的优劣,还予我们以借戒规之力化劣为优的攻略。”作者们阐述了在命名、函数、注释、代码格式、对象和数据结构、错误处理、边界问题、单元测试、类、系统、并发编程等方面如何做到整洁的经验与最佳实践。长期遵照这些经验编写代码,所谓“代码感”也就自然而然滋生出来。更有价值的部分是Uncle Bob本人对三个Java项目的剖析与改进过程的实操记录。通过这多达三章的重构记录,Uncle Bob充分地证明了童子军军规在编程领域同样适用:离开时要比发现时更整洁。

接触开发技术十多年以来,特别是从事IT技术媒体工作六年以来,我见过许多对于代码整洁性缺乏足够重视的开发者。不算过分地说,这是职业素养与基本功的双重缺陷。我翻译《C#编程风格》(已由人民邮电出版社出版)和《整洁代码》,实在也是希望在这方面看到开发者重视度和实际应用的提升。

在《整洁代码》结束语中,Uncle Bob提到别人给他的一条腕带,上面的字样是Test Obsessed(沉迷测试)。Uncle Bob“发现自己无法取下腕带。不仅是因为腕带很紧,而且那也是条精神上的紧箍咒。……它一直提醒我,我做了写出整洁代码的承诺。” 有了这条腕带,代码猴子成了模范童子军。我想,每位开发者都需要这样一条腕带吧?

 

(《整洁代码》中文版一书即将由人民邮电出版社推出。)


迁移Blog平台

Posted: 七月 17th, 2009 | Author: | Filed under: 胡编 | Tags: , | No Comments »

实在受不了Community Server的弱智垃圾评论处理手段,因为它不开源,自己修改也很麻烦,所以决定迁移到Word Press。由于hanlei.name原来用的数据库服务器只对内网开放,故WP提供的直接迁移手段用不了。折腾半天后,终于找到近乎完美的解决方案:

1、用Keyvan Nayyeri编写的Community Server 2.1 BlogML Converter,格式导出CommunityServer的数据(BlogML格式)。过程很简单,按压缩包中的文档指示,把文件传到CS相应目录下,到后台访问SyndicationOptions.aspx(“RSS设置”),在BlogML那个位置点“Export”,就会在新窗口打开导出后的XML文档。

2、用Aaron Lerch编写的WordPress BlogML Import工具在WP后台导入BlogML数据。Wayne John修改了这个工具,修正了一些小问题。Wayne John版本在这里下载

3、实际上Wayne John的版本也有问题,WP 2.7以上的都支持不好,而我的版本是2.8.1。我找到了这篇文章,根据文章指引,终于完成导入。

整个过程中有几点要注意:

1、CS要运行于ASP.NET 2.0平台;

2、第三步所需时间较长,Apache缺省的30秒执行时间不够,我修改了耗时最长的一个模块(plugin.php),使之支持60秒执行时间;

3、貌似对分类的支持还有问题,需要手工调整;

4、导入后页面上会给一个新旧链接对照表,可以据此做URL Rewrite,我的虚拟主机不支持编辑.htaccess,有空的时候在WP基础上写点代码实现跳转吧。

上面提到的BlogML导入工具,及修改后的plugin.php,可以在这里下载


Flickr for LiveWriter和谐版

Posted: 十月 16th, 2007 | Author: | Filed under: 胡编 | No Comments »

我一直用微软的Windows Live Writer写Blog。最近,由于大家知道的原因,Flickr!图片不能访问,所以LiveWriter的Flickr!引用插件也运行不正常。

后来装了伊朗人的Firefox插件,在Firefox里面倒是可以看到图片,但LiveWriter还是用不了Flickr的图片。我查看了Firefox插件的代码,对照里面给出的替换URL,照葫芦画瓢修改Flickr for LiveWriter插件的代码。没花什么功夫,就简单粗暴替换了一下URL地址。方法虽然烂,能用就行。

如果你也用LiveWriter写Blog,并且需要在LiveWriter里面引用Flickr的图片,可以使用这个修改好的和谐版插件。下载地址是:http://download.csdn.net/source/264275。压缩包里面有源代码和编译好的DLL(根目录的bin目录下)。把该DLL放到LiveWriter的Plugins目录下就可以了。有闲心的同学,不妨把它改得更灵活些,把硬编码的部分干掉。


《Beginning C# Objects中文版》勘误

Posted: 九月 10th, 2006 | Author: | Filed under: 胡编 | 5 Comments »

有热心读者在Dearbook上贴出这本书中的一些错误,我一一作了回复,整理转贴如下:

对于使用C#的OO出学者来说,这确实是难得的好书。我是抱着重新梳理一下OO知识的心态来看的,虽然到目前(刚看完第五章)还没遇到什么特别精彩的文字,但是层层推进的写作风格和出色的翻译还是把该讲到的知识点都讲到了,而且还对易混淆的地方做了重点解释,比如override和overload。

  但是今天看书的过程并不是太愉快,因为发现了几处比较严重的错误(严重=颠倒了事实,对初学者很不利),在这里贴出来,有些也可能是我理解错了,还请译者和读者甄别:

  
  1.P59,正数第8行
   原文: “引用变量的名称遵循方法和attribute的命名惯例,即使用Pascal命名法。”
   修改后:“引用变量的名称遵循方法的attribute的命名惯例,即使用Camel命名法。”
   严重程度:★★★★★ /把本来要说明的问题说得更混乱了,很严重!

韩磊按:原文:Names for reference variables follow the same convention as method and attribute names: i.e. they use Pascal casing.而举例则是使用Camel命名法。按照C#命名惯例,引用变量应遵循Camel命名法(和attribute一样)、而方法名遵循Pascal命名法。显然,原书此处有误,应改为:Names for reference variables follow the same convention as attribute names:i.e. they use Camel casing。译文:引用变量的命名遵循与attribute一样的命名约定,即,使用Camel命名法。

  2.P93,代码里MoneyOwed()方法的第三行注释
   原文: “即便它们没声明为私有”
   修改后:“即便它们声明为私有”
   严重程度:★★★★★ /把关键的话说反了,很不应该!

韩磊按:P93,public double MoneyOwed()方法注释,原文:We can access attributes of this class (totalLoans and tuitionOwed) — even they are declared to be private! — without using dot notation.
译文的确有误,把“声明为私有”错误地译作了“没声明为私有”,回想起来,应该是受了那个without的影响,不可原谅啊!

  3.P108,从4.5.3行开始数,第8行
   原文: “可以在客户代码中修改”
   修改后:“可以在提供服务代码中修改”
   严重程度:★★★★★ /把关键的话说反了,很不应该!

韩磊按:原文:its private data structure and/or its accessor code — can change without affecting how and object belonging to that class gets used in client code。译文应为“可以修改其私有数据结构和/或其访问器代码,而不会影响到使用该类的客户代码中的对象”。

  4.P130,倒数第10行
   原文: “继承常常指出两个类之间的“A是B”关系”
   修改后:“继承常常指出两个类之间的“IS A”关系”
   严重程度:★★★★ / 结合上下文,B派生于A,这里应该是“B是A”才对。

韩磊按:严格来说,在上下文中的确应为“B是A”。

  5.P145,倒数第6行
   原文: “重要提醒:C#中这样做是可以的!!!”
   修改后:“重要提醒:C#中这样做是不可以的!!!”
   严重程度:★★★★★ / 为了这个重要提醒,我还特意做了实验,没弄明白怎么就可以了呢?!况且在P144页里也明确说了C#不支持多重继承,那么这个重要提醒是什么意思呢?

韩磊按:的确应该为“在C#中是这样做是不可以的”。

我由衷感谢这位读者,他指出了我们的失误,实际上是对我们工作的促进和帮助。在下次印刷时,这些错误将得到修正。同时,我也要向所有读者致歉;无论如何,中文版中出现这样的错误,都是译者的责任。


TrackBack Spam:一颗老鼠屎真的能坏一锅汤

Posted: 六月 15th, 2005 | Author: | Filed under: 爱踢, 胡编 | 9 Comments »

最近DoNews Blog又时常出现不稳定的状况。Keso告诉我,怀疑是trackback spam在捣乱,因为每次不稳定,随后都会看到一大堆垃圾trackback。

嗯,关于trackback spam,早有听闻、亦已目见,只是从来没觉得它会对系统运行产生什么影响。可巧今天DoNews Blog突然又出问题,用性能查看器一检查,每秒访问数剧增,很多请求不得不排队,请求队列排满后,就不断被弹出、拒绝服务。于是——大家熟悉的黄屏错误就出现了。

清空Cache、清理缓存池、重启IIS、重启服务器都没用,被拒绝的请求数直线上升。这时候,我想起了Keso的怀疑。查询一下数据库,嗬,短短时间内,成百上千条trackback spam出现在眼前。再仔细查看,大概是这么几种:卖伟哥的、开赌场的、以及放高利贷的。嗯,域名五花八门,都围绕pharmercy、gambling、poker、loans打转转。查IP,发现它们来自于不超过4个站点。暂时停止trackback功能后,blog恢复正常。

然后我开始上网搜trackback spam,查询结果满满当当2,450,000项。嗯,整个blog世界,都在为这种垃圾烦恼呢!

有一个名为MT-Blacklist/Comment Spam Clearinghouse的站点,专门研究如何阻止trackback spam。虽然它是针对MT系统的,不过对改造.Text也颇有帮助。我想说的不是技术问题,而是其中一篇文章。这篇文章列出了根据内容判断一条trackback是否spam的正则表达式。一看之下,不禁笑出声来。原来,让老外烦恼的那些trackback spam,其中一些也就是让DoNews Blog不正常的那些。

看看URL匹配黑名单——

URLPattern Action
casino Block
penis Block
viagra Block
poker Block
pills Block
hentai Block
zoo Moderate
teen Moderate
incest Block
ambien\b Block
blackjack Block

有趣吧?hentai、zoo、teen和incest似乎在DoNews Blog没有见过,其他词都是老熟人了。黄赌毒,此trackback spam之三要义也。从国外blogger的反馈来看,trackback spam很多来自少数几个网站。Trackback这么好的理念和实现,就这样被无耻地利用了。几颗老鼠屎,确乎是可以坏一锅汤的。最怕有一天,中国人突然学会了利用trackback spam……


C# FAQ:关于泛型

Posted: 三月 16th, 2004 | Author: | Filed under: 胡编 | 3 Comments »

(本文来自Microsoft C# Team的FAQ Blog。我会尽量跟踪这个站点,并不断增补内容。)


Q: C#泛型与C++ templates相比如何?


A: 这个问题相当复杂。


Anders曾在一篇访问中提到这个话题。


需要说明的是,泛型和templates的目的并不一样。有些工作templates做起来比泛型好,反之亦然。


模型(Model)


C++ templates使用编译时模型。当在C++程序中使用templates时,如同有一个微宏处理器在起作用一般。


C#泛型不只是编译器的一个特性,也是运行时环境的特性。类似List<T>这样的泛型类型,在编译后仍保有其泛型特质。换言之,C++编译器的替换工作,在C#泛型世界中是由JIT完成的。


错误检查


通过例子能最好地说明。考虑一个template,其中包括方法如下:


T Add(T t1, Tt2)
{
    return t1 + t2;
}


C++编译器能正确解析此方法。当template被真正地调用时,“T”会被真实类型所替代。设若使用的是int类型,则编译器能正确创建Add方法,因为它明白两个整数如何相加。


但如果使用类似“Employee”这样的类型,编译器将出错,因为它不了解如何相加两个“雇员”。


泛型则不然。因为在编译时并不知道具体类型,所以必须通过泛型类的方式来让编译器了解类型的额外信息。


这通过约束(constraints)来实现。Contraints允许作者规定泛型类型支持的数据类型。


例如:


Class List<T> where T:IComparable


意味着无论何时使用T,都可以往CompareTo()函数中传入T并调用该函数。


约束能提供与templates几乎相当的灵活性,但需要很复杂的约束语法。对于Whidbey,约束只能规定某些操作。


例如,无法约定泛型类型必须拥有一个add操作符,所以不能在泛型类中写“a+b”。


可以在运行时使用反射来实现,但实现上味道不清爽,也会带来性能损失。在未来版本中也许会解决这个问题。


运行时操作


C#泛型拥有完全的运行时支持。你可以在泛型类型上执行反射,在运行时创建泛型类型。在C++中没有同等功能。


空间使用


C++和C#对空间的使用不一样。C++ templates在编译时完成,每种类型都会在编译代码中占用独立空间。


在C#中,对特定类型的实现在运行时创建。当运行时环境创建类似List<int>这样的类型,JIT将查看是否之前创建过这种类型。如果已创建过,将直接使用创建了的代码。如果没有创建过,将获取编译器创建的IL代码,用真实类型进行替换。


其实这并不完全正确。对于每种值类型,都会有单独的本地代码路径。引用类型可以互相分享其实现。


所以,C#泛型占用较少磁盘空间和内存空间,比C++ Template有优势。


实际上,C++ 连接器有一种名为“template folding”的特性。C++连接器寻找同样的本地代码段,如果找到,则把它们放到同一目录。


Template元编程


C++ templates有时用于template元编程(metaprogramming)。C#中没有这种特性。


[作者:Eric Gunnerson]


测试客户端发贴

Posted: 十二月 7th, 2003 | Author: | Filed under: 胡编 | 2 Comments »

测试一下客户端发贴。如果没有问题,明天就加入其它细节功能和效果


分段


.Text简单客户端几近完成

Posted: 十二月 6th, 2003 | Author: | Filed under: 胡编 | No Comments »

可是服务器终端连接不上了……暂时无法使用。:-(


设置TextBox的PasswordChar属性

Posted: 十二月 4th, 2003 | Author: | Filed under: 胡编 | No Comments »
if (ckbShowPassword.Checked){
  tbPassword.PasswordChar='\0'; 
}
else{
  tbPassword.PasswordChar='*';
}

用tbPassword.PasswordChar=’ ‘;是不行的。其实char类型的初始值就是’\0’,在这里不过是还其本来面目罢了。


一篇有意思的文章

Posted: 十二月 3rd, 2003 | Author: | Filed under: 胡编 | 1 Comment »

先来看看效果吧——

文章地址:http://www.codeproject.net/cs/miscctrl/flagseditor.asp