北戴河游记(一)
年轻人一向雷厉风行,从周二 (2007 年 6 月 12 日) 午饭之前开始有的想法,到随后做出决定,到周三午饭后搞定车子,到周四做好行前的必要准备,一切都是那么的想当然,那么的“听风就是雨”,难怪连同事都评论到:你们也真太快了!
还是先来认识一下我们这一干人等:
- 小米,嗯,是男生,事件的始作俑者,车主的儿子及我们的车夫;
- 小牛,唯一的女生,小米的老婆,一路都坐在副驾驶,可见对小米同学的驾车技术还是颇有信心;
- 文波,另一男生,想不到旅途中的他竟与工作中有那么大的差别,简直搞笑至极,用小米的话说就是:你丫太逗了。接下来的很多段子都是出自他的尊口……
- 最后一个就是我了,他们仨的独家摄影师,带了一个高像素的连自己都不会用的全自动带全手动支持的数码照相机。
自从计划定了以后,每个人就开始有自己的任务了。小米负责预定宾馆;文波负责搜集景点和旅游线路;我本来是负责买车票的,不过后来改成自驾游了,我就在家歇着好了,不过其间理了个头发,买了些衣服和游泳裤衩。接下来就是心浮气躁地等待周末的来临……
出发:旋转木马 (2007 年 6 月 15 日 18:00 至 19:00)
开始总得有点变故,还好是小变故。小米的项目被催得很紧,前几天不抓紧的他,险些在关键时刻被迫加班。不过尽管如此,还是为了给他调一段粗心的代码,浪费了近半个多小时的宝贵时间,就因为一个地方他多写了一个“s“。不过总算是搞定了,他老婆买了晚饭,说定在建外 SOHO 的旋转木马处等他。把老婆放了半个小时的鸽子,哥哥于是有些心急了。
蓝色的东风标志 307 很快地开到了门下,我和文波边鄙视他边上了车,不幸我坐在了副驾驶。之所以用不幸来形容,就是谁知道小米的技术的如何。虽然事后被证明还是不错的,不过这段路途还是把我吓了够呛。
小米说他喜欢开快车,着急的时候更喜欢开快车。可偏偏周五的下班时间,二环路上堵得一塌糊涂,从六点半出来到七点,也就挪动了一个公交车站的距离。于是小米开始加三、画龙、在长安街上超速、在国贸违章停车,总之用尽一切办法,还好在七点钟左右的时候,接到了小牛。
我和文波第一次见到了小牛和小牛开车。
Strong Enought to Break
一首奥运题材的歌曲
At this moment
We're waiting for the flame to be burning
Looking at the sparkle stars
Count down from the infinite
Until now, we're here together
In the ancient times
We warred each other spending our countless souls
Since when father became the god
They turned the killing into the games
And today, we win it with the glory
Give me your hand, and clap for me
Without your shouting I cannot sing
Give me your hand, and hold me up
No matter what can't break me down
Give me your hand, and pray for me
Even reality far from the dreams
Give me your hand, and trust me do
Give me your hand, to make me strong enough to break
我们的世界
今天午后散步的时候,在街旁,看到一个乞丐模样的年轻人枕着吉他在花池边上午睡。这可和我平时所见的衣着锦绣、个性张扬的路边弹唱者大相径庭。吉他不会因为主人的卑微而失声,音乐也更不会因为演唱者的身份而变得暗淡,也许唯一会的就是曾经心中的那份梦想,会被现实蚕食,而终被忘记……
我们的世界
不像你们想像得那样美好
华丽的生活
不管雨点在风中飘
有时也要忍饥挨饿
唱准每一个艰难的音符
有时也要风餐露宿
枕着吉他进入梦想
梦中都是音乐的酒吧
壁炉里迸出耀眼的火花
精灵的乐队
魔鬼的歌手
是摇滚与交响的合成
醒来还是这个肮脏的世界
没人愿意施舍多一点
拖着空虚的身躯
走向下一个地铁站口
拿起吉他
忘记所有的梦想
答 zhangdi 同学的问题
Zhangdi 同学说,评论我的《Java 和 .Net 在异常处理机制上的区别》帖子说:我并不认为 C#(.NET)这样处理 Exception 是好的。我觉得这与 strong-type 的概念相冲突。几个问题:
-
在设计一个接口的时候,是不是需要同时告诉用户,这个接口有可能抛出什么类型的 Exception?
答:这种说法自然是没错的,异常应该是接口设计的一部分,但是告知用户的方式可以有很多种。Java 的这种方式只是其中较为有效的方式之一,他通过编译器做出严格的限制,这其中兼有优劣。
-
如果需要,那么这个 Exception 类型是否应该成为一个接口声明的一部分?
答:其实这还要从程序整体的设计角度来讨论。在 Java 中非 RuntimeException 其实已经不是一种普通的异常那么简单。因为最终在程序运行的时候,Java 不允许有非 RuntimeException 被抛出到虚拟机,这也就是说这种异常看上去只存在于设计时。他更像是程序运行期间的一种消息传递机制,只是首先这种消息“有别于(Except)”其他的返回类型,另外就是它会沿着调用栈强行向上追溯。显然这种异常更多的是在程序设计阶段起到操控程序非正常运行时行为的作用。因此他更像是一种接口,自然声明这样的接口也是理所应当的。
但是 Java 还有 RuntimeException 的概念,而 .Net 或许就是没有区分他们而已,因为一旦程序遇到异常,无论是被程序本身恢复,还是被虚拟机捕捉到导致强行非法结束,都是可以接受的,毕竟对用户而言除了造成不方便,并不会有安全上的隐患。
-
一个已知的有可能发生的 Exception 被操作系统捕获是否可以说是用户在处理这个接口的声明的时候,出现了疏忽呢?
答:这个自然,如果不是 Java 概念中的 RuntimeException,那么如果真有这样的异常被虚拟机捕捉到肯定就是 Bug,但至少是一个安全的 Bug。而同时,就像我在帖子里说到的,需要在开发难度和设计完整性上达到一定的平衡。.Net 这样自然忽视了后者,但同时显然使用就方便多了。
-
strong-type 的目标是在编译器发现尽可能多的关于类型的错误,如果我们把接口的定义看作类型的一部分,那么是否可以说,这个有可能将 checked exception 暴露给操作系统的编译器在 strong-type 上有缺陷呢?
答:没看懂!:-)
还是那句话,我觉得我写这篇帖子已经足够公正了。.Net 在异常处理的设计上显然不如 Java 更趋近完美,但毕竟还是可以用的,还是好用的,剩下的瑕疵是可以通过程序员的经验,以及良好的开发习惯和管理来弥补的。
Java 和 .Net 在异常处理机制上的区别
关于 Java 和 .Net 优劣的争论一直在继续,而在异常处理方面体现得最为激烈,因为他们之间的差异是如此明显。.Net 晚于 Java 出现,那么 Java 对 .Net 就理应起到很重要的借鉴作用,但是伟大的 Anders Hejlsberg 为什么没有继续 Java 的实现方式,而是另辟蹊径,这是一个非常值得研究的问题。因为我们要承认一个真理:正确的东西大家都是一样的正确,错误的却各有个的错误。可以肯定这不可能是 Anders 的疏忽,那么他的道理究竟何在,或者说他们之间究竟有什么区别?
在你能耐下心来看完这篇帖子之前,我想要明确告诉你一个结论:Java 和 .Net 在异常处理的本质上是没有区别的。
一、Java 是如何处理异常的
如果一个 Java 方法要抛出异常,那么需要在这个方法后面用 throws 关键字定义可以抛出的异常类型。倘若没有定义,就认为该方法不抛出任何异常。如果从方法的入口和出口的角度去考虑一下这个规范,我们知道参数可以认为是方法的入口(当然某些情况下也可以是出口),而返回值则是方法的出口,这是在程序正常执行的情况下,数据从入口入,出口出。要是程序非正常执行,产生异常又当如何? 被抛出的异常应该如何从方法中释放出来呢? Java 的这种语法规范就如同给异常开了一个后门,让异常可以堂而皇之“正确”地从方法里被抛出。
这样的规范决定了 Java 语法必须强行对异常进行 try-catch。设想一下,对于以下的方法签名:
public void foo() throws BarException { ... }
暗含了两方面的意思:第一,该方法要抛出 BarException 类型的异常;第二,除了 BarException 外不能抛出其他的异常。而正是这第二点的缘故,我们要如何保证没有除 BarException 之外的任何异常被抛出呢? 很显然,就需要 try-catch 其他的异常。也就是说,一般情况下,方法不抛出哪些异常就要在方法内部 try-catch 这些异常。
Java 这样的机制既有优点,也有缺点。先来说说优点:
- 很显然,这种规范是由 Java 编译器决定的。倘若 Java 程序的入口点 main() 方法没有任何异常抛出,就是说要在 main() 方法内部,即整个程序内部捕捉所有的异常,否则将无法通过编译。这样编译器保证了程序对每个异常都有相应的计划和处理,不会有未处理的异常被泄露到虚拟机中,导致程序意外中断或退出,也就是增强了程序的健壮性。当然,Java 有 RuntimeException 的概念,这样的异常仍然可以随时被抛出到虚拟机中。
- 强行 try-catch 要求把异常作为程序设计的一部分看待。就如同方法的参数和返回值一样,在编写一个方法时,要结合上下文做出通盘的考虑和打算。虽然异常是所谓的“意外情况”,但是这些“例外”理应是被我们全部了解并处理的。
- 方便调试。异常理应在正确的位置被捕捉。当异常发生时,我们能更清楚的了解到其来源和相应处理程序的位置,而免去了在整个调用栈中摸索的麻烦。
- 在不借助任何文档的情况下,从方法签名就可以知晓应该对哪些异常进行处理。
Java 异常处理机制的这些优点也直接导致了他的致命弱点:将程序变得异常繁复。往往一个简单的程序,功能代码寥寥几行,而异常处理部分却占用了程序的绝大部分篇幅;同时导致缩进深度加深,既不利于书写,也不利于阅读。另外他的强行 try-catch 需要程序员有更高深的造诣,能够通盘考虑异常处理设计问题,这个在程序开始之初或者对于初学者是一个不小的门槛。这往往会阻碍其推广与发展,因为低水平初学者的信心往往因此而受到打击。然而对于高手来说,编译器是否能帮助他们找到未被处理的异常只是一个方便与否的问题,只要在编写方法时注意了异常处理,即便没有编译器的支持,情况也不会糟糕太多。反而倒是由于要遵循这样复杂的异常处理规范,以至于大多数人都可能为了图一时方便,对异常的基类型 Exception 或 Throwable 进行笼统地捕捉,这样做的危害就是那些你无法处理的异常被溺死在处理程序中,(按照异常处理原则,我们应该只捕捉那些可以被处理或恢复的异常,而把其他的异常继续抛出。至于这样做的优势,以及不这样做所带来的问题,不是一两句能够说清楚,这里就不展开讨论了。)导致程序的不稳定和不确定。既没有发挥 Java 语法在这方面的优势,反而增加了忧患。
二、.Net 是如何处理异常的
一句话概括 .Net 的异常处理方式就是随心所欲。没有人要求你一定要抛出异常,也更没有人要求你一定要捕捉异常。未被捕捉的异常会被以 Unhandled Exception 的形式抛出到虚拟机中。在此我就要先解决一下文章开头提到的问题,为什么说 Java 和 .Net 这两种异常处理机制在本质上是相同的。可以从两个方面来考虑:
- 默认情况下。Java 在默认情况下 main() 方法是不抛出异常的,正如前面所说的,这要求所有的异常都必须在 main() 方法内部被捕捉;而 .Net 则没有这种约束,他的 Main() 以至于整个应用程序中的任何一个方法对异常都是完全开放的。这样来看,这两者刚好是对立互补的。
- 非默认情况下。Java 可以通过在 main() 方法后面加 throws 关键字使得整个应用程序对异常开放;而 .Net 则可以通过给应用程序域(Application Domain)的 UnhandledException 事件添加委托达到捕捉所有异常的目的,很显然这又是对立互补的。
因此,就好像一个是“正反”,一个是“反正”,加在一起“正反反正”都是一样的,对于达到控制异常的目录来说,是没有区别的。
很多 Java 爱好者都鄙视 .Net 的这种行为,一方面他令程序变得不够健壮,因为默认情况下没有强制的办法要求所有的异常都被处理,或被正确处理;另外,他为调试增加了困难,不借助文档或代码你将无法了解到一个方法可能抛出什么异常,而当一个异常被抛出的时候,同时异常处理代码又写得不够完善,你将不得不仔细查看整个调用栈来确定异常出现的位置,而对于这一点 Java 默认是强制的。
但是 Anders 的想法总是有道理的。
- .Net 代码写起来非常容易。这是对于初学者,或者那些只是想实现一些测试性小功能的人而言,你完全没有必要考虑太多异常处理的细节,你要的就是写代码,然后让他跑起来。这样的简单性无疑是你希望看到的,这样的简单性无疑更有利于 .Net 在市场上的推广。由于他在这方面并没有什么理论上的漏洞,也就仍然适合构建庞大的项目,只是感觉没有那么舒服罢了。
- 一定程度上增加了程序的安全性。难道不捕捉异常可以被成为是安全的吗?这个话也许要从另外一方面来想,前面说过,有些 Java 程序员(绝对不占少数)为了图省事,在强行捕捉异常的压迫下,选择捕捉异常的基类型,也就是捕捉所有的异常。这样当有你无法处理的异常出现时,他们就溺死在了你的代码中,而外面的程序全然不知,还在以一种不确定的状态运行着,这就可能是危险的开始。而如果是 .Net,那么 Unhandled Exception 会被虚拟机捕获,导致程序异常退出,虽然这从面子上对于用户不是一个好的交代,但是深层次地他避免了程序在危险的状态下继续运行。
总之,萝卜白菜各有所爱。我的这篇帖子力求公正地讨论了这个问题,希望能对你有所帮助。
明天有雨
晚霞照亮了天
彩虹挂在我身边
下过雨的心情只想黑夜快快来临
血色的天际
没有月亮独自寻觅
混沌从天地开合之初流浪到这里
我的心里翻了天
远远近近都是白色闪电
惊天霹雳像远山那边男孩的呐喊
明天总该有雨吧
不然只有我一个人在哭
请不要再安排彩虹
生命中没有那样的演出
明天你不再来了吧
这样好不只我一个人孤单
鹊桥相合在七月初七
我的生命中没有那一天
测试驱动开发和软件开发流程模型
我终于决定不再继续看极限编程大师 Kent Beck 所写的那本 Test Driven Development: By Example 了。因为我实在无法忍受我与作者在软件开发流程模型上的分歧。但这并不妨碍我认同并实践作者所谓“测试先行”的理念。我是一个趋近完美主义者,因此我更喜欢像设计模式那样偏重设计的方法论,我不能认可一个靠不断修改而成长起来的软件。
按照 Kent Beck 极端的测试驱动开发模型,一个软件应该是这样写出来的:
- 写测试代码。
- 编译测试代码,编译无法通过。(因为没有实现代码。)
- 写一份最简单的实现代码,让编译通过。
- 迭代地修改代码以减少实现代码的重复度,降低实现代码和测试代码之间的耦合度。
就是这样,一个软件被一点一点修改而成。他强调了在这个过程中有两个主意事项:第一,在添加任何功能之前都要先写测试,除非代码是用于调试的,这也就是所谓测试先行的概念;第二,当编译无法通过时尽量不要再写新的测试。
我之所以不认同这个模型,就是因为其中间产生了大量的迭代过程,而这些过程很可能只在头脑中出现,或者根本就不曾出现。这些过程一方面增加了开发的消耗,也在某种程度上引入了更多的不确定性。但是其中测试先行的做法,能最大程度保证单元测试的完整性与正确性。
因此,我理想中的开发流程模型应该是这样的:
- 用户需求调研,导出成软件需求
- 根据软件需求进行设计
- 根据设计编写测试用例
- 根据测试用例编写测试代码
- 构建软件框架使测试代码能够编译通过
- 写 Mock 来保证测试用例代码准确无误
- 按部就班地写程序,用测试用例来保证所写的代码准确无误
这其中可以按照极限编程的思想以一个可独立发布可运行的模块作为单位,这样可以有效地控制模块的大小,还可以避免出现过度设计的问题。
在 Sourceforge 项目空间上部署 MediaWiki(2)
《在 Sourceforge 项目空间上部署 MediaWiki》的第一部分在这里。
造成 MediaWiki 不能向 config 目录写文件的原因,估计是 Sourceforge 服务器没有开放这样的权限。幸亏,MediaWiki 提供了一个变通的办法。找到下面的这些代码,把他们注释掉:
if( !is_writable( "." ) ) {
dieout( "<h2>;Can't write config file, aborting</h2>
<p>In order to configure the wiki you have to make the
<tt>config</tt> subdirectory writable by the web server. Once configuration is done you'll move the created
<tt>LocalSettings.php</tt> to the parent directory, and for added safety you can then remove the
<tt>config</tt> subdirectory entirely.</p>
<p>To make the directory writable on a Unix/Linux system:</p>
<pre>
cd <i>/path/to/wiki</i>
chmod a+w config
</pre> );
}
这样一来,当目录没有写权限的时候,操作不会被取消,而是生成的配置文件会以文本的形式被打印在页面上。把这些代码拷贝、粘贴到一个名为 LocalSettings.php 的文件,然后上传到 MediaWiki 的根目录,在我们这个例子中也就是 /home/groups/s/sa/sample/htdocs/wiki/ 就可以了。
最后还需要解决一下 session 的问题:
由于 Sourceforge 使用了服务器集群,所以把 session 保存在内存中是有问题的,所以需要用文件来存储 session:
- 在 /tmp/persistent/ 下面创建一个用来保存 session 的目录,例如 /tmp/persistent/sample/sessions。这里的 sample 就是你的项目的 unix name。因为这个名称是唯一的,所以不用担心会跟别人的重复。但注意千万不要把它建在你的 project 目录下,因为他们是不能被 web 服务器写入的。
- 确保这个目录是可写的,也就是执行一下 chmod a+w /tmp/persistent/sample/sessions。sample 仍然是项目的 unix name。
- 告诉 MediaWiki 使用这个目录来存放 session,方法是在 LocalSettings.php 文件的开始处添加 session_save_path("/tmp/persistent/sample/sessions/"); 注意不要丢掉 sessions 后面的那个 "/"。
如果你这样做之后,在编辑或查看页面的时候退出,碰到空白页面,请把 ini_set( "include_path", ".:$IP:$IP/includes:$IP/languages" ); 添加在上一步的 session_save_path 之前。
这样,你的 Wiki 就基本上可以在 Sourceforge 的项目空间上运行了,不过还有很多问题这里没有涉及到,比如:如何配置邮件系统、如何修改网站的 logo、或者是一些碰到的其他的问题。更多内容请详见 Running MediaWiki on Sourceforge.net。(中国大陆地区访问可能会有障碍。)
在 Sourceforge 项目空间上部署 MediaWiki
在开始部署之前,有一些准备工作要做:
- 你需要在 Sourceforge 上面拥有自己的帐号,并加入到一个项目,而且你的帐号在该项目中需要有访问 shell 的权限。同时确保该项目已经开通 MySql 数据库。
- 到 MediaWiki 的官方网站去下载 MediaWiki 1.6.8 版本。注意千万不要下载最新版本,因为 MediaWiki 从 1.7 版以后需要 php 5 的支持,而 sourceforge 服务器上部署的仍然是 php 4,因此无法运行最新版本。
- 从 PuTTY 网站上下载 PuTTY.exe 和 PSFTP.exe 。
为了方便,假设我在 Sourceforge 上拥有用户 usr,密码为 pwd,而且参与的项目为 sample。该项目的 MySql 数据库具有读写权限,可以添加、删除表和索引,并可以锁定表的用户为 mysqlusr,密码 mysqlpwd。
把下载来的 mediawiki-1.6.8.tar.gz 文件上传到项目空间,具体做法如下:
- 运行 psftp.exe
- 执行 open shell.sourceforge.net
- 按照提示输入你在 sourceforge 上注册的用户名,例如 usr
- 输入用户密码,例如 pwd
- 进入项目的 htdocs 目录,执行(以 sample 项目为例) cd /home/groups/s/sa/sample/htdocs/
- 把 mediawiki-1.6.8.tar.gz 复制到 psftp.exe 所在目录
- 运行 put mediawiki-1.6.8.tar.gz
- 待上传完成,关闭 psftp
解压已经上传的 mediawiki-1.6.8.tar.gz 文件:
- 运行 putty.exe
- 在 PuTTY Configuration 界面的 Host Name 中输入 shell.sourceforge.net,确认 Protocal 选中 SSH,然后点 Open
- 按照提示输入用户名,例如 usr
- 然后输入用户密码,例如 pwd
- 进入项目的 htdocs 目录,执行(以 sample 项目为例) cd /home/groups/s/sa/sample/htdocs/
- 执行 tar -xvzf mediawiki-1.6.8.tar.gz
- 将解压后的目录重命名为 wiki,执行 mv mediawiki-1.6.8 wiki
登录 phpMyAdmin,创建一个 Database,例如 wikidb。当然用 sourceforge 提供的 MySql 服务创建 Database 时,命名都需要有一个前缀,在此忽略。
打开浏览器,登录项目 Wiki,例如 http://sample.sourceforge.net/wiki。此时由于 MediaWiki 尚未配置,信息提示让你进入配置页面,点击进入配置页面,发现出错了。大意是说你的 config 目录没有写权限,让你在 MediaWiki 的安装目录执行 chmod a+w config 命令更改权限。但是,尽管你按照提示完成了设置,错误依旧。
本文的第二部分在这里。
【zz】天大四大才子
天大有四大才子之说。不过四大才子是谁,却是众说纷纭。
有人说是汪精卫、陈立夫、王宠惠、徐志摩。这种说法是最少的。当时我看了还真吓一跳,说我和徐志摩是校友还让我挺高兴,没想到汪精卫也是天大毕业的。汪精卫其人嘛!其实还挺才气的长相也很帅。可恨的是他是卖国贼。所以这种说法笔者不承认。
其它四大才子的说法都是关于当代天大的人物了,说法有以下几种:
1、社外才家瑞老师,孟宪堂,管院的汤伟刚,任保平
2、单平,才家瑞,刘晓纯,天南街卖烧卖的胖子
3、西门修车老大爷,西门地上写字的老大爷,美学第一人孟宪堂,才家瑞老爷子
4、等等……
据考证,第一种说法是最正确的。其中孟宪堂算是最无争议的人。人称他美学第一人——孟宪堂。他绝对是天大一宝,那自信劲是无人可比的。虽然笔者还没有上过他的美学概论,但是他的经典语录已略知一二。他的第一节课,就在 500 人的面前说:“中国近代有三大伟人——孙中山,毛泽东,孟宪堂。”紧接着台下晕倒一片。更有甚者狂吐三天不止。他曾说,五千年来没有人发现美,当然他本人除外。如果要学好他的课一定要把黑格尔的小逻辑和爱因斯坦的相对论搞个通通透透才行。但实际情况是考试前买本他出的书就能稳过,还能拿高分。他曾经指着一个女生说,我从她的身上看到开来的两列火车。还曾经指着一个男生谈论谈论学院里的男女问题时说,你是那个学院的?化工的!哦,那你除外,你们学院没有女生。
管院的任保平一点也不熟悉,不过汤伟刚却很有名气。汤老师自称管理学院资产第二,逢股必赢。他讲课慷慨激昂,粉笔沫到处飞扬,讲股评唯他独强,谈收益“不可抑制”的增长。今年上他课的时候每次教室都是人满为患,那可是大教室 24-117 一直以为同学很多呢,没想到到考试的时候仅有不到五十个。
才家瑞老先生,我在这正统四大才子李最后一个介绍,因为他是我唯一一个听过课的老师。对其比较了解。才老师的确很有才气,不听他的课是不知道的,不过由于他身体的原因还有其他事务,他可能带完我们这届就不再教学了。这令我们既觉得幸运又有些失望。才老毕业于北京大学历史系,他是台湾问题专家,所以经常在内地和台湾之间飞来飞去。他经常讲他的以往的故事,而且是重复重复再重复的讲法,使得我们对他的以前的事情了如指掌。才老喜欢美女,什么年轻时在北大认识的美女,在新疆别人给介绍的演员,我们都经常听他讲述。不过最终他娶的老婆并不是美女,这事情说来话长了,要讲到他毕业,去新疆什么的老长老长。在这里就不讲了。才老师虽然年纪很大,但是在给我们讲课的时候却很开放。他经常在课堂的谈性,还经常告诫女同学要做好安全措施。我们平常一谈到才老都会想到他的两大主要思想,即熄灯要睡觉,上床要带套。哎!这老头子什么时候想起来都觉得开放得要命。我们这群年轻人都自愧不如。
接下来要讲讲,其余的非正统四大才子中的人物了。西门有个修车师傅,原来是天大的一个老师,留学过日本,退休后闲不住,修车,自学了四国外语,和留学生聊的最起劲儿。记得有个师兄告诉我们在天大千万别嚣张,修自行车的都比你学历高,说的就是他。还有一个写大字特别漂亮的老爷爷,经常在空地上拿粉笔写大字,我曾经看见过他写的怀念周总理的诗。写的是那种空心的楷书,不打格直接就写,工工整整的真叫人佩服。天南街的二胖子,“哎!同学烧卖,还有锅贴啦,虾仁乱蹦哦!”不知道有什么才,但是似乎大家挺喜欢他的。41 斋外面买鸡蛋大饼的算一个,据说年轻时在内蒙古混过,一根九节鞭打遍内蒙无敌手(这是他的原话)。