- 一月
-
- 在元旦的锐豪杯围棋赛中,Juha七盘五胜,成功晋级一级。
- 迪卡侬弄了一台椭圆机,要锻炼身体啦。
- 同事彬彬离职。
- 爸妈红宝石婚家宴。
- Stefan Rink到杭州来传道,说服中国这边用puppet配置测试环境。
- 春节,大年初一去看了电影《大话天竺》,妈在电影院里睡着了。
- 到大悦城坐摩天轮。来家过年的亲戚去东海大桥。
- 二月
-
- 跑了几次医院。
- 买了一块2T的硬盘。
- 按照往年惯例给江妹下载超级碗录像。
- 小学开学。
- 买了两本书,《笔记术》和《数据术》,都是日本人写的。
- 同事给我留下的月流量5G的联通卡失效,买了一元一天五百兆流量卡。
- 办公室换座位,新座位0712A,打印机边过道处。
- 三月
-
- 115上续费一个月。
- 飘鹰健身卡到期,练习最后一次。
- Juha拍照,申领新一期身份证。
- 同学移民澳洲,告别宴。大雨,在中山公园附近日本料理。
- 四月
-
- 为了方便,买了一台佳能的打印机,喷墨的。
- puppet的事情还是落在我头上,之前我只玩过玩具,这真的要进入生产环境了。
- Juha参加小应氏杯,胜一场。
- 肇嘉浜路医院边上谈了一次。
- 115又续费一个月。
- 秋霞带孩子们来上海。姐妹团聚。
- Juha摔跤,休息三周。
- 五月
-
- 继续用puppet配置环境,已经可以规模化了。
- Juha新身份证拿到。
- 开始晚上在办公室加班生活,很晚才回住处。
- 还掉居委会的轮椅,使用费20快,日均一元。
- 出差到上海部门帮搭建puppet,一周时间。
- 杭州Team Building,去汗蒸,吃两顿。很爽。
- 百度会员买了个季卡,72块。
- 六月
-
- 配了新眼镜。
- “无支持”会议。
- 到杭州城里转一圈。
- 去了一次海洋馆,家庭卡就到期了。
- 开始玩ELK,想在开发环境中起作用。
- 月底决定了转到上海的部门。
- 七月
-
- 暑假开始。
- 佘山、朱家角游玩。
- 衢州探亲。周末游览水亭街。
- 杭州旅游四天。
- 持续优化AutoHotKey脚本。
- 出差在上海,为正式转移做准备。
- 八月
-
- 北京旅游一周,住前门富力。
- 长城、故宫、牛街、德云社、天坛、北海;见小舅。
- 在电脑上装luajit,现在已经想不起来缘由了。
- 34周开始在上海工作。
- 上海puppet重新部署。
- 九月
-
- 见青岛同事,问黄岛事。
- 参加为期四天的Java培训。
- 老付到上海传经一周。可以学习的东西很多很多。
- 十月
-
- 衢州三个孩子到上海过假期。
- 115又续费一个月。
- 参观自然博物馆。
- 树莓派上机器人重新部署起来。
- SCM向Git迁移启动会。
- 新部门,新领导。
- 为老付的项目做贡献,写Keyword,要写成递归的。
- 男人四十。
- 十一月
-
- 到江湾体育场看三对三篮球赛。看见活的邱峻。
- Juha封窝沟。
- Juha学会骑自行车。
- 为知笔记续费,买一送一。
- 给家里装上监控。
- Team Building,滨江森林公园烧烤,半天。看见了黄浦江和长江交界的地方。
- 在大学参加git的培训,半天。觉得讲得一般,但是事后发现能讲好很难。
- 见吕丰一家。
- 修理iPhone 5S。没几天屏幕又碎了。
- 看电影Coco,曲阳电影院。
- 十二月
-
- Juha开始篮球训练。
- 着手解决netboot问题。
- 周末到柚子的工作室玩一个。
- 到天潼路吃好吃的东北菜。
- 给部门做教室内的git培训,失败。需要总结的点有很多很多。
- 和同学见面,交流软件开发流程。
- 小超和Juha过生日。
- 到杭州一天,和饭团吃饭;办公室里问问题。
- 同学回沪,聚会吃饭唱K。
Git 基础培训
12月14日的时候在部门内组织了一次Git的基础培训,效果不太好。
对于效果为什么不好,我觉得有一些原因。
- PowerPoint的演示我用得太少。我借了一个投影仪,用了复制模式。按理说我笔记本的屏幕应该和幕布应该显示同样的内容,但是,PowerPoint在播放的时候在笔记本上显示的演讲者模式,幕布上就用不一样的分辨率显示观众内容。这个是我始料未及的。由于分辨率的改变导致观众内容非常模糊,所以在前半部分根本在和银幕做斗争。后来,我干脆不播放PPT,直接在Bash窗口里打我的命令,效果反而好些。
- 准备的东西有点儿多,进程也编排得有点花哨。忽略了受众是常年用SVN,对分布式版本控制完全没有概念的。解释起来有一定的难度。应该拆成两个培训,可能效果会好一些。
- 下次如果有机会再做这类的培训,我会选择Jupyter Notebook来做演示;或者写扁平风格的PPT来做,不要动画效果,朴实一些。
我准备的材料差不多是下面的这些。
0
Centralized VCS: designed with the intent that there is One True Source that is Blessed, and therefore Good.
Distributed VCS: systems are designed with the intent that one repository is as good as any other.
1 Git
Since 2005 created by Linus Torvalds
Installations
Linux: apt-get install git
Windows: Git for Windows(Git Bash)/TortoiseGit/SourceTree
Basic configurations
git config –global user.name “Your name”
git config –global user.email [email protected]
git config –global color.ui true
Commands
Basic Commands
- init
- add
- commit
- status
- log
- diff
- show
- mv
- rm
- reset
Branch Related Commands
- branch
- checkout
- merge
- rebase
Collaborating Commands
- clone
- fetch
- push
- pull
2 Basic Workflow
Like SVN
- git init
- git status
- git add
- git commit
- git log
- git diff
- git tag
Branching
- git branch
- git checkout –b xxx
- git merge xxx
Stashing
- git stash
- git stash apply
- git stash pop
- git stash drop
- git stash list
3 Collaborating with Other Colleagues
GitLab or GitHub
Creating Repositories
- git remote add origin https://gitlab/stefanzweig/gittraining.git
- git push -u origin –all
- git push -u origin –tags
Cloning others’ Repository
Collaborating Commands
- git fetch origin
- git merge origin/master
- git push origin master
- git pull origin master
- git remote add pekka https://gitlab/pekka/gittraining.git
4 Other Tips
I am so sorry that I have done these…
- git checkout — files
- git reset –hard/–soft
I can ignore the conflicts, using mine…
- git checkout –ours/–theirs
I need one node, instead of whole branch
- git cherry-pick
What have I done in this repo?
- git reflog
Comprehensive logs
- git log v2.5.. # commits since (not reachable from) v2.5
- git log test..master # commits reachable from master but not test
- git log master..test # commits reachable from test but not master
- git log master…test # commits reachable from either test or master, but not both
- git log –since=”2 weeks ago” # commits from the last 2 weeks
- git log Makefile # commits that modify Makefile
- git log –no-merges # dont show merge commit
Python 的 with 语句(2)
我们经常既想利用with语句的便利,又不想很麻烦的写一个类来实现__enter__() 和 __exit__()方法,有什么比较现成的办法呢?
Python的标准库里引入了contextlib 模块可以解决这个问题。contextlib 模块提供了装饰器contextmanager,使用这个,可以对已有的生成器函数或者对象进行包装,加入对上下文管理协议的支持,避免了专门编写上下文管理器来支持 with 语句。
contextmanager 用于对生成器函数进行装饰,生成器函数被装饰以后,返回的是一个上下文管理器,其 enter() 和 exit() 方法由 contextmanager 负责提供。被装饰的生成器函数只能产生一个值,否则会导致异常 RuntimeError,产生的值会赋值给 as 子句中的 target,如果使用了 as 子句的话。
from contextlib import contextmanager
@contextmanager
def demo():
print '[Allocate resources]'
print 'Code before yield-statement executes in __enter__'
yield '*** contextmanager demo ***'
print 'Code after yield-statement executes in __exit__'
print '[Free resources]'
with demo() as value:
print 'Assigned Value: %s' % value
例子的执行结果是:
[Allocate resources]
Code before yield-statement executes in __enter__
Assigned Value: *** contextmanager demo ***
Code after yield-statement executes in __exit__
[Free resources]
可以看到,生成器函数中 yield 之前的语句在 __enter__() 方法中执行,yield 之后的语句在 __exit__() 中执行,而 yield 产生的值赋给了 as 子句中的 value 变量。
需要注意的是,contextmanager 只是省略了 __enter__() / __exit__() 的编写,但并不负责实现资源的“获取”和“清理”工作;“获取”操作需要定义在 yield 语句之前,“清理”操作需要定义 yield 语句之后,这样 with 语句在执行 __enter__() / __exit__() 方法时会执行这些语句以获取/释放资源,即生成器函数中需要实现必要的逻辑控制,包括资源访问出现错误时抛出适当的异常。
贴一下contextmanager的实现。用的时候就当成一个修饰器(decorator)来用。
def contextmanager(func):
"""@contextmanager decorator.
Typical usage:
@contextmanager
def some_generator(<arguments>):
<setup>
try:
yield <value>
finally:
<cleanup>
This makes this:
with some_generator(<arguments>) as <variable>:
<body>
equivalent to this:
<setup>
try:
<variable> = <value>
<body>
finally:
<cleanup>
"""
@wraps(func)
def helper(*args, **kwds):
return GeneratorContextManager(func(*args, **kwds))
return helper
另外说一句。with 语句的管理上下文的能力在python中往往被定义成设计模式的一种。下面就是一个例子。其实就是实现上下文管理协议,但是名字叫ResourceAcquisitionIsInitialization(资源获取初始化)。只贴代码,不另外做解释了。
class Box(object):
def __init__(self, name):
self.name = name
def __enter__(self):
print("Box " + self.name + " Opened")
return self
def __exit__(self, exception_type, exception, traceback):
all_none = all(
arg is None for arg in [exception_type, exception, traceback]
)
if (not all_none):
print("Exception: \"%s\" raised." %(str(exception)))
print("Box Closed")
print("")
return all_none
#===============================================================
if (__name__ == "__main__"):
with Box("tupperware") as simple_box:
print("Nothing in " + simple_box.name)
with Box("Pandora's") as pandoras_box:
raise Exception("All the evils in the world")
print("end")
-EOF-
Python 的 with 语句(1)
最近组里在CoDe(Competence Development,能力培养)。花姐讲文件操作,例子里有如下的代码:
with open(r'demo.txt') as f:
for line in f:
print line
# ...more code
语句很简单,就是把demo.txt文件打开,逐行打印出来。我感兴趣的是这里的with语句,这个用法很简洁,比下面的try … except 用法要少一些代码量。
f = open(r'demo.txt')
try:
for line in f:
print line
# ...more code
finally:
f.close()
可以看到,下面的这种用法代码稍微复杂一些,还涉及到了文件的关闭操作。而with语句是怎么避免了显性的关闭文件呢?更进一步,with这个语句是怎么实现的,它的目的和好处是什么呢?
对比着看,可以感觉到with做了一系列的操作,准备工作、用户代码、扫尾工作。准备工作就是打开文件并且返回文件句柄(是不是这么定义?),用户代码就是中间那一部分逐行打印。扫尾工作就是关闭文件。
再做一个类比。在用robotframework做自动化测试时,总会定义 suite setup 和 suite teardown,这就是保证测试的进入和退出都有一定的保护措施,进入时做准备,退出时打扫战场。Python 的 with 语句就是suite setup 和 suite teardown的作用,是Python 2.5以后引入的特性。
在Python 2.5里要通过
from __future__ import with_statement
才能使用with 语句,到了Python 2.6就可以直接用了,它从一个实验性的特性变成了内置的了。
直接了当说,with的原理是实现了一个上下文管理协议(Context Management Protocol),而这个协议的两个必要部分就是两个方法,__enter__() 和 __exit__(),任何支持该协议的对象要实现这两个方法。一目了然了吧,这两个方法可以对应robotframework里的suite setup 和 suite teardown。
先看一个例子吧。
class DummyResource(object):
def __init__(self, tag):
self.tag = tag
print 'Resource [%s]' % tag
def __enter__(self):
print '[Enter %s]: Allocate resource.' % self.tag
return self
def __exit__(self, exc_type, exc_value, exc_tb):
print '[Exit %s]: Free resource.' % self.tag
if exc_tb is None:
print '[Exit %s]: Exited without exception.' % self.tag
else:
print '[Exit %s]: Exited with exception raised.' % self.tag
return False
这段代码我是从最顶上那个帖子里抄的。可以做一些说明。
- 这是一个叫DummyResource的类,提供了__enter__() 和 __exit__()两个方法,说明这个类是可以用with语句来调用的。另外从类名我们可以感觉到,with语句的运用都是和资源相关的。什么是资源?文件,网络套接字,线程thread,等等这些都是资源。
- __enter__()方法里,除了一句打印“山顶的朋友,我在这里”,就是一句返回语句:
class DummyResource(object):
# ...
def __enter__(self):
print '[Enter %s]: Allocate resource.' % self.tag
return self
# ...
返回了一个self!这是什么意思?就是把这个类的实例返回出去。这样
with context_expression [as target(s)]:
with-body
中的as target(s)就可以得到这个值了。忘了说,target(s)之所以有或许复数,是因为__enter__()方法是可以返回多个值成为一个元组的。
- __exit__() 是个更复杂的方法,用来定义退出时候的动作。在方法的定义中可以看到有额外的参数exc_type、exc_value 和 exc_tb。这三个都是和异常相关的。如果with语句包住的用户代码正常执行,那么这三个变量都是None;反之,如果出错了,可以简单通过exc_type来判断异常的类型,配合后面两个变量获得更多的异常信息,进一步做相应的处理。
- __exit__()方法中更重要的是它的返回值。return False。False的意思是“我还没有处理完,我要把这个异常继续抛出去,你们外面的代码去抓住它继续处理吧”。如果心满意足的,或者心怀鬼胎的觉得已经处理完了,就返回个真值,外面的代码就不会知道有异常发生过。很多问题的根本原因就这么湮没了。:-(
结合这个类定义,看看实用的调用例子吧。
小乖乖:
with DummyResource('Normal'):
print '[with-body] Run without exceptions.'
和不乖的:
with DummyResource('With-Exception'):
print '[with-body] Run with exception.'
raise Exception
print '[with-body] Run with exception. Failed to finish statement-body!'
小乖乖的输出是这样的:
Resource [Normal]
[Enter Normal]: Allocate resource.
[with-body] Run without exceptions.
[Exit Normal]: Free resource.
[Exit Normal]: Exited without exception.
很好,按部就班,只要读得懂类代码就很容易看出这些输出。下面看一下“小淘气”的输出呢。
Resource [With-Exception]
[Enter With-Exception]: Allocate resource.
[with-body] Run with exception.
[Exit With-Exception]: Free resource.
[Exit With-Exception]: Exited with exception raised.
Traceback (most recent call last):
File "G:/demo", line 20, in <module>
raise Exception
Exception
除了读代码能看清的输出,还要说一两句。
- 用户代码中是先抛出了异常后又打印了一句“[with-body] Run with exception. Failed to finish statement-body!”。在输出中这句没有打印。这说明了__exit__()方法是清道夫,你们用户代码怎么乱糟糟,你先跑,抛出异常了,就别接着往下走了,我留下来打扫战场。
- 输出中的“Traceback (most recent call last):”一段是解释器抛出的异常,在__exit__()方法中的开关就是最后的那个返回否值。如果是返回真值,这段Traceback是不会输出的。
最后,说说最初的那个花姐举出来的例子。
with open(r'demo.txt') as f:
for line in f:
print line
# ...more code
打开一个Python的IDE(我用的是Pycharm CE),可以点到open的定义,就是一句话。
def open(name, mode=None, buffering=None): # real signature unknown; restored from __doc__
"""
open(name[, mode[, buffering]]) -> file object
Open a file using the file() type, returns a file object. This is the
preferred way to open a file. See file.__doc__ for further information.
"""
return file('/dev/null')
仅仅返回一个file实例。继续点过去,就豁然开朗了。
class file(object):
# ... some codes
def __enter__(self): # real signature unknown; restored from __doc__
""" __enter__() -> self. """
return self
def __exit__(self, *excinfo): # real signature unknown; restored from __doc__
""" __exit__(*excinfo) -> None. Closes the file. """
pass
# ... more codes
file 这个类 实现了__enter__()和__exit__()方法,那外面当然可以用with语句来建立文件操作的上下文。
其实实现上下文管理协议并不是每次都需要写一个类实现两个办法,还有其他的方法,会另开一篇写写。
-EOF-
2017年展望
别过的像2016年就行了。
狗屎皮聚会
简单记一笔。8月20日,苏州。
因为先要去酒店入住,稍晚到会场。后来才发现第一场Scala的分享已经完全错过了。
TR在讲Symfony。由于技术细节听不太懂,只能关注一些方法,比如:
- 跟数据相关的操作往后拖,所有的api都返回json格式的结果,前面的操作可以有更灵活的选择。
- 路由用正则表达式来进行限制,超出这个范围的不做理会。
- 要构造测试样本数据,合理真实,并有确实的期望结果做参考。
TR在gitbook上发布了一本相关的电子书,大家又讨论了一下gitbook的生成等周边技能。
午饭吃湖南菜。
下午令狐从架构的角度讲了讲。我能记下的是:
- 一定要有技术手段来限制客户那些操作不能做。
- 一定要考虑到灾难,比如硬盘坏了,节点挂了,大楼炸了。不是说过度设计,但是要找到一个平衡的点。
- 代码检查,静态检查。要有,要有给对方犯错的机会。(这是不是说我们都长大了?)
- 升级自己的产品的时候要兼容以前的版本,旧用户发现不能继续使用了是不可以接受的。
接下来我给大家看了一个docker-elk的image,ELK 的一个小例子。我事先导入了一本小说,然后可以分析词频,仅此而已。昨天,公司里有个培训,一个CI工程师分享ELK使用。他就是在Jenkins上用ZMQ插件把数据都规整成一定格式,用json方式发给ELK,就有各种可以供分析的新tags。我准备在自己的Jenkins上也这么弄一弄。
最后三火演示了一些Mesos,Marathon的东西,虽然知道这是分布式的方向,但是也不是个人能玩的。
每年有这么一次交流的机会很好。期待明年。
见Cliff
三月九号晚上在星光二期的新疆菜见了一个长辈Cliff,十几年没见了,又是同行,谈得非常投机。
有几点感受。
- 专注。他一直在一个行业里工作,从来没有因为软件是万金油而转行,专注做那一块。
- 积累。他二十年了还在用MFC,大浪淘沙,现在会MFC的高手已经少而又少了,他就是一等一的高手。二十年来他写了很多能给自己用的类库,积木搭一搭就很快了。反而不用不断的跟进新技术。
- 围棋还是很开发智力的,要坚持。
PyCharm两件事
这是一篇技术相关的笔记,如果没有兴趣请绕路。
由于工种的变化,我开始用python写一个比较大的工程。那小作坊式的编辑器就不适合我,PyCharm就是我的选择。
单位的操作系统是Windows 7,家里的是Windows XP,两个系统上用的都是 PyCharm Community Edition 3.1.3, 都遇到了一些问题,分别说。
家里Windows XP上PyCharm 装好,启动。 发现内置的Terminal不能用,是灰的。
一开始我还到Twitter上去问,没有人给我回音。后来我发现可以看到PyCharm后台的log,具体的位置在“c:\Documents and Settings\username\.PyCharm30\system\log\idea.log”。打开,查找“Terminal”,能看到一些java抛出的异常信息。向上看,能看到一条:
“Unable to load library ‘D:\USERS\Haijiang\tools\PyCharm313\lib\libpty\win\x86\libwinpty.dll”
好吧,估计就是这个dll出的错啦。google上查找,找到了https://code.google.com/p/android/issues/detail?id=62572 这个帖子。帖子里说的是 android-studio 碰到这个问题,鉴于PyCharm和android-studio用同样的IDE,那就试试看。在#3答案里面提供了一个链接,github上的: https://github.com/rprichard/winpty/downloads 里面有一些编译好的包下载,我下载了winpty-0.1.1-msys.zip 这个包,替换了原来的位置的dll和exe文件,名字改成原来的样子。
重启,Terminal用起来。
在办公室(Windows 7)遇见的问题倒是简单一些。我最近偏爱Solarized Light这个配色主题。在github上我找到了一个为PyCharm做的主题,在这里:https://github.com/sevas/pycharm-color-schemes 。用起来还不错,有一个小问题,就是Terminal里的配色默认的情况下文字和背景是一样的,只有在选中的情况下才能看出来原来那里是有字的。一开始我以为Terminal也是灰的呢,后来发现能用,只是暗夜里的乌鸦,墨墨黑。
通过和其他的配色文件进行比较,我发现有两个变量控制终端的前景色和背景色,CONSOLE_BLUE_OUTPUT 和 CONSOLE_GREEN_OUTPUT。看到这里哑然失笑有没有?!github上的那个主题是没有这两个变量的,加上,给不同的值,把配色的xml文件放到 “c:\Documents and Settings\username\.PyCharm30\config\colors\” 下面去,PyCharm里面选好,重启。Terminal就用起来舒服了。
改良过的主题文件我放在我的github页面上了,这里。
停电
家里前天晚上停电了。
楼上那家在装修,倒是好心早早就在楼下写了条子,说家里要装修了会扰民,到时候请联系,电话号码电报挂号等等,我也没当回事。一天从外面回来发现家里断电了,进门,推电闸,电来了。只是冰箱上有水,地板上的电插板也湿了。自己弄干净了就没事。再后来,下水堵了,楼上在弄水管的时候把小石子扔下来,跟他们说了,也修好了。家里的基础建设就这么一轮一轮的经受考验。
前两天情况有点变化,跳闸的时候楼上的空气开关是好的,得到楼下总闸去看看保险丝。这样弄过两次,想想和楼上的装修也关系不大,是冬天来了的信号吧。只是大晚上的去弄保险丝挺烦人,需要跑上跑下。
前天晚上十一点多,已经躺在那里打游戏,突然就断线了。起来要开灯灯不亮,知道是停电了。打手电去看空开,也还好,那就是楼下的总闸跳了。算了,不要抹黑穿衣服拿工具下楼上楼装好再下楼上楼了,睡觉吧,明天是新的一天。
可是长夜是漫漫的,翻来翻去不能入睡。网络是断了的,冰箱是热了的,电视是没的看的,和外界唯一的连接线是手机上的Edge。感觉怪怪的,好像自己困住,在一个黑漆漆的异次元,想叫叫不出,伸手一探一切都是虚幻,我在天边仿佛看到一丝白光,但是又不能向那个方向前进。我只好拿出手机看扎克看饭否看大众点评看街旁。我就想着我是一盘童安格的磁带,放了A面《干燥花》该翻面到B面放《忘不了》,唉,折腾好久,到三点,入睡。
东方既白,下楼,弄保险丝,一切都欣欣然的样子。
=====================
自从Mansum离世都没有想起写点别的。今天早上在公车上看村上春树的《当我谈跑步时,我谈些什么》,突然有写写闲话的冲动。
早上很冷,我开了空调暖了好久才爬出被窝。想着周末小超母子可以过来收拾一些冬衣。到了办公室,听说过两天会升温,那就还是我一个人跑跑吧。我是靠近天蝎的天秤,纠结的天秤。
纪念李文琛先生
这是LinkedIn上的一个截图,可惜这个页面该不会再更新了,消息也送达不到收信人了,李先生已经荣归天家了。
Man Sum为他们公司的产品提供支持,为我们提供帮助。渐渐的他和我们很多人都成了好朋友,这是一个谦逊善良的兄长,一个真正的朋友。
第一次见到Man Sum是2006年底。他和John第一次来我们这里访问。我那时还对这个领域很陌生,Man Sum给了我很大的帮助。
Man Sum总是耐心的听完我的问题,然后耐心的告诉我怎么做。有的时候我都觉得我提出的问题是很蠢,提出来多么的不应该,起码应该自己找找解决方案。可是Man Sum没有嘲笑我,没有指出应该先去RTFM或者STFW,而是撸起袖子帮我一起做,同时会一点一点的告诉我这个信息到哪里去找,如何找到相应的资料。
Man Sum总是很耐心的记录下所有的需求。他会说不能马上答复你,但是他总会给你一个说法。哪怕这件事情是多么的小,小到你已经忘记。
后来我有了Juha。Man Sum建议我多给孩子拍照。他自己也是个摄影爱好者,为了家里的狗狗拍了很多好看的照片。为了这些照片还制备了RAID等硬件。他是一个热爱生活的人,为了生活拼命的工作。
Man Sum帮我带了几次香港的奶粉,后来他跟我说杭州的海关都认识他了。有一次Juha生病,需要保婴丹,正好知道Man Sum第二天要来杭州,我就冒昧的在晚上打电话给他,他二话不说就出去买,回到家还电话我说运气好,在超市关门前一刻买到最后的两盒。我和小超都很感激他,一直说要吃一餐饭。可是就永远的错过了。要是能换Man Sum回来,哪怕一天,烧掉一个Justin Bieber我也不在乎的。
很多话到了指尖就是打不出来。我想,除了我一定会有别家公司的人在写纪念Man Sum的文字吧?我也在想,是Man Sum什么样的品格使他受到这么多人的尊敬呢?技术人员的路就是该像他这样踏实的走下去的。
这两天总想到Man Sum。总想着办公室的门打开,他清瘦的身影背着黑色的电脑包闪进来,总是这么希望。
李先生一路走好。