嫩豆腐汤

年轻的时候,我在韩半岛生活过一段时间,尝了不少正宗的韩餐,后来一直念念不忘。里面绝大部分在韩国以外是吃不到的,即便吃到了味道也全然不对。但有两样除外,一是海鲜乌冬面,二是嫩豆腐汤。
在韩国,嫩豆腐汤算不上一道正菜,往往是烤肉吃到差不多,人喝得醉醺醺的时候,上来两小钵,座上几个还清醒着的遂分而食尽。一众人里,我总是那个等着喝汤的,将其当成一餐里最不能错过的美味。

幸运的是,在美国,只要韩餐店是韩国移民开的,嫩豆腐汤不可或缺,以至不少韩国餐馆直接挂牌匾作“豆腐坊”。更幸运的是,嫩豆腐汤在家也可以轻松制作,海鲜、牛肉、海带、青瓜、香菇……这些食材随处可见。唯一的要求是得有个韩国石锅,要选对豆腐,以及韩国辣酱。

如果不去公司,嫩豆腐汤就成了午餐的首选。步骤简单,口味稳定,分量对于两个人来说,更是恰到好处。
今夏天冷,一碗热汤正好能驱赶寒意。

黄石

前些日子,我飞到Jackson Hole,在机场租了车,一路往北,去大提顿和黄石逗留了几天。游玩结束后不想走回头路,于是继续向北,开到了蒙大拿的小镇Bozeman,那儿有另一座机场,可以异地还车。
因为在城里吃午饭耽搁了些时间,有点担心赶不上航班。所幸还车手续异常简单,堪称一条龙服务——沿着机场入口的指示牌,可以直接开到租车公司的专用停车场,在航站楼顶层,电梯下去就是候机大厅。当日还车的人并不多,却有两位笑容可掬的接待员候着。她们核对了名字和车号,热情地叮嘱我不要忘掉行李,然后礼貌地问询黄石之旅感受如何。

”真是不错!“我回以同样的礼貌。这时,我注意到其中一位姑娘眼中发光。
”这么近,我可还没去过一次呢!“她说。
”你一定要去一次!“我鼓励说。
”你说得对,等到国庆日有了假,这就找几个朋友一同去!“

那一刻,她的笑容让我想起一弯浅月。

去山景城

山景城的计算机历史博物馆我慕名已久,还在中国的时候就将其列为此生非得去一次的地方。可不知什么原因,一直等到在旧金山湾住足十年,我才终于想起带了两个已经老大的孩子前去参观。我不得不说,那地方太容易把人的怀旧之情撩起来,看着巨大的ASCii表格,带滑轮的鼠标,灰扑扑的苹果电脑……往事便如烟如云地翻滚而来。

给你们讲个恐怖故事吧,我说。

爸爸小的时候——也不小了,刚上高中——学校开了计算机课。爸爸就特兴奋,记得第一次进电教室,脱掉鞋子,套上脚套,感觉跟朝圣一样——什么叫朝圣?哦,就是那种很想但又很怕怕的感觉,你们长大就知道了——按钮按下去,屏幕刷地就亮出一道绿光,吓得爸爸触电了一样,再不敢碰那机器——对了,机器上画着一个彩色的苹果,我印象深刻,就是它的名字,跟现在不一样,那时候人们都觉得奇怪,为什么把那玩意儿叫做Apple。对了,爸爸的第一个Basic程序就是在那台电脑上写的——哦,今天讲的不是这些,是有那么一天,Apple电脑黑屏了,怎么摁也亮不起来。老师也没发现。下课后,有两个同学风风火火地跑过来告诉爸爸,老师知道你把电脑弄坏了,要赔!很贵很贵的!二十!那是的二十块钱有多少呢?这么说吧,差不多就是你爷爷好几天的工资!吓死人了!回家也不敢跟你爷爷说,吃饭吃不下,睡觉也睡不着……

“怎么才让你赔二十?刚才我明明看到Apple II卖500块呢!”

好问题!那是因为我们穷啊!谁敢想那么大的数目——听我继续,爸爸茶不思饭不香大概有一个礼拜,那两个同学大概是觉得不好意思了,跑过来承认,说原来是他们合伙骗爸爸的,老师早就把电脑修好了,根本不用赔,那纯粹就是一个prank!

“是万圣节吗?”

“记不得了,好像是吧——有日记记着,回家查查。”

博物馆出来已过正午,大家饥肠辘辘。因为极度厌恶疫情后泛滥了的消费文化,我有好久不愿意在外就餐了,就跟娃们说回家煮饺子吃,结果大家一脸沮丧。我不得不打开谷歌地图,忽然发现谷歌就在附近,立刻有了主意。

在谷歌游客中心,我们要了一份酸菜培根三明治和一个蛋糊牛角包,另加一根酸黄瓜。老实说味道还不错,一共二十,没有小费。

蜜香红茶

今天去台湾小店买豆瓣酱的时候发现有好些茶卖,忍不住拿了两罐。包装上写的是“蜜香红茶”,也没细看,只是觉得管它蜜香还是花香,大概率是品不出来。

我喝茶有二十多年了。巅峰时期只买锡兰的努瓦拉埃利娅,那时候是真能尝出其中香槟特有的清冽和甜香来。只是后来口味越来越重,就只有英式早餐茶还对口,差不多要到依赖印度茶渣的地步。至于台湾红茶,倒是从来没有尝过。

拆封后发现是大叶,特意多泡了几分钟,出来的颜色仍旧清澈。洗了洗舌头,抿了一口。味道有点熟悉,可能是武夷山大红袍的感觉,发过酵的版本。再看说明,才知道这叶子是专门拣幼蝉吃过的残叶,所谓蜜香乃来自那虫子留下的粘液。

原来如此。

在路上

劳动节假期三日,驾车至内华达山脉西侧做短暂旅行,穿越了南部的巨杉和国王峡谷以及北部的优胜美地两个国家公园。路途漫长,景点零散,三日以来下车游逛时间加起来顶多四个小时,大部分时间尽在路上,而我觉得透过车窗看到的许多风景其实更佳。旅途匆忙,无暇写生,唯能拍照记之,等回家后再画,希望趁着记忆尚新鲜,还能把当时所感受到的气氛烘托出来。

一、漫山黄遍的加利福尼亚旷野中,几棵孤零零的老橡树在风中摇曳。

我好几年前就画过一棵橡树,还是因为张同学的某一首诗,搞笑的是那时候竟然不知道加利福尼亚的旷野中到处都是橡树。
这几棵橡树长在圣路易斯水库附近的山坡上,几个月前去优胜美地的途中就看到过,但那时候是春天,四处绿意盎然,橡树长得灰不溜秋,极不显眼。而到了旱季,野草尽数枯掉,橡树就成了群山中唯一的绿色点缀。
那日天气一反常态,空中阴云密布,还滴了几滴雨,在这个时节的加州极为罕见,从而烘托出来的苍凉的气氛压满群山,再看那老橡树枯枝落地,新叶萌发,处处显出挣扎中之生命的顽强,几欲让人落泪。

California's Oaks
San Luis水库附近的几棵橡树。

二、180号公路的黄昏

180号是从国王峡谷返回到Fresno的公路,下山之后黄昏降临,空旷的中央谷地忽然闪现出一座小山,夕阳投射之下从墨绿化作金黄,宛如幻术。

三、世界边缘

沿120号公路驶出优胜美地不多久,有一处观景台可以俯瞰Stanislaus的原始森林和峡谷,由于往年的山火,森林已经毁损殆尽,却令峡谷的景色更为壮观。

Stanislaus National Forest Vista: Rim of the world

四、中央谷地

从旧金山湾区到内华达山脉,必须穿越中央谷地,其间横亘多条州道,分别可以去太浩湖、莫诺湖、优胜美地、国王峡谷……。中央谷地之空旷是我以前没有想象过的,果园和牧场往往蔓延千里,一望无垠。记得那日沿120号公路一路向西,时至下午,加州炽烈的阳光赋予周边景物至纯的颜色,干净地令人窒息。

CA 120

日本印象

大学的时候我选日语作为第二外语,花了一个学期学完了两册《标准日本语》,后来一直想着能去日本旅游一次,但计划来计划去都是半途而废,其中最主要的原因就是日本消费太高,预算做不下来。等到再后来疲于生计,这个想法也就束之高阁起来。没想到这次筹划回国,发现转机东京机票价格最为便宜,那何不在日本小驻几日?既可以倒时差、减缓长程旅途的疲惫,也顺便了却旅行日本的心愿。

我是在深夜抵达东京的,次日包车到河口湖,看了一看富士山附近的几个景点,第三日逛了逛东京市内最出名的几个景点,第四日便匆匆离开了。所到之处皆走马观花,仅得一些粗浅的印象。

先说说东京。
楼高,路窄,处处便利店;公寓密集但看不到小区;行人超多却没有热闹的感觉。神社随处可见,其散发出的宗教气氛远超佛教的寺庙。几个网红景点——浅草寺、东京塔的商业气息非常浓重,然而不会让人不适。寺庙的架子与国内差不了多少,但颜色鲜艳很多,有些卡通化。景点的日语广播都是轻柔的女声,腔调也很卡通,和街上听到的日常日语截然不同。
最让我意外的是一点也没有体会到东京消费的高昂,五十美金可以在便利店采购三天。起初我以为是因为总和美国湾区对比的缘故,后来回南京体会了一下,仍旧觉得相同品质下东京消费更加友好。说国内消费低,其实是因为大量低质产品和服务的存在。

东京塔
明治神宫
明治神宫深处的草坪

关于自然景观——主要是富士山周边,我并未发现特别可道之处。可能季节也不对,没有樱也没有枫,富士山也没有雪顶,还被云遮盖着。特别是刚刚去过被称为北美富士山的Moutain Shasta,白雪皑皑极其壮观。相比之下真正的富士山反而逊色很多。然而,日本人造景的能力还是令人印象深刻,河口湖一圈,包括大石公园、忍野八海等,均属于围绕富士山开发的人造景观,里面的薰衣草田、玫瑰园、步道都很有特色。只是常在北美游逛的人,必然会觉得不够粗犷。

从大石公园远眺富士山
从大石公园远眺富士山
山中湖的真假天鹅

两天里打了很多卡,也顺便调整了时差,此行还是很值。去机场送机的是个日本司机,顺便还练习了一下早已生疏的日语,圆了个心愿。

冒险游戏

最近两个周末在家里和孩子们玩一个瞎编的冒险游戏,兄弟俩都不亦乐乎。

起初规矩很简单,楼上铺地毯的地方都是大海,楼下铺地板的地方则是陆地,游戏从弟弟的小床开始,他们一个人得一个收纳箱做小船,可以乘着去海里探险,捡到任何宝贝都可以找我换钱,比如一架飞机二十块钱,一辆汽车十块钱。很快,小屋里的玩意儿就给哥俩搜刮赶紧了,他们就得去其它房间,那样我就要求他们出去一次吃一顿饭,一块钱;接着他们又想下楼,我就说下楼要有飞机,在楼下走要有汽车,每加一次油又是一块钱。兄弟俩后悔不迭,用攒的钱来跟我买汽车,一个三十,买飞机,一个五十。哥哥又想着去客厅,我说那里是沙漠,要有越野车,一个五十,五块钱加一次油,哥哥想了想,还是掏出了五十块钱,然后就破产了。

大家都觉得这样子玩没多大意思,于是我就为大家设立了游戏的任务——去找到一个橙色的乒乓球。
哥哥立刻行动起来:捡东西、换钱、买飞机、买汽车,终于发现乒乓球在厨房吧台的水果篮里。
“吧台那么高是不许直接拿的,除非——”
“除非什么?”
“除非你有蜘蛛人帮忙!”
“可是蜘蛛人刚才十块钱卖给你了?”
“要买回来吗?”
“要”
“一百。”
哥哥又破产了。

一个软件架构师的实践回顾(续)

花了两个周末,把原先仅支持Windows和Linux的嵌入式应用平台成功地跑在了一块Cortex-M4开发板上,这距开始着手设计这个架构刚好三年。每每与同行聊起此事,他们要问的第一个问题必然是:“怎么不用安卓?” 答曰:“养不起那么大的Team。”
安卓大概也就是给创业公司拿去做做DEMO找找投资,或者给山寨公司套套壳比较合适,不然,一不小心就会把几十号人陷进去,尤其是在你需要的功能集远远小于它所提供的功能集的情形下。今天更是倍感庆幸,如果当初选择安卓,要转到M4上只能完全推倒重来。
总之,同定制安卓比,打造一个精简的嵌入式应用平台没有想象的那么复杂。

设计初期,语言的选择是C++,平台是Windows。C++远不是最佳的编程语言,但却是妥协性最好的编程语言,如何使用它完全取决于架构师,而非语言标准及其支持库本身;至于选择Windows,则是因为芯片选型尚未完成,而刚好手里面有一套基于Windows的操作系统抽象库。那么,第一个任务就是构建一个好用的操作系统抽象层——这里面的重点不是抽象,而是好用。因此,光有线程封装是不够的,还得有一个更高级的事件抽象模型,于是借鉴了不少Java的东西,主要是JMS和并发包里的线程池(我从来不耻于承认Java是自己最喜欢的语言),当然需要做许多精简,使其更适合嵌入式终端的需求。等到这个库差不多稳定下来的时候,硬件设计也刚好出炉,这时再把线程封装换成Posix,就可以直接拿到开发板上跑了。

分层和模块化是我踏入这个行业所学到的第一课,还记得多年前浩哥拿着飞利浦的PPT给大家讲,那时听得稀里糊涂,现在这些思想却几乎已经成了一种思维本能。简单地说,分层有利于降低软件的物理依赖性,不仅适合一个产品系列的并行开发,也可以在很大程度上降低频繁的产品需求变更对软件开发的冲击。比如,他们问:“LED给用户的感觉太生硬了,听说最新的驱动支持可以调节的亮度渐变,给你两周的时间能加上去吗?”
这时你可以和他们要过最新的UX Spec,然后内心镇定却故作忐忑状地答道:“两周可能比较紧张——尽力吧!”

其次是设备管理,这点做得有些过。:
我崇拜Linus,但同时又是宏内核的反对者,一直倾向于将设备操作从内核搬到用户层,动机嘛,其实不复杂,就是希望降低对芯片商的技术依赖。当年在S社的时候,内核驱动的bug都会在芯片商那边拖上十天半月,至于小客户,那只好听天由命。
后来发现设备管理器显然是被过度设计了,大家都略有怨言,刚好来了个小印,做内核的,捣鼓了个ko,又把用户层的操作全给搬了回去。挖剩下的那些,也就只能给缺板子的同学们在Ubuntu上调着玩。

然后是控制和状态推送模块,简而言之就是MVC加一个protocol buffer,这个模块可以让一个通过蓝牙或无线或任意其它什么方式连接到设备上的远程应用便捷而实时地对设备进行操作和监控。这也是仅有的一个使用了大量脚本自动生成的代码的模块,其时曾逆想某天人工智能学会编码的时候这碗饭自己还吃成吃不成。

最后聊聊有限状态机。
概念是同事提出来的,但因为当时我们已经有一个可以做演示的原型,我并不是十分热心,总是觉得必要性不大。但幸亏被成功说服,不然后期频繁的UX需求变更怎么都能把你的架构戳成危楼一座。也正是因为有状态机的支持,许多找不到根本原因的许多问题也都放到了应用层做workround,不就是加一个迁移或者顶多一个状态吗,几个表格的变动。
一个设计良好的状态机可以消灭大部分if/else和switch/case,毕竟,人类的大脑在读图表的时候犯错的概率还是低好多——何况改图表不是那么容易引入看不到的副作用。

开发初期同学们还是有些抵触情绪,抱怨最多的是过度设计,因此加班加点地做过还几次重构,最终我自己认为还是达到了务实的标准。还是那句老话:软件不是设计出来的,是演进出来的,凭空设计的软件、没有进化能力的软件,都是死的软件。另一个担心是觉得这个平台还是有点重,如果真的有一天要拿到256K ROM,128K RAM的微控制器上怕跑不起来,这也是早期大家反对使用C++的原因之一,我当时的应对方案是限制标准模板库的使用,至少不能让它们出现在函数的参数表中。基础模块的开发还是维系了这一原则,但到应用就有点乱,string、map漫天飞——赶进度嘛!好在最上层应用的重用也没有太大意义,该重用的也都重用了,这也进一步佐证了软件分层的意义。

此番回顾算是给三年前另一篇文章一个交代,实际上,以上每一个话题都值得花些时间深入探讨。