回望来时的路:构建之法 东北师大站 2016春季学期

1. 前因

微软邹欣老师著有《构建之法:现代软件工程》[https://book.douban.com/subject/26577755/]。第一版首版以前,我还不知道邹老师是哪一位,就在网上曾经看到过有人转引他的观点,感到说得太有道理了,一拍大腿的感觉。比如他提到教师和学生之间应该是健身教练和学员间的关系,不是教师带领学生参观浏览,也不是狱警和囚徒的关系。比如他批评没有代码量的软件工程教学。《构建之法》到手,第一遍粗读我花了一周的时间,酣畅淋漓。很多处让你再拍大腿,“对啊,这正是问题的症结,他的招儿没准好使呐。”在那以后向我的好几位学生极力推荐阅读。似乎亮哥看了,别的同学也没有怎么重视,虽然我极少推荐读哪本书,怕推荐多就不值钱了。

book

邹欣老师本人是微软首席研发经理,北大、清华、北航等采用过《构建之法》作为教材。一方面权威,另一方面也令我等小校望而胆怯。有次在周筠编辑的群中得知,他有意图促进《构建之法》和“learning by doing”的软件工程教学理念在不那么特别好的学校里推广,顿时心向往之。我想起不少小说里描写到的文革时期随便那么几个主人公小青年,就能懂副歌,能关起门来讨论伏尔泰和卢梭。时代之进步,让我们有机会偏居一隅而能与世界对话,应该充分享受比那时更幸运的条件。但是那个学期我排课程失败了。邹欣老师后来招募远程助教参与别的学校的教学,我也非常也申请,但是估计自己的时间和精力不足以做出工作量的承诺,只好放弃,非常可惜了很久。

本学期有机会开设课程《软件项目管理》,赶紧求同学们选我选我选我,达到限额,终于开课。

2. 课程的一些数据

2016年3月4日13:30:00计算机楼320教室,夏一鸣同学[http://www.cnblogs.com/xiaym896/]在他最后一篇技术博客里清楚地回忆起时间地点。事实上,他回忆错了,第一堂课因为排课冲突,临时改到了二楼的微格教室,以后的课程都是在320教室,不过时间没有错。

3月4日起,课程教学持续12周。

选课时间注册XX位同学。这个数量并不重要,仅为超过开课人数限制。这里有些同学根本不打算要成绩和学分,只是助我开课。感谢。

实际参加21位同学,坚持到结束17人。放弃的同学,有的是在第一次课程以后就发邮件通知我了,只要成绩,不想参加项目实践;也有同学尝试了开设博客这一步,然后放弃;也有同学比这还努力稍多一些,发了一两篇博客。鸡汤名言说: 所以的失败都有一个共同点,就是坚持的不够久。也许我们所能直接看到的利益太少,也许我们能够做出的选择太多,也许如刘伟硕同学说,缺乏强制措施。还有同学在学期末的感言中提到,如果能够再有一次机会,如果可以重开此课,诸如此类。说实话,今生放手的人,我不怎么相信来生会更珍惜。

这17位坚持到底的同学中,有三位旁听生。他们没有注册,也不会有学分,但是成绩优秀。其中一位是我以前的学生,她现在本人也是教师,同时作为邹欣老师本学期某校的远程助教,名郑蕊;一位是现在的研究生,但是他没有选课,名亮哥;一位是本科三年级同学,名冉华,他曾经一度参与亮哥的项目。郑蕊和亮哥的成绩属最优秀的之列,冉华同学独立完成了一个持续10天计累计46.05小时的小项目《H3C汇聚层交换机认证在线人数展示系统》。这告诉我们人的主观意愿和追随内心的力量。

全体同学发布技术博客共254篇,人均超过每周1篇。教师发布21篇,每周约2篇,其中一篇是这一周作业重点提示及更新点评,另一篇是这一周作业的成绩。

在第3周开始,全体同学结成4个团队,每组约4位同学。其中3个团队站到最后,1个团队在alpha发布后开始解体。解体的团队,有1位同学加入其他团队,另2位同学保持游离态。

以团队为单位发布项目,学期末发布共5个共3种。3种项目是 抢答器、记账本、四则运算在线,分别源于耐撕团队、OneZero团队、爆打团队。在学期中真beta版发布后由每个团队选择fork其他团队的一个项目,并在两周内增加功能,与源出的团队竞争开发,即要求每个团队最终发布2个项目。学期末,抢答器、记账本有2个团队分别发布branch,四则运算在线1个branch,共计5个。这样做教学上的原因是东北师大北前没有积累可供训练 维护 阶段的代码,以fork其他团队来部分贯彻邹欣老师提到的:写一万行代码,在别人的十万行代码中愉快的运行。

所有的技术博客和代码可以通过教师博客[http://www.cnblogs.com/younggift/]找到。

在第2周课程的时候郑蕊同学建立了 东师软件工程 微信群。不过与《构建之法》其他高校的群不同的,东北师大的群里基本没有人说话,教师临时修改增加作业或点评,也不太有响应。我本人不喜欢在“群”里被集体通知或告之,然后自己选择是否与自己有关。这种被组织的感觉不好。我担心同学们是这样感受的,进而进入 狱警囚徒模式,所以对群里一片安静听之任之。东北师大的群最后大家选择了实名(而且人数这么少很容易人肉出来吧),据说有的高校的群是匿名的,有同学发表了对教师和/或助教的不满。这也是个大家不吱声的原因吧。还有,可能由于就业太容易,似乎无论什么对就业都没有什么正面或负面影响,东北师大的同学似乎历来高冷……我习惯了。

3. 历程

第1周和第2周,基础知识及鸡汤。知识不是重要的部分,更不用说对于研究生阶段的同学。往往是,我们知道,但是不做。更重要的,猛灌鸡汤。同学们通常并无强烈的动机想进修软件工程。他们的热情一般止于热烈的表达愿望,或者言不由衷地对科目重要性的认识,有时还有对教师的表扬。但是,也仅止于此。第一轮工作量就会把他们貌似熊熊燃烧的小火苗烧熄,然后他们会说,“其实也那么重要,其实也没那么渴望”,用那么二字这一程度副词否定自己的“初心”当真是好借口。鸡汤是药,不能停。在真beta发布前后,教师说,以后不会再有鸡汤了。那个时候,同学们疲于应对从没见过那么多的工作量。同时,教师对同学们不能甚至消极地响应很失望,邹欣老师和周筠编辑的鸡汤也不足以补足元气,对每周的截止时间周三晚24点守岁般度过然后你没有提交作业很失望。我觉得,你们并不像你们所声称的那样希望我们共同所做的事,而你们没有想到我会坚守承诺,并且对你没有坚守承诺愤慨和绝望。我就是在这个时候放弃的,当你用行动宣布放弃的时候。好多年前我用更激烈的措辞给学生们写过一封信,大意是,我们不是因为情感走到一起,而是因为共同的目的,你不坚持,就是背叛,我绝不挽留。我现在会微笑着对全班同学说,“我爱你们,同学们,发自内心,而且你们真的与以往每届都如此不同”。不过,我没有什么不同。

从第3周开始,分团队,团队项目立项介绍。两周SCRUM,要求每天站立会议及会议报告作为技术博客,每个团队共10篇。不过这只是要求和愿望。不少同学们在这时还没有意识到我在第一堂课的鸡汤,“刚工作的同学往往以为有60分这一档,其实那是不存在的,工作上只有0分或及格。”只要你有一点不符合要求,就触碰了底线,0分。超过截止日期,要求的项目有没有完成的,指标达不到要求的,要求结对没做的,要求互评不评的,都是0分差评。在工作中,我们就是这样一步步失去信任的,如果偶有错误,时机不定;也是这样一步步赢得信任的,如果你每一次都符合要求。有同学问我,在工作中如果做得不好,是不是就会挨批啊。不会的,成熟的上级从来不批评你,只会减少你的工作量,越来越少,直到转岗开除。而干的好的,会不停地挨批要求改正要求更好,然后升职,去承担更重要更可怕的工作。

两周SCRUM后,alpha发布发期进行。此前亮哥创造性地给了一个发布剧透,介绍发布时将会发布的事情,简述功能。此后,剧透成要标准要求。alpha发布后,每组有1位同学离开原组,加入新的团队。alpha要求有真实用户评论,4组团队只有2个用户评论,并不详细和认真。达不到要求,和教师不敢于认真要求,都是一步步的,如同腐烂,是缓慢开始的。有一整天不呼吸,以后就不能呼吸了,有一年不联系老友,他就不再是老友了,有一次不遵循规则超过要求,以后就不再是完美实现了—不少人就此放弃,虽然不完美也比一次次放弃要强。

东北师大的SCRIM及alpha早于《构建之法》16周的教学计划,是因为考虑到课时少,可能会早于16周结束,另外假设学生有更好的软件工程课程基础,因此理论教学减量。

alpha发布如同《构建之法》其他高校及邹欣老师的预料(通常总是如此),同学们高估自己可能输出的工作量,有太大的雄心壮志,然而无能实现。所以alpha发布后,同学们都趋向现实和保守,每周只肯实现一两个工作量不大的功能,我甚至怀疑大家开始降低投入时间了。

4周已过的时候,颁发领跑衫两件,奖给当时成绩最突出的两位同学。分别是郑蕊和刘伟硕[http://www.cnblogs.com/younggift/p/5352171.html]。zhengrui

liuweishuo又两周SCRUM,每天站立会议及报告,然后beta发布。在这两周中也包括对alpha发布的review。考虑到研究生同学有更自由的时间可供支配,此处比《构建之法》减少一周专门的alpha回顾。这两周SCRUM之后原计划是beta发布,但是各团队并未做到beta的应有之意“公测”,没有真正用户,并且功能也并不大的进展。

教师称此次发布伪beta发布(因为没有真用户),要求再两周SCRUM,增加功能找真用户,然后真beta发布。这期间教师按学校要求出差1.5周,在网上看了作业,但是由于视力原因不能点评,真beta发布由亮哥主持。在此期间郑蕊提到有一周的工作状态是“失控”,其他同学虽然没有提到,教师以为这是普遍的现象。同学们开始痛恨或者无视课程要求,工作量压得喘不过气,并且维护既有代码并增加功能带来更大的压力。虽然各位在学期末的回顾中很享受的样子,我深以为有多半是军训般的斯德哥尔摩效应。我们不应该喜欢训练带来的痛苦,我们只是喜欢训练带来的结果。之所以如此痛苦,是因为以前的积累太差了—像网上的段子说的,期末的突击学习的难度,取决于你是复习还是预习。在这样一门课程中,又要积累编程经验,又要学习工程理论,又要实践。恩,既然贵族需要三代能积累出来,那么我们还是继续做奴仆好了。

第12周期末final发布。要求所有需要成绩的同学参加,本学期唯一不接受请假的一天。有同学电话我了,确实有非常之理由需要缺习,我表达了我的理解,也请他理解我不能接受请假的理由。

在final发布时,又颁发4件领跑黄衫,分别奖给
特别能作战 齐嘉亮[http://www.cnblogs.com/dendroaspis-polylepis/p/5534847.html]、
敬业福 夏一鸣[http://www.cnblogs.com/xiaym896/p/5536226.html]、
可以托付靠谱 濮成林[http://www.cnblogs.com/charliePU/p/5537734.html]、
力挽狂澜 高鑫[http://www.cnblogs.com/gaolzzxin/p/5515451.html]。

qijialiang

xiayiming

puchenglin

gaoxin成绩核算,需要按学校的要求,作业和期末论文都要交纸质品。具体的我要求为技术博客打印,期末论文打印,代码我折衷了一下,给出代码片断及下载地址。

最后,进入邹欣老师所说的“诸葛亮会议”时间,会团队review,教师也review。在此期间以前的毕业生正在上海工作的李暘发来对耐撕团队代码的review,使本已沉寂的耐撕团队队员内心又起波澜。课程有结束之日,求索没有停止之时;常回望来时路,才能进步。

meeting

4. 外援

邹欣老师拿出自己的稿费征募远程助教,为各高校提供帮助。这样一门实践不瘸腿,代码量和写作工作量很大的课程,需要助教给学生及时和充分的反馈才能得以进行,而高校机制决定难以实施。邹欣老师自掏腰包,以及课程本身的吸引力,颇有一些实践经验丰富的工程师承担了助教工作。助教无疑也付出了非常多的时间,要知道,几乎每一行代码、每一行文字,助教都是审核过的。只是,也许能力,也许精力,更重要的是时机,助教没有指出学生每一个细节的失误。我本学期没有申请助教协助,因为知道成绩核算方法和教学水平都不一定能保证满足邹欣老师的设计意图,所以由我一个人兼作教师和助教。从我的学生仅17人计,仍然感觉工作量非常大。我最初每次回复和点评技术博客,需要1至2小时。后来只好拆分成几段,挑空闲时间而且有PC机的时候处理。很多个小时,一般是一整个下午,多半个晚上。牛宝乐老师和郑蕊老师分别做过助教,他们也都提到工作量巨大。我知道承担助教工作的还有幻飞龙博士。虽然我没有申请助教,但是也从助教群中收获不少,包括不限于 工具、方法、学生的现状。谢谢各位助教。

邹欣老师和周筠编辑提供的领跑黄衫,着实让同学们兴奋了一把。来自“官方”的看得见的肯定,仍然是同学们追求的重要目标和强大动力。

很多学生的技术博客,邹欣老师也给也点评或者建议。他的点评和建议从来不是泛泛的,而是切中肯綮。一方面,我感慨邹欣老师同时点评这么多高校和学生,作为教师我也能学到不少,心存感激。另一方面,我和郑蕊私下交流过,我们点评一篇需要半小时以上,而邹老师只需要八九分钟,质量却是比我们更高。所谓高手和菜鸟的差别,他们少犯错,他们效率更高。能让我们亲眼看到高山仰止,也是幸运。

除了邹欣老师以外,还有几位专家也参与了点评。他们是maverick@柳园 (余晟), 李暘,无效的昵称(来自阿里的曾同学)。几位共同指出一个特别重要的问题,代码规范和文档规范。这不仅是学生的问题,也是教师的问题。如果有下一次课程,我会注意改进。谢谢。maverick@柳园就规范问题还给出过具体的建议,文档模板。这一点我心尚存疑,对于学生的主动性培养和适当引导,我仍然在犹豫之间,此时就以邹欣老师提供的教辅助材料为准。谢谢各位。

为了能得到来自校外的专家的点评,我在助教和构建之法微信群中,每一周都发布广告,恳请指导和鼓励。后来我不敢再继续发布消息了,因为同学们做得实在令我汗颜。如同我在课堂上说的,所有的一切都是公开的,代码袒露在所有人的面前,东北师大和你个人的能力如何,是不是会被别人藐视,无论你多么爱国和爱校,事实也就是这样。尊重不是靠恳求和隐瞒得到的,而是靠实力。

在教学中,我还得到了牛宝乐老师的帮助,他向我推荐和提供了幻飞龙博士开发的工具,把EXCEL格式的文件转换成Markdown格式。我用这一工具处理每周发布的成绩,以及成绩计算的依据。非常有效,节省了不少时间。谢谢二位。

两位旁听生,郑蕊和齐嘉亮,成为整个班级和团队的中坚力量,在带动别的同学上面起到了极大的作用,让我放心不少。谢谢。

5. 教学内容

工程。从第2次课程开始,教师持续地强调 这是工程课程,不是编程课程。编程的经验对于 项目的结果 起到了非常关键的作用,这一点从亮哥在耐撕团队的作用、刘伟硕换组以后立即突破OneZero团队的关键技术问题(数据库连接和操作)、高鑫加盟暴打团队以后团队起死回生 可以旁证。但是超越编程经验的工程思想,才是本课程教学的重点。不少同学在学期中或学期末的时候表达了理解 工程控制 的重要性,不过教师并不确认这种表达到底多少真诚,有多少可实施的愿望。

为了强化工程的体会(以及降低技术风险),教师强制要求,不得采用需要探索的技术,只能使用现在已经熟练掌握的技术。直接要求而不讨论,禁止了在统计文本的词频中使用 Hadoop、禁止了使用某种框架。教师也有过担心,万一同学们只会做console程序,连GUI和web前端都做不出,那么产品的效果得多么惨不忍睹。邹欣老师教导我(大意如此)说,那就是愿望和能力间的差距太大,还是能出来啥就做啥 — 做出不来的,光想也是没用,发布才是硬道理。

还是为了强化工程的体会,教师特别若干次强调 边界,并在需求分析、功能列表、SCRUM中再次援引边界。边界是一个系统与外界的分隔也是连接,是允许调用的接口规范,支持的功能的集合,use case driven指定的整个工程的开始端,也是拒绝服务的依据。

估算和度量。对时间(PSP)、工作量(技术博客字数累积、代码行数累积、进度条)的度量要求,对时间的(预计)估算要求。冉华同学的项目在时间和工作量估算上受到教师的直接指导,他的进步(至少体会上)非常明显。工程思想要求所有的效果都是可观测的,所有的猜测(模型)是可验证的。计算机系的同学实验经验还远远不足,“我猜”而不验证仍然经常出现。

以上两点,是不限于软件范围的一般性工程思想,是教学中的重点。教师相信中国软件工程学科教程[https://book.douban.com/subject/1653554/]中的观点(大意),软件工程与一般工程间的区别远比我们通常认为的要小得多,应该首先注意到它是 工程,其次才是软件相关。

结对编程。一定程度上解决了某些同学编程基础薄弱的问题,但是实施不持久。实施了一段以后,同学们以 时间、地点、导师部署的工作量大 等理由开始搪塞。关于同学们对于知识的尊重和对训练的轻视,后面会再谈。由于此时团队项目开始出现团体reciew和团体一起编程的情况,教师对于结对报告没再坚持。

规范,文档排版,用词和造句,变量命名。这些在前期有提及,并且安排了作业,但是在时间驱动团队项目的压力之下,教师和学生都放弃了这对规范的要求。

版本控制。要求使用github。同学们在团队项目开始后,抱怨网络现状和响应速度,纷纷放弃使用github,不过版本控制的习惯保留了下来。

技术博客。要求发表在 cnblogs 上。有同学抱怨但是全都服从了。遵循虽然不见得最优但是并不明显愚蠢的上级要求,也是成为工程师的一课。希望同学们在此能有收获。

版权。我们提到了文字复制粘贴的侵权问题,也讨论到图片引用。从同学们发布的技术博客文字和课堂争论来看,并未就版权的界定(比如引用图片是否算以“学习”为目的,不营利是不是就可以盗版)达成一致意见。在本课程中,教师视引起争论为达到效果,不在教学中作更深入的探讨。

6. 缺憾及体会

1)知识和训练。同学们普遍而长期地忽视训练。

同学们普遍而长期地忽视训练,如果我们认可他们相对地更重视一些知识的话,虽然他们最重视的是感受(“这个老师真和蔼,全心全意地爱学生,这样的才是好老师”)和态度(“我反对我赞同,不转不是中国人”)。决定成败决定效果的,直接地不是感受和态度,而是技术。现在比较普遍地能够接受的,即使在人民战争中,人民的认可如此重要,但是在最终和敌人刺刀相见的时候,意志远不如技术重要。打架是个技术活,工程也是。头缠红带如果只发生在临期末了,改变不了战局。

在课堂中,教师也屡次提到,知识是可以传授的,告诉你你就知道,而技能是不能传授,只能通过训练习得。游泳、骑自行车、弹琴、编程,这些技能只能通过训练获得,你仅仅知道也是白扯。邹欣老师在《构建之法》中有生动的比喻,一个在健身房里参观的学员,是不会自动长出一身肌肉来的,只要你不*主动*运动,亲自克服阻力,无论教练对其他学员的教学方法有多么地好,教练多么地帅和态度友善,你的愿望有多么热切。

例如,在本学期实际的教学中,同学们对于结对编程最初表现出强烈的轻视,觉得明白道理就行了。在工程实践中,也倾向于乐于观摩,而不希望投入时间;在课堂中,倾向于听教师讲单口相声,“啊”地一拍大腿或者频频点头,而不希望做作业。在课余的项目中,我也注意到学生们普遍地具有这种估向,希望真项目、有实际用途的项目、有好的效果的项目,同时希望工作量要少,希望多学知识,而不是实践知识。针对这一点,在课堂中,教师多次提到,资本家不会因为你会什么知识而付你钱,只会因为你做了什么而付钱。

对于训练的否定态度,以前也经常有项目组的同学对我说,“老师,我还得学习呢。”也就是说在同学们的心目中,项目研发,不过是业余的爱好,并不是学习的一部分,读书考试才是真正的学习。下意识中,掌握了知识,或者把某书的电子版搞到手了,就完事大吉。其实这只是开始,甚至远未开始。知识,从写出代码第一行时,在实践中,才真正开始掌握。知乎中有人问,“编译原理和算法导论是不是屠龙技 有技而无龙可屠?”我在回答中说,“除非真正屠龙过,否则不能确定掌握了技术--做习题是不够的。因此“有技(而无龙可屠)”是个伪命题。”道理是一样的。

当然,我能够理解,同学们经常看到世界充满欺骗和吹嘘,甚至我们已经习惯。说一套做一套,理论和实践毫不相关,要求别人的道德准则和自己亲自实践的泾渭分明。不过,如果我们所做的和我们宣称所相信的如此不同,我们得是多么精神分裂啊。所以,试一试,按单一的原则生活,实践你相信的原则。拒绝你不相信的。

知识与实践(及训练)应该是统一的。

2)主动地参与世界。积极性。同学们普遍高冷。

本学期有一个抢跑项目(把 [http://www.cnblogs.com/xinz/p/3852177.html] 的量表做成APP或网上调查问卷,并发布在微信朋友圈中),有三个名额,但应者寥寥,最终只有两位同学参与,并且有一位是教师单独动员的。

这个抢跑项目初看很简单,简单到同学们不屑于抬起手指。这种傲慢在学习工作中也是普遍的,“显然啊”是不少人的口头语,颇有一种“你怎么这么笨就是不明白呢”,即使后来深入了解发现并不简单甚至“显然”自己错了的时候,也气势不减。

简单的项目不做,复杂的项目做不来。在课堂上也常这样,显而易见的问题不吱声,稍微难的问题不敢吱声。所以,沉默的大多数,寂静的春天。假装大人,掩饰自己的不足,故作淡定,不参与不表现,不评论不反对不支持。

第一次第二要求结对,很多同学不做;再三强调推动,终于做了,但是体会不乐意写或不乐意多写。要求互评效果更差,只有一两位同学参与并保持。教师提供了“他山之玉”,转引邹欣老师整理的其他高校的技术博客汇总,似乎没有几位同学看,从在课堂中对作业要求的表现可以猜测。

“主动地参与世界”是世界不放弃的前提。还是在知乎上看到的一个吐槽,某高校几位女同学在大雨天被浇到了,而路上所有独自撑着伞的男同学都静静地看着她们在雨里走。有位回答得与我们刚刚提到的主题正相关,他说,你如果有求于人,要主动提出,否则别人会以为你享受雨中的散步;没有人有闲工夫看你,所以我们根本不知道你在雨里。“主动地参与世界”,不要期待世界来求你。绝大多数同学的技术远没有达到可以隐居的程度,不过作法上已经很有大师的样子了。

3)主动地参与世界。人类语言和代码写作。

课程要求同学们每周发布技术博客,课程还要求期末交课程论文。从技术博客和现已看到的课程论文来看,篇幅都短得可怜。课程论文谈体会,还没有教师的体会一半儿长的同学,不觉得惭愧么,或者教师该为这一学期让你收获如此地少而说声抱歉?

不少同学可能会说,“没有什么好说的。”

抛掉我们课程中提到的,错误的承前省和代词使用,是网络贴子主要的错误来源,认为读者知道你所知道的信息,是一个错误的假设。如果读者已经知道你所知道的一切,那么心有灵犀的情况下,沟通就毫无必要—也许你确实认为报告、技术博客、论文,只是形式化的仪式而已。向别人解释自己的动机、技术路线,在毕业论文和项目答辩中阐述你所认为的重点难点,不仅是使得别人了解你,也是评定专家确认你了解你所说的内容的重要手段。对于从北京到走向世界的途径如果你说,“靠脚”或者“没有必要,最好的我们都已经有了”,那么别人至少了解你的方法论或者价值观,而你说“那不显然么”,除了傲慢的态度,别人对你没有任何新增的了解。

有个心理学或教育学故事告诉我们,不了解别人不是自私,而是幼稚。故事说,令孩子A观察孩子B的行为,并回答问题。有个人对被观察者孩子B展示糖果并放在抽屉里,然后在孩子B短暂离开时把糖果从抽屉里拿出来放到口袋里。问孩子A,孩子B回来以后会到哪里找糖果。有一些孩子A回答,孩子B会在口袋里找糖果。这些孩子A并不知道,孩子B不知道糖果转移这一信息。

代码、文档、报告、技术博客,都是告之另一些人,他们所不知道的信息。主动地参与世界,在代码和人类语言写作中充分预估别人可能不知道,展示自己的友善,而不是展示自己的聪明。

如果你不知道应该如何表达,或者表达哪些信息,那么 多读书,多读别人的经验之谈,多读代码,多看看别人是怎么写的。不要沉浸在自己的小世界里,你不注意别人,就不知道别人需要什么信息,期待阅读什么。多想到别人期待什么,而不是你意图展示什么。这样,能避免写作和代码词不达意。你的个性和态度,没有人乐于为此付钱。帮助别人,别人才会付钱给你;请我们欣赏你的个性和态度,你需要付钱给我们。

4)时间。快节奏,短迭代。时间驱动。对时间的估算和度量。

课程每周一次。也就是说,如果师生在此中间没有任何沟通,那么学生在此时所犯的错误,可能要7天之后才能得以纠正;学生是否理解纠正,需要再一个7天老师才能观察到效果。如此往复,我们在一个学期16周中也不能交流多少东西。所以,提高工作节奏,以尽可能短的迭代来完成任务非常必要。这也是Agile/Xp方法论的核心之一,也是RUP接受的理念。

齐嘉亮、刘伟硕、濮成林和夏一鸣都采用过短迭代完成作业。在作业部置的第二天,就已经提交一个版本,教师(和邹欣老师)给出的修改意见、增补的工作要求,在接下来本周过完以前再提交一次,可能根据修改意见再提交一次。这样,别人一次作业,他们不仅多了两三次的工作量(也即收获),而且远超这些,因为后面的几次作业是在教师针对性的指导之下的。

相比之下,有些同学采取了等、靠、拖的策略。在作业截止时间最后几分钟提交,其中一个借口是“我希望尽可能完美”――但是不会比教师直接指导下的修改更完美,并且展示完美不是我们学习的目的。教师给出修改意见以后,不少同学说“我会在下次/以后的作业中改正”,这基本等价于“老师,我已经给你留了面子,表达了充分的尊重,请不要逼我太甚”或者“我以后会改的,请不要再烦了我好咩”。如果那是错误,为什么不在本次改正?如果这是你期待的希望的“真正的”项目,不改正的错误会导致你白做,甚至可能赔偿损失。这种态度让我想起郭大侠的女儿郭芙,她砍了杨过的右臂,然后哭闹说,“我的确砍了你的胳膊,可是我被爹爹骂也骂了,对你道歉也道了,你还想怎么样啊。”郭芙之娇横可能连你也不能接受,不过那毕竟不是她本人的胳膊,而这是你本人的问题。

也有的同学会说,我改你指出的毛病已经够费劲了,"你还想怎么样啊"。笑话又说,期末的突击学习的难度,取决于你是复习还是预习。学生费劲、教师频繁地提出修改要求,改了一个毛病又整出一个来,一方面是因为不改完第一个,第二个毛病无从改起;另一方面,实在是因为某些同学的基础太差啊。好吧,那不全是你的责任,而是以前你的学校、学院、教师的责任,让我们一起抱怨吧。然后静等这个世界变得更美好…和宽容。

关于时间,邹欣老师还提到发布要求 时间驱动。没有截止时间的压力,同学们不定哪天才能完成—一般是最后一天开始动手。夏一鸣同学在期末总结时感叹,学期初的愿望有两个,其一是 题目难道能循序渐进,其二是 如果太难,希望能放宽时限。一个也没有实现,不过他大大地成熟了,已经进步到不再有这两个愿望,而是“老师是不是可以分配给我下一个任务了。”

时间要求是个硬线,在教学中,宁可缩小功能范围、降低质量,也不能超时。就在要求的那个时间,无论如何,程序要发布要可执行。我喜欢说的一句不太动听的话,在规定的时间规定的任务必须交付,如果做得像屎一样,就交付屎一样的工作,并接受别人对我们屎一样的评价。下次更努力一些,不要在这一次就求饶。

与时间相关的最后一个问题,同学们普遍缺乏对时间的估算和度量的意识,如果说对代码量的估算和度量还有那么一点意识的话。时间是工程中最重要的资源(没有之一,因为时间直接地就是生命,别的都不是),所以对于自己做类似项目的能力的度量应该持续进行,这也应该成为事后review诸葛亮会议的重要内容,并根据这种度量一次次在新项目开始前估算时间,在项目结束后对比事前估算与事后度量,增强下次的估算能力。自动控制中常用的PID方法、机器学习中各种基于经验的方法、读者故事里鲨鱼怕疼不敢撞玻璃那样的浪漫的基本原理也大抵如此。我们怎么能在工程中有时重视估算和度量,而对最重要的时间却如此忽略。多么精分啊。

5)规范

规范不止是代码规范,还有作业要求,用人类语言表述的作业要求的条目。

为什么没有一再地强调规范,因为同学们普遍地达不到更低的要求,所以教师放弃了规范这样更高的要求。时间、工作量、工作报告质量、视频,很多不能达到最低要求,有不少同学直接忽略部分作业条目,当没看见。同学们根据工作量和时间调整要求,而不是根据要求调整投入的工作量和工作时间。

还是在知乎编译原理是否屠龙技一问中,我这样回答,“能找到的活儿太差的时候,觉察不到技术的必要。成天跟小孩打架,不用练力量敏捷抗打击;成天盖狗窝,不需要图纸和水泥标号。如果理想就是这样,龙只是传说,屠龙技当然毫无用处。”如果你满足于这样的生活,不希望精益求精成为一个更优秀的工程师,我又有什么法子。我当然知道优秀的教师能够“有教无类”,“没有差生,只有差教师”,可是,偏偏我不是优秀的教师,咱们可怎么办呢。

对于不完成作业的全部这一点,教师考虑过以更详细和严厉的规则来应对:作业应该针对小项倒扣分,而不是全部作业都不完成才倒扣分。不过,教师担心这会开启 狱警-囚徒模式,尤其学生是研究生阶段的 成年人,理应获得这样程度的尊重。

说起尊重,我想起一个故事。据说侵略者为了瓦解印弟安人,对战士说,“你在部落里有什么样的权力?”战士回答,“我有冲锋在前的权力。”冲锋在前,是一种权力,这是尊重的来源。我尊重你是成年人,作法就是像对待成年人一定对待你,绝不称你为“孩子”“那个孩子”“那些孩子”,绝不轻拍你的高贵的头以示亲昵;我尊重女性,作法就是像对待男性一样对待女性,尊重她们冲锋在前的权力,所有的爱护都无声地宣布“你是弱者,自觉承认”。

我尊重你,尊重你按约定完成任务的自觉和按规范完成的能力。你按约定和规范完成任务,是对我的尊重的尊重,也是对你自己冲锋在前的权力的尊重。你之所以能看到的我的愤怒和失望,是因为你放弃了权利,你没有侮辱了你自己也侮辱了我,也是因为我对自己的无能的认可和恐惧。

6)学生观摩。现实,外界的限制。

邹欣老师希望学生能够观摩final发布和各次发布,他希望退课的同学能回来看看,看看失去了什么;他希望本科生也能来看看,看看可能在将来学到什么。邹欣老师还希望成绩能够严格执行平时作业的标准,并且平时作业应该占到应该的比重。

这些期待,我很惭愧,没能全部实现。作为主讲教师,我切身体会其中的难处,有些超过了时间花费、知识结构和技能,进入了我们所隶属的单位的组织结构(和课程体系)。课程教学只是上级(我不是在讨论赞同或反对高校行政化)要求的诸多工作的一部分,还有很多别的工作,这并不是最主要的原因。更重要的原因是,如果那么做,所付出的代价。不是克服困难所付出的努力,而是克服困难所需要承担的后果。所以,所谓“尽我所能”“不惜一切代价”我从来也没有脸去说,也不能以此要求我的同学们。

prison

7. 总结

回望来时的路。构建之法 东北师大站 2016春季学期,终于结束了。

第4周的时候,我曾经写过鸡汤如下,赞扬2位领跑同学和当时尚未放弃的18位同学。其实情形一直这样艰难,从来也没有改变。

他们的成绩反映的是这样的场景下的胜利:
你是一位将军,
部队弹尽粮绝,而且很饿;
战士战术技能很差,装备落后;
行军在敌国的沼泽里,风声鹤唳;
敌人有空中支援,有坦克,有热的饭菜和热水;
上级是没脑的杨贵福,战略垃圾,脾气暴躁,
他决定此刻立即开始,进攻前方的碉堡,既没有迫击炮也没有照明弹,
只有炸-药-包。

你的下级准备解散部队,准备撤出战场,准备起义反对你。
你说,不惜一切代价,16周突袭。
这就是4周以来的战况,我们还活着。

我们还有12周战斗。

继续冲锋。

此刻,继续冲锋。
如果你为感想和收获还不到教师的一半长度而惭愧,此刻,继续冲锋,不要等到下一次作业再改进。没有下一次。

bitter

————————————————————

博客会手工同步到以下地址:

[http://zhuanlan.zhihu.com/younggift]

[https://younggift.net/]

[http://blog.csdn.net/younggift]

[http://giftdotyoung.blogspot.com]

Debug一例,Wordpress 插件 Blogger Importer Extended 导入 blogger 图片问题

1. 背景和问题

2月25日至29日,约12小时,中间有预计会有长时间导入的过程,享受咖啡和小说。

起初,高博先生微信我,向我提供博客空间。他鼓励我,这样爱写作的人,应该坚持下去。我申请了域名,高博先生提供空间并架设wordpress已毕。既然准备长时间驻守,我就打算把以前在 blogger、CSDN、短乎 上的博客全导过来,计1478篇。

问题就是从导入 blogger 开始的。我和高博先生都发现,有些贴子的图片不见了。

最先确认的是,一部分不见的图片,是因为我从知乎贴过来,如果我作为知道用户登录了知乎,那么我是可以在导入后的文章中看到图片的;而高博先生及其他人就看不到。我以前从知乎向CSDN转贴的时候,还想过,知乎真是大方有礼的网站啊,居然可以直接盗链。恩,似乎也不是。如果盗链的时候就告知还好,竟然不声不响么……这部分图片我手动一张张重新上传过,OK了。

但是仍然有几张图片显示不出来。在网上搜索了一下,有人提到 (大意) ,"图片都下载到wordpress服务器了,在文件系统中找到了,但是在博文中不显示"。似乎正是这样啊。

跟着讨论走下去,发现导入插件的作者9个月前说打算解决,然后就没了消息。下面一大堆回贴,"我也是这个毛病啊"。

高博先生说,用正则表达式容易定位出哪些图片有问题,不过如果找到bug,方便大家就更好了。他提到用正则表达式的时候,我心说惭愧,竟然没有第一时间想到;当他说方便大家的时候,我觉得"压出皮袍里的小来了"。

见贤思齐,跟踪一下这个bug在哪里吧。于是动手,12个小时,及这篇贴子。

我用的wordpress插件,实现 blogger -> wordpress 的,是这个:

Blogger Importer Extended Migrates your Blogger blog to WordPress.  Version 1.3 | By Yuri Farina

2. 故障重现,实验床: 受控,孤立

得先找到bug,然后才能改bug,而找bug,又需要先重现bug的现象。这是个简单而直接的道理,不过不少同学似乎不怎么相信和实践呢。我经常听到这样的问题,"老师你说我看啥书才能编程好呢",这类似于"你说我吃点啥能减肥"。

万军丛中定位将军,是件困难的事,杀了他,通常不过是一刀的事。
灯光下的豹
故障重现,要求能一次又一次,在相同的条件下,触发相同的现象。而这个现象,就是你希望它消失的那个。要给药退烧,必先测体温。你猜大约是发烧了吧,猜大约是肺部感染,猜大约哈希表比数组来得快,都是猜,所有的猜测,无论是否有理论支持,在实验数据面前都是猜瞎。不少同学上来就改改这看看吧,改改那看看吧。然后某次现象消失了,他就误认为问题解决了。这叫做work around (绕过问题),不是解决。

故障重现有时需要1.特别长的时间,或者2.特别宝贵的资源,或者3.生产环境不允许动作,或者4.代码特别长特别复杂,这时需要 实验床。实验床有利于在*受控*的环境下触发特定的条件,从而导致特定的现象,方便重复。实验床有利于孤立问题使之与其他复杂的环境和因素解耦。

如果能证实实验床与生产环境是一致的,那么bug的触发条件、现象也会是一致的。实验床就成为生产环境的一个模型。在模型中思考和操作,是重要的科学、技术和工程手段。

这次找bug架设实验床,我注意了以下两点。

2.1 先本地测试,再更新到远程,xampp

重现故障现象,而且不知道是哪些图片 (更重要的是在何种条件下) 有问题,最朴素的做法是从 blogger 到 wordpress 同步实验,一次又一次。每次实验改变单一的因素,看看故障是否再现/消失。

从 blogger 到 高博先生提供的wordpress,速度也没有多快,而且我担心他的流量和带宽占用。

所以实验床应该架设在本地。

我在我自己的PC机上架设了一个 xampp,装上 wordpress,从 blogger 到我本地的 wordpress 同步。这样,我至少不用担心高博先生在哪个时区,是否方便打扰,何时可以响应我的请求重启服务器、清空数据库、重置 wordpress。等我本地找到bug修改完,再在远程的服务器上修改。

我不止一次对编程的伙伴们说,把手册下载安装到本地,但是网断的时候他们还是会说,"网断了查不出手册啊,编不了程序了啊。"我想说,没有人可以依靠,除了你自己;成为可以被别人依靠的人。

2.2 小规模实验,确保触发故障现象快速精确

同步所有的博客文章,才能触发问题。但是执行一次同步,需要耗费两三个小时。有些动作,并不需要触发问题,所以同步的不必是博客文章中的全部。这些动作包括不限于,1.下面会提到的加入日志记录语句 (并测试是否生效),2.猜测某个因素是造成问题的原因,修改这个因素以后测试效果。

所以实验床应该短小精悍。

我注册了一个新的 blogger 站点,发一两个贴子,专用于 wordpress 拉取。这样能确保触发故障现象的因素 快速 而 精确。想调校哪个参数立即就可以测试,不必等到一千多篇博文同步的两三个小时。而且更容易确保造成现象的原因就是某个因素,而不是整个庞大项目中的某个你无意中设置的变量。

我就在这个新的 blogger 站点上发贴子,粘图片,每次同步几秒钟。

架设实验床的时间,考虑实验床如何架设的时间,这些都是值得的,甚至单轮测试所花费的时间缩短的效益就值回来了。

3. 故障定位,日志: 受控,易于追溯

有了实验床,就可以罗列可能造成问题的因素A,B,C,D ,然后设计实验,一一验证或证否。所以,故障定位,是这样的技术手段,在受控 (各种因素)条件下,重复过程,以检验假设。

3.1 跟踪手段选择,error_log,可长期留存的 vs. 瞬间消失的
清湖
重现故障,初学者希望立即、马上、直接看到效果,铛地一声弹出个对话框,告诉他出错了。

人类不同于动物的一个重要特征,是可以理性地推迟期待的效果。然后成批次处理。日志输出输出输出输出,然后分析分析分析分析,而不是 输出分析输出分析输出分析。在操作系统进程调度算法中,效率最高的,是成批处理,不分时,不中断,不切换进程。学习和工作效率最高的做法,是集中注意力,完成一件工件,然后再开启新的任务。

日志输出、TDD、自动化测试、脚本,甚至程序本身,都遵循了这样的原则。

用日志跟踪,而不是实时显示,能避免不少问题。比如,工程师借口说,"当时我操作啥我也不记得了,反正故障消失了,等以后再出现再说吧。"你可以一次又一次分析日志,条件、现象都在日志中记录中,而不必非得再开启一次实验才能回想起来。"我输入什么这个现象才出现来着,唉呀状态不好,忘了。"工程方法让每一个人都不必非得是天才,也能做好工作。

我选择 php 本身内置的 error_log,日志写到error.log中,而不是另打开一个文件写进去。如无必要,勿增实体。紧着现成的用。

3.2 读代码框架,了解流程,确保日志可以被触发

接下来我大致读了 wordpress (之前粗读过一本书和 wordpress 手册)代码,然后沿着这样的顺序找到准备设置日志记录的代码行:

wordpress -> blogger-importer-extended插件-> importer.php -> 函数-> 代码行

设置位置的原则,跟猎人设置陷阱的原则是一样的,1.要确保目标猎物会经过此处,2.目标猎物会触发陷阱,3.当触发时能够把猎物抓住。

就这个案例而言,对应的是,1.跑每次实验流程的时候,希望执行 发现图片、下载图片、改博文中图片的地址 这些操作的时候,能够记录这些动作,成功的和失败的。2.失败的图片,那些图片下载了,但是博文中的地址指向却没有变更的,一定要记录下来。不希望跑了一次实验,有失败的现象出现,但是却没有捕捉到。3.当触发了日志记录动作以后,希望把准备用于分析的信息都记录下来。不希望跑了一次实验,现象也发生了,也记录下来现象发生了,但是发生的现象以及此刻变量的现象没有记录。

3.3 输出的字段,0.易于找到,1.触发条件,2.assert

记录哪些字段呢?我想的包括: 0.易于找到,1.触发条件,2.期待的,实际的

第一,易于找到,要容易在很多行日志里找到,所以加上明显的分隔线和换行。

在Linux下,我就开个终端,tail -f error.log,完成一次实验,往上翻到刚刚开始实验时候,往下读。这次是windwos,我记一下实验开始的时间,然后在日志里找,或者在每次实验时在日志里写个明显标记,从结尾往上,最后一个标记就是本次实验的开始。

第二,要记录触发的条件
直路
分析的时候,找到出故障的那条,看何种条件下会触发。这就是程序设计语言里的" if ( condition ) "里的condition。如果每当这个条件都会导致故障,就可以怀疑这个条件可能就是原因。

需要注意的是,因为找到bug以前还不知道触发的条件,所以尽可能多记一些怀疑的条件 (在眼花缭乱以前),每次实验就能多分析一些因素。

我按下面这样日志。

error_log("-foreach post----\n"
.  print_r($post->post_date,true)."\n"
.  print_r($post->post_title,true) . "\n"
.  print_r($found_images, true), 0);

这一条记录了触发日志记录 (不是触发故障,那需要根据日志人工判断)的条件foreach post,遍历每篇博文的时候;记录了博文的日期 post_date,博文的标题 post_title,图片的某个信息 (路径?名字?很多图片的名字拼接在一起?)。

第三,你期待会是某个值的变量,如果它值得怀疑,记录它。对比你期待的值和实践发生的值,如果有差异,那就是问题的原因。这个变量,既可能是条件中的,也可能是参与计算和输出的。

在这里 $found_images 就是值得怀疑的,我打印了不少次这个变量,在不同的位置。C++开发原则之一,assert你认为本该如此的那些量。这时我做的差不多根据同一原理。

3.4 日志分析,触发事件的特征

接下来就是人力工程了,一行行读代码,找到故障发生 (我们记录了进入那样的分支,比如那些成功的操作以外的else)的地方,看触发故障时 各个因素 (条件)都是什么样的。

故障发生的条件,是不是有规律?每当这个时候我就想起包师弟,归纳能力超强,能从乱七八糟毫无规律的现象中发现模式。恩,他的模式匹配算法可能比较好,很多智商测试题都是考察归纳能力的。

这次,我独立找到了模式。中文。

如果文件名是中文,比如"鹦鹉螺",那么就会发生故障。一共15张图片符合条件。

进而发现,所有文件名是中文的,都发生了故障;所有文件名是英文的,都没有故障;所有没有故障的,都是英文文件名;所有发生故障的,都是文件名中文。

4. 解决

豹
万军丛中取上将首级。万军丛中找到上将很花时间,此次约10小时。斩杀上将,只是一刀,约几秒钟。验证上将确实死透了,需要的时间稍微长一些,先实验床,然后生产环境。

一共只改了一行,如下,正是中文文件名容易出现的问题。原来的代码,在文件系统中和在博文的 img src 中,分别 urlencode 和 没有urlencode,所以当查找那个文件时,按期待的名字,它不存在。

下面的代码,注释了的那行,就是bug所在,注释那行的下面,是我修改的结果。

wordpress\wp-content\blogger-importer-extended\includes\importer.php:
if(!is_wp_error($image)) {
$attachment = wp_get_attachment_image_src($image, 'large');
//$content = str_replace($found_image, $attachment[0], $content);
$content = str_replace($found_image, dirname($attachment[0]).'/'.urlencode(basename($attachment[0])), $content);

5. 修改工具,还是修改产品;一般性的程度

我没有修修改插件的代码,仅仅测试通过。我手动修改了在高博先生那的wordpress里的15篇博文。我选择的是修改产品,而不是工具。

鉴于出现这个问题的,可能主要都是能读懂中文的,所以我写了这篇博文,而不是修改插件再发布。

修改工具能更一般性地解决问题,更大范围地产生效益。我惭愧,还是没有高博先生那么有高度和乐于助人。

5. 感谢

感谢高博先生的空间和时间。

感谢winguse先生提供链路,使我得以访问 blogger。blogger,就是 google 的 blogspot,如果不能访问到的话,我没法授权 google 允许导出,也不能导到我的本地测试PC机中。

在跟高博先生和winguse先生讨论的时候,我都很享受,高效率地交流使用条款和技术路线。三言两语可决,毫不罗嗦。

感谢叶卡编辑让我认识高博先生,及那么多精彩的人。

感谢 Yuri Farina 开发 Blogger Importer Extended 插件,使我得以取回自2007年2月以来的历史博文。
电线杆
------------------------------------------------------------

博客会手工同步到以下地址:

[http://zhuanlan.zhihu.com/younggift]

[https://younggift.net/]

[http://blog.csdn.net/younggift]

[http://giftdotyoung.blogspot.com]

木雕体会

3d23f96ca45b19a2767c97eb259acd61_b

初学,刻了10小时左右。只需一截木头,一把小刀,一个人,可以静下心来一两个小时。有些许愉悦,与各位同学共享。1.

典同学提到过,他特别不喜欢重复的枯燥的事情。木雕一刀刀削下去,是不是重复枯燥的呢。不是,每一刀面对的不同纹理会产生的后果,刀沿不同木纹时的手感和 阻力,刀的角度的影响,刀尖或刀锋的差异,切削大平面或小细节时的不同。雕刻的每一刀,绘画时的每一笔,代码的每一个字母,在别人看来是无聊地重复。如果 你明白并细心体会,每一次呼吸都是不同的。

我在做100个俯卧撑的时候,典同学和诸多同学都提到这是毅力。事实上不全是。一次性做100个俯卧撑非常累,最热的天气汗水甚至可能在下巴颏的正下方聚 成一小滩。但是跟你想像的不同,最重要的不是力量,而是呼吸,如果你不能保持呼吸,很难坚持20个以上,因为你的肌肉没有足够的氧气;跟你想像的不同,至 关重要的不是毅力,而是观察,每一次下沉和推起都是不同的,前50个,第60个,第70个,甚至第55和第56个。在每一次下沉和推起时,完成了多少,还 剩多少,完成了百分之多少,这是当前小单位 (比如10个为一单元)中的第几个。这一次的呼吸刚好与动作配合吗,差距在哪里,你还有多少次可以纠正和体会呢。这一轮100个俯卧撑与昨天的有什么不 同。

如果能够了解到纷繁复杂的观察角度,了解这些变量的意义,甚至只要了解大千世界每一项技艺都有这么多角度,你从未注意的,或者别人从来不知道的,没有什么是重复和无聊的。

每一截木头都是新的,每一件作品者是新的,每一刀都是新的,为这一刀设想的每一种没有实施却在你头脑中闪过的念头都是新的。

2

2.

技艺中有工程,用工程的思想学习技艺易于接受,技艺与工程思想也相互印证。

小步快跑。每一次切削不可求快,不可以贪多。一刀削下去,如果跨步大了,可能多切掉一块,再也无法粘回去。虽然可以想些后续的招法弥补,但是书里提到的猫 头鹰被削掉耳朵只好改成企鹅这种事,不一定总能成功吧。而且,弥补也需要一些本事呢。切得块儿大了,用的力量大不易控制,木质错综复杂,随时可能遇到脆弱 的地方,可能就一刀削在手上。小步前进,反倒比大跨步跑得更快。每次只削下一片,每刀只前进一点点,还要每每回过头来检查是否符合预期,接下来如何。

我们写代码的时候不也是这样?对于不熟悉的技术,要写技术原型测试,而不能急于集成进工程本身。每次写上几行,然后就编译,确实没有语法错误,甚至为了确保能编译,要把一个大的任务拆成几个段落,每个段落都编译,设置检查点,总结,记日志。

持续集成。木雕是立体的,不同于二维的绘画,在最初的原料上,你没有办法标记所有后续要切削的效果。而且随着慢慢削进肌肤、骨骼,你原来标记的记号被削掉 抹去了。需要持续地重画铅笔记号,甚至你需要特意切削出一个以后一定会删除的平面弧面,只用于这一轮的标注。每一轮切削,都要重画下一阶段重点的计划,然 后再把标记的计划削掉。天狼星升起,尼罗河洪水再来,建城毁城,如此往复。每一次重画,都可以体会到不可一蹴而就、以退为进、步步为营,体会多个角度观 察,各变量间的约束和耦合,体会正交之艰难。

可能与常识相悖。记得第一次在书中读到,在第一轮迭代中最优先应该完成的,不是最简单容易的任务,而是风险最高最可能失败的部分。因为工程中的各个部分是 乘法而不是加法,任何一个部分的结果是0,全局皆输。所以,如果工程如果必然失败,那么让它尽早失败。在木雕中也是这样,先刻风险最高的部分 (不是最精细的部分,我们假设你已经技术成熟,不在当前项目中学习基本技能)。如果这一部分刻坏了不可修补了,就可以换块木头来刻了。

类似高风险先行,另一个与常识相背离的原则: 锋利的刀更安全。因为更锋利的刀在切削时需要更小的力量,因而更容易控制。在锻炼中也有类似的原因,动作要慢,要利用肌肉本身的力量,不要"悠"不要利用 惯性,因为不受控制就更可能令你受伤。以上原因我们都容易理解,我们容易忽略这样的一个事实,锋利的刀或者钝刀,都能够轻易切开手指的皮肤甚至肌健,所 以,钝刀并不更加安全。

不停测试。每一个步骤的结果都是可检验的,或者可以通过与其他步骤的相互作用因而效果是可自检验的。我们需要在最初计划的时候就设定好每个步骤之后检查点,并且需要时时停下来检验。我们甚至可以不把检验理解为"停下来",而是把检验作为步骤的必要组成部分。

在写代码时,我们有时会兴致来了写上个十几个函数,醉心于各个函数之间复杂(因而优雅和令我们兴趣?)的调用关系,然后在终于开始编译时发现里面充满了没 有预期的bug甚至总体框架的错误。我们忽略了检验测试。为当前迭代的成果 (还远不是最终成品的样子)设置好检验的方法。在用同一块木头雕刻或车铣出两个套在一起的环的时候,细分为五六个步骤,为了避免细瘦的圆环断裂,需要最后 一步才能成环和打磨。

3

4

在最后一步之前,圆环是木条,是十字架型,是方形粗糙的框子。如果你能从这些胚子里看到未来,当然最好,即使如此,你也需要知道在每一步,那些木头、十字架型、方型框子应该是什么样子,当前的效果与期待的差距是否可以容忍。

5

3.

看不到未来,看不清全局,没有足够的能力从一截木头中看出最终的模样,怎么办。我们都是凡夫俗子,是不是就不能木雕?工程和科学存在的最大价值就在于,它能够让凡夫俗子完成令自己都惊讶的任务。

解耦。

Lee Hammond 在 Draw Real People! [Draw Real People! (豆瓣)] 一书中给出这样一种方法,任何人都成能为精确绘制人像的画家。她 (?)提到给照片打上5*5的方格,然后细心*复制*每一个方格里的内容,不要管那里的东西是什么,是眼睛也好,是嘴巴也好,都不要管,而是想像,那只是 直线、曲线,这样弯那个角度的线,有轻重,有浓淡的元素。在她这里,画的元素不是骨骼肌肉、透视、情感,而是 点、线这样的元素。

元素(你甚至看成像素也未尝不可吧),与你所希望绘制的目标无关的元素,才是你在实施过程中需要关心的。这就实现了整体与部分的解耦,也完成了各个部分间的解耦。

我现在还记得跟袁FY同学一起用MFC做电化学工作站的上位机程序。我说,咱们在这里添加一个自定义消息。这对于我而言,就是单一的一个动作,袁同学随口 就说,好啊,是应该添这样一个消息,一共分成三步。我当时震惊得都停了下来。确实是三个步骤,我也早就知道是这样,侯捷老师的《深入浅出MFC》里明明白 地写着。为什么我有的时候会写着写着突然忘了呢,因为我从来也没有把这一单位动作拆分成若干明确的步骤。更不用说理解这些步骤正是对整体动作的解耦。

以前我讲课的时候喜欢说,第一步、然后、然后、然后、然后,最后嘻笑着说"这就成啦",甚至就是从头到最后,中间没有段落节奏。我喜欢这种连贯一气呵成的 感觉,享受流畅的过程。后来我爱人和刘馆长分别教育过我,需要分成若干步骤,读者、学生和受众都更希望有若干点而不是整体。这是部分与整体的解耦。

木雕经常要把木头翻过去倒过来,以便于行刀。这时,穿过木头看本质看未来,就更难。但是,如果你翻转之前划上一道线,告诉自己,我要在这里刻一个这样弧度 的表面,从这里到这里,这样就简单多了。我们不需要看到未来,只要能看到此刻,我们不需看穿木头,只要看到这一层。世无天才,有巧妙之法。

在软件工程中,我们把用户的愿景把需求"降维",分解成互相之前的关系由spec规定的模块。这样模块的实现者就不再负有了解全体大局之责,不再为战略失 误负责。如果他实现了spec而总体拼接效果不佳,那是划分模块的人的责任;如果他的代码跑起来不符合spec要求,那才是他的责任。把战略失误推给战术 实施者,这是常见的糟糕手法啊。所以我希望,所以谓协作配合的第一步,不是协同,而是分割、确定边界,解耦。

为了避免涉及全局,在工艺上有一系的手段用于解耦。画家要求精确地画你所看到的,而不是你以为的。要求你把一幅画上下颠倒临摹,要求你不画物体而是画它们 之间的空隙 (阴形) ,这些和要求只划每个格子里的点线一样,达成了局部与全局的解耦。程序员关注的,是spec,而不是需求。不是把自己放在大潮之中,而是割裂上下文,割裂 与这个世界的联系,沉浸在当前这一时刻的短期目标之中。

6

4.

工艺过程。有些东西,如果不看过程,只看成品,我们是难以理解其中的巧妙,或者如何简单的。The Art of Whittling [The Art of Whittling (Woodworking Classics Revisited) (豆瓣)] 1930年的小册子,只有91页。作者提到一种奇特燕尾槽,难以想像是如何拼装的,他说是一个经典谜团。但是当作者提到,这一结构是先做一般的燕尾槽,然 后再切割成这样,你一下子就豁然开朗"啊"直拍大腿了。瓶子里有把椅子,不是在椅子外面吹个瓶子出来,而是椅子是天鹅绒或羽毛的;瓶子里有艘船,那船的每 节桅杆都是放倒了装进船子,然后用线在瓶子外面把桅杆拉起直立的。

7

8

这是工艺过程。就像现场观摩代码的生成,读github上一个开源工程的演进,观察一个人 (比如自己)的成长,与直接把进度条接到最后,看好人如何把坏人绳子以法,愉悦和理解之深刻都是不同的。

雕刻一件作品可能需要1000刀,或者500刀。写一个小项目可能需要1000行代码,调用20个不同的库函数,声明和维护15个变量的状态,50个分支 和循环。所有这些,所有这一切,都是乘法 (逻辑与)。如果一个小小的瑕疵,可能整个大厦就此倾覆。这也是工程师为什么最好是强迫症,或者职业把他们塑造成精确、严谨、刻板。因为当你完全发挥你的 极限工作,活着本身就已艰难,根本没有心思逗乐游戏。

高手和低手的区别,在于这1000刀,每一刀他都比你快一点点,在于这1000刀,他能做到没有一刀犯错,在于他能比你少切削800刀而得到相同的效果。 在于他是一个更全栈的工程师,不仅能刻各种角度,能充分发挥各种刀的长处,他还能把手上的破刀磨成刚好锋利,时时锋利,而你以买代磨。在于他能用剃须刀片 用瑞士军刀改造出一把刚好合手的劈刀,而你需要等网购来的专用工具,时间在等候优秀工具中流逝。

在于他能够耐心等待油漆干透,然后打磨,然后刷上新的一层,然后再等待。他知道什么时候必须等须,不能强求,质量、范围、时间、代价,不可皆好。

在于他知道顺着木纹下刀或横截纹理,在于他预计到这些纹理可以在最后成品中表达特别有意思的效果,而一直保留着这一平面。在于他知道只有纵向的木纹才用作 为马腿支撑木雕,在最初这一点就改变了很多选择和方向,你甚至还没有看到他把刀从鞘里拔出来,巨大的区别就已经开始积累了。

在于作者说木雕猫头鹰是5分钟工程,杂志记者说她花费了1小时。而我,花费了2个小时。
9
5.

美术老师告诉我了,素描什么的就别指望了,没啥希望,也没有那个时间。我明白自己也只能停留在自得其乐的程度,专业、高手,甚至初学者、入门之类的,都距离我太远了。我知道,画得像刻得像什么的,并不是艺术追求的目标,从来也不是,甚至并非入门的标准。

当年,我爱人的英语阅读书的扉页上看到她写着,"不为无益之事,如何遣有涯人生",当时我很受触动。我们经常在接到一个任务和目标时,首先质问,"这有意 义吗,这能成功吗"。这是我们走向一无所成的第一步。不踏出第一步,我们甚至连都闻不到意义和成功的气味,连失败的资料都没有。

没有目的,不在乎意义。

我沉浸在每一切削之中,沉浸在观察木质纹理在层层显现之中的变化,沉浸在锻炼时汗水呼吸和心跳的感受观察之中。代码一行行生长,模块按我的预期渐渐由模糊变得清晰,数据开始庄严流动,电压和电流和光强和所有的信号帮助我感知。世界按我手的指向呈现出本来的样子。
10

11

12

13

Big Book of Whittle Fun [Big Book of Whittle Fun (豆瓣)]

似乎即 手工木雕[amazon.cn/%E6%89%8B%E5%]

------------------------------------------------------------

博客会手工同步到以下地址:

[杨贵福 - 知乎专栏]

[杨贵福 的专栏]

[giftdotyoung.blogspot.com] 我本人也访问不到了,blogspot暂停更新。

你喜欢过的,变了

8d86f2c290ad6735f6e4c606ad7df64b_b

1. 为什么我不用QQ,不变的理由
这是个老话题了,可追溯至2007年12月25日,从那开始经常有人问我,"你为啥不用QQ呢"及QQ的诸多好处。

起因,是因为与QQ合作的珊瑚虫版QQ作者soff因为一二三四罪名被跨省拘捕并处以刑责。作为一个也写代码的人,我感到深深恐惧,决定永不使用QQ。我 不认识珊瑚虫的作者,也与我是否赞同他的做法无法,我也没能资格赞同或反对法律对他的触发,纯情感导致的个人选择,我向所有QQ好友发送了这条消息,我将 永不使用QQ,八年已过,言犹在耳。[http://newsmth.net/nForum/#!article/SF/131764],"杨贵福通信方 式变更"。

八年多来,因为不使用QQ及QQ群,为我的同事、我的学生,还有我本人,带来非常多的麻烦。就像所有的选择一样,我当然知道这样做是有代价的,有时代价沉重。如果你也已经工作了,就知道拒绝领导要求,无论什么理由,不使用指定的通信工具是非常不受欢迎的。

有时我说,我有宗教信仰不能使用QQ,就是 不用QQ教。跟飞天神面教有得一拼吧。有时我说,就是不喜欢QQ群打扰我工作。有时我说,单位没有为我配备一台机器专门运行QQ,我的手机和我家里的计算机是我个人的。

后来,珊瑚虫的作者刑期已满,我也看到了新闻。但是,我也不能再使用QQ了。

这时的原因,一是因为在过去这么多年来,劝我使用QQ而被我拒绝的同事、师长、同学,如果他们知道我改变了主意,是我对他们的不尊敬;二是因为,我无法补偿过去那么多重要的事务中,因为我不使用QQ而为别人带来的不便。

有人打趣我问,为啥你可以用微信呢。非常简单,因为我当初的誓言里,我将永不使用的是QQ,而不是腾讯公司产品。事情上,虽然心理略感不适,我在这几年里 偶尔也用过QQ邮箱。所以,承诺兑现不易,不能轻易给出,内容也要谨慎。因为你一旦给出承诺,它就不再是你的,而是属于所有接收到你承诺的人,他们因你的 承诺而做出的决定,你都有一份责任。<Getting Real>说,"Bottom line: Build products and offer services you can manage.  It’s easy to make promises. It’s much harder to keep them."

2. 也许他们都没有承诺,比如有道词典

我曾经很喜欢用有道词典,两点原因。

一、在有道词典被网易收购后,保持了原有简洁的界面,没有像很多门户网站那样把一个好的产品藏在几百个链接里面,用户要点三级才能找到。虽然有道新闻、有 道云笔记出现了,但是有道词典一直可以用[http://dict.youdao.com/]进入。他明白作为用户,我根本不关心有道词典是谁家的,在百 货大楼的外面写上类似"某某股份有限责任公司"的全称,对于顾客是非常莫明其妙的。我只想要不变的承诺。

二、有道词典以前我用金山,有道比金山的广告少,无论是刚进入,还是查询以后。

我经常在浏览器地址栏里输入dict,然后回车选择自动补全;然后输入要查询的单词,回车出结果。两步。

最近几天,有道词典开始频繁弹出窗口,好心地建议我安装 APP。需要用鼠标找到X,点击,然后才能继续。

有道词典不知道,我早就安装了APP,在手机和平板里各一,而且已经用得还算喜欢;我还知道,即使此时我再买个新手机安装APP,有道词典也一定不会知 道,他会继续好心地建议我安装。我还不明白,为什么要在PC端这么急迫地推广移动端的产品,打断查单词这种只有不到20秒的动作,插播一条必须2秒以上才 能关闭的广告。

情怀哪里去了?我突然就明白了为什么那个小子要巴巴地大清早跑到列农家门口把他一枪打死。因爱生恨吧。忍了几天之后,我终于从浏览器地址补全里删除有道词 典,准备过几天把手机和平板里的APP也删除掉。全面安装 bing词典 [http://cn.bing.com/dict],我试用一段时间了,界面简洁,挺方便的。

我所期待的,不是更好的服务,不是更贴心的猜测,而是 一 如 既 往。一如既往就很好,就很不容易,改变往往包藏着别的动机。

3. 人人网,你是为了我的安全么?

当年人人网正火,我用得心情舒畅,每天偷菜,隔几天发贴,还有一大堆好友,数量直追周治国老师。某天人人网告诉我,为了我的安全,需要我提供手机号,然后 是繁琐麻烦错误百出的过程,这一过程中的错误也表明,它不是为了我的安全,而只是为了得到我的手机号。所以我不再人人网玩了。当然的贴子在这里, [http://blog.csdn.net/younggift/article/details/7779174],我提到----引文开始我决定注 销人人网的账号,这实在太浪费时间了。而且,这让我想起来小学和初高中老师。

笑呵呵走过来,对你说,"唉呀,这不都是为了你好么。"

绷着一张脸,对你说,"你的同学可都同意了,就你,怎么这么没有集体观念呢。"

拍拍你的后脑勺,对你说,"你看,这么长时间积累的东西,你舍得么?"

我恨不得穿越时空回到这些老师面前,回答她们的问题。我舍得,舍得抛下一切,以避免更长久的胁迫。----引文结束。

4. 那些美好的公司,他们可能确实没有承诺过

google当然关闭reader,我说"云服务就是个渣:云服务或者google reader有多可靠" [http://blog.csdn.net/younggift/article/details/8675402]。

传说google很明确地提到他们准备把大家都强迫到g+上去。这个传说不知道是不是真的,不过google很干巴巴地说,他们打算关闭reader这个 服务,我猜他们当初的条款中就明确提到可能会是这个结果。王朔笔下的小流氓常对女主角说,我可不喜欢你啊,你别追我,追我我也不负责啊。大致如此。而且他 真的不负责。

我唯有认命,谁认我当初猪油蒙心瞎了眼睛,觉得就我能改变浪子让他回头呢。认。

后来google又说,他打算把日历 (calendar)的短信功能也关了。我当时的第一反应是,"啥?"好吧,我也认。当时GFW越来越高,我为了能够使用 google calendar先后换过三个手机 (比此前所有的手机数量都多),新手机因为不能访问calendar就被扔到抽屉里。我追随google calendar到当时尚能访问到它的4G网络,才买了苹果手机。然后4G网络也经常访问不到的时候,我靠翻墙订日程,然后盼短信。

短信功能没了,我放弃了 google calendar。决定放弃是个漫长的过程,持续了几个月。最终我开始删除日历、转换到新的日程软件的时候,我面对计算机长久地坐着,叹口气,删除了过去和信任。

后来google说,他们打算把picasa也关了。我愣了一下,不再关心细节。如果他从来没有承诺,我也没有什么抱怨,也没有什么希望。

类似的,kindle默默 (偷偷?)地升级了屏保,由情怀变成了广告。好在打开书页以后依然如旧,封面广告可以忍。不过,在此之前,亚马逊出售过一款kindle,屏保有广告的, 是更便宜的,也就是说,没有广告的是更贵的。原来没有广告的现在变成有广告的了,不知道亚马逊是根据哪些条款。我得承认,我是个懒惰的消费者,我没有去查 条款,只是在心里给kindle减分而已。

5. 我们可以相信什么,我们愿意相信什么,信仰和誓言

有的同学可能会说,你也太事儿了,这些许小事,无所谓吧。

每个信条的改变,每一个承诺的抵赖,都是翻天覆地的大事。你可以允许别人,这是宽容;但是当你要求或希望别人允许你背叛,性质完全不同。你的价值,就是你 的承诺的份量。谨守承诺,不会增加一分,背叛承诺,一文不值。承诺是黄金制成的,不能触摸,经凡人之手,哪怕一次,就只是灰烬。

科幻作家星河先生,也是SMTH笑话讨论区常驻小黑屋的用户。他一次跟人讨论,提到:你们曾经发誓 是共产主义接班人,是不是都忘了。底下回帖一片哄笑,但是我读到星河先生很严肃。

我在读帖的时候在想,如果你轻易地就说"那些都不算",那么,哪些才是算数的,什么是可以相信的,你的什么形为是可以预期的,你个人什么是可以相信的。

所以,古代知识分子期待王莽在未篡之时就死去。所以,我当年曾经为我年轻时喜欢的歌手孟庭苇设想过多种结局,并以为她年纪轻轻就死去是最好的,后来闻讯她 准备修佛,后来嫁给了高中同学,都不错。"自古美人如名将,人间不许见白头",从这种意义上讲,也是一个角度吧。周迅嫁了演员,我觉得不错,各位同学觉得 范冰冰嫁李晨如何呢。好吧,我们至少可以有理由设想,她们嫁给了爱情吧。

另外的一些呢?唱着清纯的歌的人,突然说这些也就是谱子歌词;你喜欢过的,变了。就是这个感觉。

6. 单纯的你,一如既住

豆瓣前几天发布了一个广告,情怀什么的。我看到不少人在网上嘲笑,还有人提到,这些太不关心大众的口味了,你们这些抑郁症和文青们就窝死在那里得了。

一如既住是件困难的事,尤其是当外界纷繁变化。商业可能有各种变化的要求,但是情怀应该坚持原本的,不忘初心。我仍然希望在那里标注我看过的书,我看过的电影,偶尔评论。自己的情怀,标注而不是展示,不关心别人,也不追求被关注。不关心世界,也不关心大众。

我曾经请教过科幻编辑和作者们,为什么国外的科幻杂志读者也只有2000人却可以坚持数十年,而我们的杂志读者数如果不达到几万 (?)就办不下去。几位当时指点我的原因略去,我当时是想幼稚地质疑,为什么我们非要做大做强,继续做个原有规模为承诺过的用户一如既住服务的小站,不好 么。支付宝就非得也成为社交工具么,不攻略全国全世界就心里痒痒,这是什么传统衍生出来的情怀呢?

对了,我不在豆瓣发日志,因为它审核过我,不许发表,[http://blog.csdn.net/younggift/article/details /7078445]。虽然这是一篇挺技术的文章,但是我没有怨言,因为被审可能是因为这篇的最后最后最后一段提到了GFW这个关键词吧。我没有怨言,因 为,豆瓣没有说过什么都能发,它早就审核日记了。因为,他以前也没有做出一副"你来吧,我对你可好了,什么都能发"的态势。

我心匪石,不可转也。我心匪席,不可卷也。你真认为这是爱情和浪漫么。同学醒醒,这是承诺。
68e4c307148db48acdfa24e615a12742_b
--------------------------------

博客会手工同步到以下地址:

[http://zhuanlan.zhihu.com/younggift]

[http://blog.csdn.net/younggift]

[http://giftdotyoung.blogspot.com] 我本人也访问不到了,blogspot暂停更新。

2015述职

2015转眼即逝,很多事情回想起来就像发生在昨天,在刚刚这一刻。

很多年前的事,也就像昨天。

课桌微温,书纸尚有余香,而红颜已老。人生苦短,世事无常,流沙过指隙。日影不可追,且注目此刻。

01

02

03

04

05

06

07

08

09

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

 

GRE单词里的大数据和丰富情感,一笑

20160110174047922

大学时学英语,一件非常让我痛苦的事,就是课文里的内容如此无聊。在我看来,满眼都是谁对谁的评价、观点、态度,环保如何,圣女心,世界让我感到满意喜悦,诸如此类。即使用中文表述的时候,上述情感在我初中以后也日渐稀少。

没错,我就是有些同学说的那种 粗线杀,情商低下。对于别人的细微情感变化,我感到难以理解,同时,别人对我难以理解他们的情感也难以理解,或者说他们认为我情感淡漠。薛师兄说,只认机 器不认人。经常地,我在探讨真假,大家在探讨我是否关心他们或者接受他们的关切,稍一拔高度就是我和他们是不是一伙的。

H老师曾经对我说,"刚才那个家伙真是太气人了,所以我最后就损了他两句,他果然没词了。"我后背直冒凉风的感觉啊,我说,"H老师,你以后要是觉得我太气人了,可千万真接告诉我啊,我都没看出来你生气,而且我根本没听出来你是在损他。"

向你描述一下我通常的感觉,那就是: 聊着聊着天,正讨论着,别人怎么好像突然生气了呢,怎么回事。这就是我的自我感受,我对别人的感受是下面这样的。

你有没有那种感觉,跟一个体力贼好的人一起徒步或者做事,你已经累得舌头吐出来,跑得跟狗一样喘,他没事儿人一样,而且还在催促你。你遇没遇到过那样的 人,凡是讨论题目,他都是"这不是挺简单的么,就这么,你看就解出来了",你时刻及各角度被智力吊打。你觉得这道菜就是好吃二字而已,他能辨识出五六种调 料,肉还有点老,如果浇点汁会更好一些。

当我对你们中那些情感丰富的人,就是这样的感觉。

但是 ! 最近我认识到,这些我见过的人的情感丰富程度还是弱、爆、了。

记得那个传说么,爱斯基摩人有36个还是多少个词汇用来描述 白色,这个故事试图说明只有当能够细致区分的时候,才会有这么多词汇。这个故事后来据说证实是假的,不过汉语里确实有不少词汇用来区别马,公的、母的、年 轻的、阉割以前或以后的,都是单字。还用不同的单字区别不同的人的死,皇帝的、诸侯的、王的、大人物的、小人的、死得其所的、死不得其所的,各国打仗也有 类似的区别细微的动词,征伐讨战。类似意思对应多个词汇,说明使用者熟练区分的能力已达臻境。

试想你身边有这样一个人。在他看来,你可能是傲慢的,傲慢的种类分为 10种。你没看错,10种,每种还略有不同。他希望你了解到他愤怒了,愤怒一共28种。这不是28个等级啊,同学们,不是可以排序的,而是有若干维度,不 同的愤怒。你可能被评论为一个有趣的人,也可能,你真是无趣 (我最初从古龙先生那里看到这个词) 。有趣或无趣,一共19种。他觉得你笨,笨有18种。诸如此类。

我在背GRE3000的时候发现,怎么这么多负面情绪的词汇,好几个诽谤,好几个指责。开始我以为是错觉,背了一轮以后,我大数据 (EXCEL)了一下,如下。

20160110174714834
即使在汉语在现实世界里,量化和精细区别这些情绪也够难的了。更不用说用英语,原来老外情感如此丰富,看来他们冷漠的形象是因为怕咱们不懂。

有的同学可能好奇我如何统计的。用EXCEL和手。

-----

李 (日易)同学看完此篇后,与我讨论,如下。

李: 老师我刚才看你的知乎的专栏了。我给你分享下我最近看到的关于语言的一些观点

然后李同学分享给我下面这本书中的几页,我们就此展开讨论。

屠杀器官[日] 伊藤计划 / 邹东来 / 朱春雨 / 上海文艺出版社 / 350页 / 平装 / 38.00元 / 2014-11 [http://m.douban.com/book/subject/25977519]

杨:谢谢分享。刚刚看到的你拍照的观点,我想起当年一个同事对CS游戏的评价,她说,“不就是这些人从这里到那里,然后把那些人杀了么。”帝国时代也是如此,大部分电影也是如此吧。

杨: 如果只归结为目的,就涉及到1.他人是工具,2.过程不重要,这两点。而且简单化这种作法,在抽象出目的的同时,也抹杀了被抽象消减掉的其余的细节,而那些细微的区别,正是另一些重要的维度。

我所嘲讽的,只是GRE细致入微所区别的那些,而不是区别这一行为本身。

李:我就是看你提到萨丕尔沃夫假说想到的。英语作为霸权语言,使用范围如此之广和包容情感能力强有关。

杨:我部分赞同。霸权语言一定是有强表达能力,虽然有强表达能力并非成为霸权的充分条件。

李:当然也和日不落帝国有关。滚雪球。

杨:大脑里主司语言的区域,应该正是进化的结果吧。我的确倾向于相信,思维与语言是一体的。

李:我认为思维和意识是先于语言的。共和,社会,民主都是舶来品,但是这种思维却不一定是。有很多意识用目前的语言表达不了,或者说简单语言表达不了。作家之所以是作家是因为他们能表达更多的情感,就和歌唱家能表现更多音域一样,普通人唱不出的音高但是却可以听到感知到。

杨:

>我认为思维和意识是先于语言的

>共和,社会,民主都是舶来品,但是这种思维却不一定是

思维与语言一体,并非仅指共和或republic一词,也包括描述这种思想的语言元素。这个词的发音和写法,倒在其次。思维,这里指是概念的内涵,你讨论的是概念的外延。

-----

16

aggrieve
agonize
arduous
bale
drudgery
excruciate
fretful
grieve
grimace
harrow
irk
lacerate
lament
lucubration
painstaking
smart
travail

4
挖苦
backhanded
caustic
diatribe
persiflage

10
轻率
brash
candor
flippancy
forthright
frivolous
hasty
impetuous
imprudent
rash
toy

7
顺从
amenable
compliant
obedient
pliable
pliant
submissive
tractable

6
贬低
debase
deprecate
depreciate
detract
disparage
pejorative

40
友,和,不和
ally
amiable
amicable
amity
camaraderie
comity
congenial
cronyism
inimical
intimate
outgoing
rapprochement
affable
amicable
clement
comity
concord
congruent
consonant
disarm
discord
dissonance
equable
estrange
genial
inclement
intemperate
mollify
rapport
rapprochement
reconcile
reprove
adversary
animus
antagonize
confront
enmity
inimical
innocuous
rancor

10

arrogance
bumptious
hauteur
imperious
impertinence
overbearing
peremptory
pontificate
supercilious
aloof

14
吵,喧
boisterous
fracas
spat
squabble
tiff
blatant
din
furor
pandemonium
revelry
riot
roisterer
strident
vociferous

12
严厉
barb
berate
dour
draconian
excoriate
harsh
lambaste
pan
rebuff
scathing
severe
upbraid

22

acrid
asperity
barbarous
boor
churl
crass
curt
feckless
harsh
husky
impertinent
insolent
laconic
loutish
potboiler
raffish
ribald
rustic
scurrilous
slipshod
squat
uncouth

6
沮丧
appall
chagrin
crestfallen
deject
hangdog
wretched

7
煽动
incite
instigate
rambunctious
riot
tempestuous
testy
tumult

6

acrid
asperity
barbarous
choleric
despotic
fury

19
趣,及无趣
agog
anecdote
apathy
badinage
banter
disinclination
distract
droll
drudgery
ennui
indifferent
intrigue
jejune
pall
torpid
vapid
agog
wag
bland

18

awkward
clumsy
cumbersome
dolt
dullard
fatuous
flounder
fumble
gauche
ham-handed
inept
lumber
maladroit
obtuse
ponderous
simpleton
tactless
ungainly

28

antagonize
apoplectic
bait
bristle
choleric
disgruntle
exasperate
fury
gall
incense
infuriate
irascible
irate
miff
nettle
pique
provoke
rage
ticklish
vex
rankle
rant
rile
roil
spleen
sulk
tantrum
testy

7

careworn
dolorous
gloomy
lugubrious
misgiving
saturnine
somber

11
怕,惧
appall
formidable
redoubtable
apprehension
boggle
grisly
terror
trepidation
xenophobe

6
无责
exonerate
upbraid
vituperate
feckless
wastrel
truant

22
责备
admonish
berate
castigate
censorious
censure
chide
culpable
denounce
deplore
diatribe
execrate
liability
reprehend
reproach
reproof
reprove
stricture
fulminate
goldbrick
guilt
impugn
lambaste

6
诽谤
aspersion
besmirch
calumniate
malign
obloquy
vilify

12

aggrieve
annoy
beleaguer
chagrin
fretful
grate
harrow
irk
irritate
miff
peeve
vex

12
骂,辱,咒
abuse
invective
obloquy
opprobrious
upbraid
vilify
vituperate
anathema
discredit
epithet
ignominy
stigma

------------------------------------------------------------

博客会手工同步到以下地址:

[zhuanlan.zhihu.com/youn]

[杨贵福 的专栏]

[giftdotyoung.blogspot.com] 我本人也访问不到了,blogspot暂停更新。

设计模式里的多态,答疑

dab8ac6ba9674c5110cd20e7e3debf19_b
>在java程序设计这门课中,我读的书上写到多态有两种形式,1.一个类中,具
>有相同的方法名,但参数列表不同,称这种形式为静态多态性,又叫重载。
>2.子类与父类拥有相同的属性或方法,称为动态多态性,又叫覆盖。重载和覆
>盖的区别在于,重载在编译阶段就可以知道调用哪一个方法,而覆盖在运行阶
>段才能知道调用的是子类还是父类的方法。

我没听说过动态多态、静态多态(注:查了一下,这两个术语是确实存在的,我学业不精没记住),除此以外,上面提到的内容都是对的。

overload, override.

>设计模式中提到的动态绑定下的多态我觉得属于覆盖这种。

对。

设计模式中所有的方法都基于 OO(似乎除了工厂方法),而 overload不是OO。

>文中提到 彼此有相同接口的对象 是指两个子类继承自一个父类,然后两个子
>类所实例化的对象可以相互替换?

可以。

>设计模式第十页提到:动态绑定允许你在运行时刻彼此替换有相同接口的对象。这种可替换性就称为多态。这句我不是很理解。

1. 多态,是设计模式这种OO设计手段所依赖的最核心的OO编程技术。

所以,你找到核心了。

2. 假设用C++实现。

动物类 有个方法 吃(),那么动物类的子类 鹿类 和 虎类 都可以有 吃()方法,
为方便起见假设无参或参数类型相同。

鹿类 和 虎类 可以分别实现 吃,那么就覆盖了动物类的吃。又,特别的,如果
动物类是个抽象类,吃就只是声明而没有实现。在运行时,如下。

  1. 动物类 ani*  a ;
  2. switch (用户输入)
  3. {
  4. case 虎:
  5.     a = new 虎();
  6.     a -> 吃(); //是虎在吃,调用的是 虎::吃()
  7.     break;
  8. case 鹿:
  9.     a = new 鹿();
  10.     a -> 吃(); //是鹿在吃,调用的是 鹿::吃()
  11.     break;
  12. }
  13. delete a;

以上代码中,考虑到用户输入在编译时未知,因此调用鹿::吃()还是虎::吃(),
是在运行时决定的。

这就是"动态绑定允许你在运行时刻彼此替换有相同接口的对象。这种可替换性
就称为多态。"这不是设计模式的内容,而是设计模式应用了OOP中的多态。

3. 如果用JAVA实现多态,可以不用继承,而使用接口。

某类a、类b实现了接口i,在多态的角度 可以把 类a、类b 视为子类,把 接口i
视为超类,类a、类b 的方法eatable () 实现 (或覆盖)了接口i中声明的方法
。只有在运行时才知道,接口i的实例是a类类型还是b类类型,eatable ()方法
的调用到底是a.eatable ()还是 b.eatable ()。总之运行时不会调用i.eatable
(),因为它是纯抽象的。

4. 在设计模式中,大量使用了多态,并且基类是抽象类,只有方法的声明,不
做实现。正是因为在运行时决定子类 (及其方法) ,带来了设计模式的灵活性。

f914b7e599ee58fc1c5934ca45f2154c_b

fcd12317f2f738721fd3b110128c3cbd_b

> 老师:求助解答。设计模式第十页提到:动态绑定允许你在运行时刻彼此替
> 换有相同接口的对象。这种可替换性就称为多态。这句我不是很理解。在
> java程序设计这门课中,我读的书上写到多态有两种形式,1.一个类中,
> 具有相同的方法名,但参数列表不同,称这种形式为静态多态性,又叫重
> 载。2.子类与父类拥有相同的属性或方法,称为动态多态性,又叫覆盖。
> 重载和覆盖的区别在于,重载在编译阶段就可以知道调用哪一个方法,而
> 覆盖在运行阶段才能知道调用的是子类还是父类的方法。设计模式中提到
> 的动态绑定下的多态我觉得属于覆盖这种。文中提到 彼此有相同接口的对
> 象 是指两个子类继承自一个父类,然后两个子类所实例化的对象可以相互
> 替换?
>
>
> 发自ZR的小米手机

------------------------------------------------------------

博客会手工同步到以下地址:

[zhuanlan.zhihu.com/youn]

[杨贵福 的专栏]

[giftdotyoung.blogspot.com] 我本人也访问不到了,blogspot暂停更新。

背单词,及工程原理在其中的应用

d958c728b077a1fc67bc88d6d97aeb20_b
1. 我试过的背单词方法大学期间,我的英语一直很差,直到倒数第二次才通过四级,没有兴趣也没有机会尝试六级。不到十年前党员学习的时候,赵老师曾经评价,像小杨这样的年轻同志还挺愿意学习的,等班车还背单词。那既不是为了出国,也不是为了考研,而是为了补课。读英文文献的时候因为单词量不足、词义记得不准确而多花费很多时间。

我尝试了你们听说过的大部分提高词汇量的方法,都有效,效力不一。

比如在阅读中学习。高中时英语李铁钢老师告诉我,不要那么用功,应该多阅读,他借给我弗兰肯斯坦等缩写本。那是英语专业一年级的课外阅读材料,他如此器重 和帮助我,现在想想,他老人家让我感动得流泪。李老师说,如果这个单词重要并且重复出现,影响你阅读了,你就可以查字典;如果这个单词不认识,但是不影响 阅读,不要去管它。我这样认识了"tobacco"这个词,因为有个坏蛋总是点燃它、叼着它。我的单词量中,有不少是阅读这一来源,除了计算机专业书籍 外,主要阅读游戏手册和游戏本身,比如文明、帝国时代。所以,考试的时候非常痛苦,因为出题人感兴趣的领域主要是日常生活、环境保护、人物传记、时事评 论,这些我汉语能读但是不感兴趣的内容。

我当年还听过新东方的词汇课程录音,俞敏洪、赵丽,没听过李笑来的。赵丽老师从好几个角度讲同一个单词,谐音的、口诀的、拆字根的、讲故事的。我现在还记得"只有rim是边缘""扑灭了光,就陷入困境",还有吴三桂怎么满面红光看陈圆圆羞涩。

我也背过单词书,效果一般。有些人反对背单词,我反对这一点。不同于英美人直接靠单纯的阅读和对话,我们缺乏大量的这种沉浸式的环境。背单词固然不能了解用法、缺少组词造句的能力、会学死,但是这些并非不可以后来再补。

我小学的时候没有足够的课外书看,中午吃饭的时候最常翻的是新华字典。三四年级的时候,字典里还有很多不认识的字,就看它的解释和读音,如果解释里有不认识的字,就再去查解释里的字。这方法很笨,但是也有效果。

笨的方法,也比等待要好。

2. 回顾,推荐1,基本原理

我有两次明显能感觉到的单词量增长,一次是考研之前。当时也试过能见到的各种软件,还有星火背单词之类的。其中有个软件帮助了我,名字叫做 极点单词。不知道这软件现在是否还活着。

极点单词界面粗糙,就像初学VB做出来的。我记不清楚了,到底是极点单词只有这么一个功能,还是我只用了这个功能,正是这个独特的功能帮助了我。

给定英语单词,要求选择汉语意思。不考察拼写,也不需要读音,也不考虑汉语到英语。只有英译汉。

用极点单词,我背得飞快,很快就把考研单词捋了一遍。有的同学可能会质疑,如果只用英译汉,那读音/听力、汉译英、作文、拼写,我怎么办呢。答案是放弃。 我当时的英语水平,只想过线,没有能力也不敢奢望考多高分。而且一个事实上是,拼写、作文、汉译英所需要的 拼写、汉英 能力,并不需要那~么~大的单词量。熟练使用的,能拼写能汉译英的,远远小于总的单词量。大部分单词,只要你见到它能认识,就行了,不需要会写。在阅读英 文文献时,长的单词我曾经长期只看前三个字母,足够区分。

再认和再现,在记忆上的负担差别巨大。再认只需要在选项里挑出正确答案,再现则需要在毫无提示的情况下给出答案。1.有个单词,imp....,它是分 析、设计、实现、部署中的哪个呢。这是再认。分析是an,设计是des,实现是imp,部署是dep。2.有个单词,实现,你还记得怎么拼写 么,implementation。这是再现。

没有能力、没有时间、没有紧迫的必要性的时候,工程上需要妥协,功利上需要权衡。群论、lamda、OO,那都是很好很好的,只是现在写代码的时候还是要用C/C#、面向过程。万世基业岂能一蹴而就。

我猜有同学正雄纠纠准备站起来跟我争辩,"更精确的才是更好的。"好吧,我们学过一些人物的名字,比如 尼古拉·阿列克谢耶维奇·奥斯特洛夫斯基,马克西姆·高尔基,弗拉基米尔·伊里奇·列宁,你是不是看到最后一小节才"再认"出他们是谁,虽然你以前也看过 全名。还有 卓娅·克斯莫捷米扬斯卡娅,是不是让你感觉好一点。这些人名,除了托尔斯泰有不止一个容易混以外,只记那一段常用的,足够再认。即使托尔斯泰这样容易混 的,我们也会想招偷懒。一个托氏名叫列夫·托尔斯泰,其实他的全名是 列夫·尼古拉耶维奇·托尔斯泰;另一个托氏名叫 阿·托尔斯泰,其实他的全名是 阿列克谢·尼古拉耶维奇·托尔斯泰。

如上。这个例子告诉我们,只达到再认并且活下去这种事,我们早就做过了,并非从背单词才开始的。不妨继续这样做。

3. 推荐2

如果你受上面提到的 对付 原则,那么下面这个软件推荐适用于你。

我最近一个多月尝试了背单词软件 百词斩,在苹果和安卓系统上都有。我不认识百词斩的作者和公司,也没有利益相关。特此声明。

我在百词斩上背单词49天,完成了托福、托福核心、GRE3000。
8394e0013e85852889d3443b34ecb855_b
1)达到的程度,见到能认识,有的单词需要辅以上下文;不会拼写;有的听读音能在认识,需要辅助以上下文。

2)单词量11000左右,有其他两个独立的测试为证。从5000至8000左右上升到这些。

百词斩说:
3fa97bc19e89ef6d0be9f7af725efc86_b
qsbdc.com说:
f0244164db34f060701530448cf8da37_b
扇贝说:
f8263e893845575b277c9d001d521cca_b
3)用到中间的时候,百词斩搞了个背单词得积分 (积分包邮和减价1元对我没啥用),我积分9900,也就是说背了这么多单词。

提到这些,是希望你能了解到,我依据自己的经验而做出评价。

有的同学看到"见到能认识""不会拼写"的时候,可能会喊,那也能叫认识么。有此感慨的,请复习上一节"回顾,推荐1,基本原理",尤其关于妥协和再认的一段。

除了 *仅*英译汉,四选一 以外,百词斩有以下特性,对我背单词有正面作用,列举出来,供你参考。重申,*仅*英译汉,四选一,我认为这是最宝贵的特性。

列举特性如下。

1) 图片、字根、故事、语气、读音

每个词都有配图。有的词有字根拆分,有所帮助。所有的词都有造句,这有助于了解应用的场景,而且相当于一个小故事。小故事是赵丽方法的第三种 (?)。句子和词的朗读都是有语气的,活人读的。有意思的是,凡是男主角的故事,都是女士读,凡是女主角的故事都是男士读。那位男士会模仿各种声音,跟口 技一样,挺好玩的。每个词都有读音,不是音标,而是会读出来,有助于纠正我这样原本记错的。
c509c39d98ab4cbdec6c7b21f2f8c288_b
以上是英译汉,四个选项。按“提示”进入下图。
38411de340a1f7aaedb7979a6f94ae33_b
图片和句子设计得都挺夸张的,中文符合现在网络时尚的特性。如此符合,以至于在我的角度看来略微低俗。不过记忆术告诉我们,低俗有利于记忆。

多种媒体结合展示,据说,对学习有明确的正面促进效果。

2)比赛。随机约基本能约到人 (本地约基本白扯) ,我一般会打到胜比输多一场,例如7:6,然后结束。
af93223eb021c0094615e98e3b2eb559_b

571fd9ff79895f2100a2c5678010063d_b

cb2486bab733c31fd2b591f4692200ad_b

3)已学单词/未学单词,错的次数
0924bbd1245068036be88c578a5c3849_b
给出了已学单词/未学单词/单词总量,还有每个单词错的次数。这一部分仍嫌简单粗糙。

4)换一本书学的时候,可以导入已学。但是似乎导入的不全。

5)下载离线包。每本书100多M,然后可以离线了。

6)定制,结合动画片和文化背景。根据你的文化背景,圣斗士、破产女孩、生活大爆炸、西游记、柯南、犬夜叉、机器猫来展示图片。

7)加量练习: 听音选词

每天完成计划的任务 (类似10分钟至1小时这样,可以自己调整) 以后,可以加量练习,其中之一是听音选词。这是三星难度,对我挺难的。还有拼写、搭配、在句子里你发音填空系统识别,超出我的能力,无法评论。

8)好创意,但是缺好的程序员

切换字典的时候,需要按确认,这让我困惑;如果不切换词典,不能自动提醒背单词任务,这也是奇怪的设定。切换词典的时候状态机 (按钮、进度、计划) 会有混乱,我甚至怀疑这段没用用状态机实现。个别单词读单小,似乎声音强度的归一化不是软件而是人工的。

9)社群文化: 淘宝,卖笔记本什么。也许吧,也许社群文化能促进学习...和销量。

4. 致谢

谢谢你,百词斩的作者。

一并感谢极点单词的作者。

感谢李铁钢老师和赵丽老师。
257bd44f056b6f8fe74f75a1743668fc_b
-------

此博客会手工同步到以下地址:

[http://zhuanlan.zhihu.com/younggift]

[http://blog.csdn.net/younggift]

[http://giftdotyoung.blogspot.com] 我本人也访问不到了,blogspot暂停更新。

代数结构 笔记, graphviz绘制

19dcc110abbe47a27cb6706b83f65752_b

狂欢夜读离散数学,手绘概念关系笔记,第二天用graphviz重画一遍。

1. 手绘

b12b26a05ea082fa1948dbd9a1ba7c06_b

2. graphviz的效果

982e400d23a521c70bab416a8da3df41_b

3. 所执行命令行如下:
~ $ c:/Program\ Files/Graphviz2.38/bin/dot.exe -Tpng -o group.png group.dot

输入文件是 group.dot,输出是 group.png。

是在emacs的eshell中执行的,如果你的环境不同或者graphviz路径不同,命令可能会略有变化。

4. group.dot 文件源代码如下:

digraph G
{
//rankdir=LR;
graph [label="代数结构\n根据关伟洲老师\l《离散数学》\l第四篇 代数结构\l20151227 by Young", fontname="FangSong", fontsize=18]
node [fontname="FangSong", shape=box];
edge [fontname="FangSong"];

subgraph cluster_sys {
graph [label="", labelloc=t; labeljust=center, fontname="FangSong", fontsize=18]
代数系统;
}

subgraph cluster_group {
graph [label="群论", labelloc=t; labeljust=center, fontname="FangSong", fontsize=18]
"广群" [label="广群\l<A,*>\l*在A上封闭"];
"群核" [label=<σ-1(e'),当
G和G'同态映射σ
e'是G的幺元
>];
代数系统-> 广群 [label="封闭的"];
广群 -> 半群 [label="可结合"];
半群 -> 子半群;
半群 -> "幺半群/独异点" [label="有幺元"];
"幺半群/独异点" -> 群 [label="有逆元"];
群 -> 子群;
群 -> "交换群/阿贝尔群" [label="可交换"];
群 -> 循环群 [label="G=(a)"];
群 -> 群核 [style="dashed"];
群 -> "左陪集,右陪集" [label="aH={a*h|h∈H }"];
"左陪集,右陪集" -> "右商集,左商集" [label="{Ha|a∈G}"];
"右商集,左商集" -> "正规子集/不变子集" [label="aH=Ha"];
"交换群/阿贝尔群" -> 变换群 [label="<F(A),○>的子群"];
变换群 -> 置换群 [label="A有限"];
}

subgraph cluster_ring {
graph [label="环论", labelloc=t; labeljust=center, fontname="FangSong", fontsize=18]
环 [label="环\l<R,+ ,·>"];

代数系统 -> 环 [label="<R,+ >是交换群,<R,·>是半群,·对+ 分配律"];
环 -> 子环;
环 -> 交换环;
环 -> 含幺环;
环 -> "无零因子环/消去环";
交换环 -> 整环;
"无零因子环/消去环" -> 整环;
环 -> 域 [label="R-{0}对·作成交换群"];
{
rank=same "体/除环", 域;
}
环 -> "体/除环" [label="R-{0}对·作成群"];
"体/除环" -> 域 [label="交换体"];
环 -> "理想子环/理想" [label=<aN是N的子集 并且 Na是N的子集>];
"理想子环/理想" -> "商环/剩余环";
"理想子环/理想" -> 主理想 [label="含幺交换,aR"];
"理想子环/理想" -> 单纯环 [label="{0},R"];
"理想子环/理想" -> 素理想;
"理想子环/理想" -> 极大理想;
环核 [label=<σ-1(0')>];
环 -> 环核 [style=dashed];
}

subgraph cluster_lattice {
graph [label="格论", labelloc=t; labeljust=center, fontname="FangSong", fontsize=18]
布尔代数 [lable="布尔代数", fontcolor=red];
//lattice [label="",width=.01,style=invis];
//代数系统 -> lattice;
//lattice -> "代数格/偏序格" [label="<L,⊕,⊙>\l交换同,结合,吸收\la⊕b=sup{a,b},a⊙b=inf{a,b}\l原文⊙写作圈里叉\l"];
代数系统 -> "代数格/偏序格" [label="<L,⊕,⊙>\l交换同,结合,吸收\la⊕b=sup{a,b},a⊙b=inf{a,b}\l原文⊙写作圈里叉\l"];
"代数格/偏序格" -> 子格;
"代数格/偏序格" -> 对偶格;
"代数格/偏序格" -> "有界格,有余格,分配格,模格";
"有界格,有余格,分配格,模格" -> 布尔代数 [label="有余分配格"];
布尔代数 -> "n维有限布尔代数\l<B,+ ,·, ̄,0,1>";
}

subgraph cluster_term {
graph [label="术语"];
整环 -> a [style=invis];

a [label="交换\l结合\l等幂\l分配\l吸收\l左/右幺元e\l左/右零元θ\l左/右逆元 x*y=y*x=e\l"];
b [label="f(x*y)=f(x)○f(y)\l同态\l同构\l自同态\l自同构\l同余关系\l保序映射\l"];
}

}

d7b41bdfb519a592e7b16a8724423434_b

------------------------------------------------------------

博客会手工同步到以下地址:

[http://zhuanlan.zhihu.com/younggift]

[http://blog.csdn.net/younggift]

[http://giftdotyoung.blogspot.com] 我本人也访问不到了,blogspot暂停更新。

完美爬犁

0d7f48d66fb93ada29ad6cd84209b568_b
爬犁,南方遇到飘小雪花就会尖叫的同学可能没见过,我先解释一下。深刻了解爬犁工作原理的同学,请跳过下一段。

爬犁,小学的地理还是语文课本提到,我们的祖国地大物博,北方已经白雪飘飘,南方还如何如何。北方白雪之上,据说人们用爬犁作为交通工具,用马拉或狗拉, 哈尔滨的太阳岛上据说还有风帆驱动的,我全没见过。我从小见过的爬犁都是家长用木头做的,下面绑铁丝减小摩擦力,有的前面有头,据说转向更灵活,虽然我切 身体会并没有用。从大坡之上,或坐或卧,呼啸而下。然后再拉到山上去,如此反复,如西绪弗斯而乐此不疲。

以上是爬犁简介,如果你跳过了没啥影响,我只是为南方同学勾勒了北方冬天的美好生活,美好的那部分。下面故事正式开始。

我去年为二猫做了个爬犁,耗时大概4个小时。她乐颠颠地参与画图纸、提问题、装饰,并命名为红绳号。拉去河边,我跟她从堤坝上风驰电掣般滑下去,然后发朋友圈显摆。
e5a49aa7c81b6d0ec1645f6056412be3_b
朋友们回应很积极,大多是改进意见。归纳大体如下:

1. 下面连铁丝都没绑,能滑起来么。

2. 我从小就做这个,个个都比你这个好多了,改天教你。

3. 太小了吧,能坐下吗,屁股都得掉下去吧。

4. 都没有头,怎么转弯。

5. 有钎子么,在平地上怎么滑。

6. 头上的绳子太细了吧,拉着孩子走的时候绳子会断吧。

7. 现在有的是塑料的爬犁,比这个精致多了。

8. 你那也算爬犁么。

我统一答复: 你行你上。大家交互甚欢,哈哈一片。一年过去了,我和二猫又翻出了红绳号,从河堤上滑下去,跟去年一样风驰电掣的,然后拖着爬犁连滚带爬再杀上去。那些开着善意玩笑的指导者们,仍然没有做出他们自己的完美爬犁来。他们没有享受到这么糟糕的爬犁带来的快乐。

完美爬犁这个故事告诉我们,行乐要及时,不要等到某个特别的时刻或事件,或者必须使用优雅的代码、完美的模型。

往极端了说,如果没有木板,没有钉子,没有绳子,神人也做不出爬犁的情况下,也不应该等待,而是穿得厚厚的扎上护腰和护膝,用楚留滑的方式从河堤上冲下去。要么放弃,要么开始,绝不等待。

项目一旦启动,选定框架、选定语言、选定人员和时间地点,就应该立即启动。简而言之,一旦启动就立即启动。更好的语言,更好的模型,更好的抽象,都留到下一个项目或者下一轮迭代再发挥威力。择善而从,从一而终,有犹豫的时间,蜀之鄙的贫者就到南海又回来了。

当年我带学生做"项目管理"课程,小班授课,选定内容是做俄罗斯方块。我提问,大家有没有想到,小块一边往下掉,同时还要响应用户的指令旋转移动,这应该 怎么实现呢。一位林同学说,那一定是用 多线程。我继续问,那么帝国时代里面有好几十战士来回跑和对砍,如果用多线程如何实现呢,用好几十个线程么?

当年有一种游戏机叫做红白机,国产版好的是小霸王,用电视作为显示器,用手柄控制。那种游戏机里就有俄罗斯方块,甚至手柄大小的掌上游戏机里也有俄罗斯方块。那些机器里连操作系统都没有,也没有多线程,是怎么实现同时满足多个动作这一要求的呢?

工程师自我办法。办法就是: 只用你手头现有的知识,一样能实现各种效果。所以,这个故事不是告诉我们应该如何掌握新的更好的技巧、方法、知识的,像有些同学以为的那样,而是 如何应用你现在已经掌握的技术。

所以,我对每一个希望跟我一起做项目的同学说,如果你期待能在我这里学到任何知识,那么这个希望都会落空,你什么知识也学不到。有些技能,只有做,你才能 掌握,比如"如何应用你现在已经掌握的技术"。汉字就那些,你也认识我也认识,为什么有些人能写出文章;API一共就那些,你也读过我也读过,为什么有些 人能编出程序。不是因为会写的人读了某本你没有读过的书,而是他把你也读过的书里的知识 实践了 很多次,然后就会了。

邹欣老师在《构建之法》中说,教室如同健身房,教师如同教练,学生如同学员。如果你不真操实干地抬起哑铃,教练喊破喉咙,他的肌肉也跑不到你的身上。

秘诀是什么?就是没有秘诀。去做,然后你自然明白。。

当年的工程师怎么实现多线程的效果呢?看看windwos api程序设计的demo,无他,就是轮询。在每次循环里 get/peek message,然后 translate message,然后dispatch message。然后有一个个消息响应函数,被调用以后就干什么什么事,要求,这些函数占用CPU时间都不能太长。为什么,因为要回到循环去。 windows的消息循环,或者说,windows程序带有GUI的有菜单按钮能画图的,不过就是死循环,而且要求程序员不要在循环中执行太多指令。

借用类似这样的机制,我们就能猜到,在俄罗斯方块中,我们需要这样一种机制,能够获取用户输入并且不阻塞程序继续执行。我们需要找到这样的异步读取机制。多线程并非必需,并非唯一。

当年有个游戏叫做 Doom II,红遍全球。Doom眩晕就是用它命名的。这是个第一人称视角游戏 (不是第一个,第一个是同一公司 id soft的刺杀希特勒),屏幕下面有一双手持枪射击。这双手在没有三维建模,没有三维重建,没有光晕渲染的时候是如何画出来的呢?

这双手是两位主力开发者之一的手的照片,改了色调和分辨率什么的以后,贴图在屏幕上的。

简单粗暴,非常有效。更多的特征,更深刻和更精致的原理都留到以后,现在只要足够好,不要更好。

关同学告诉我,她在化学学院见到某位同学,为了做量子化学计算,居然写了个40重循环的程序。你读了这么多年书,见过40重循环的程序么,能想像40重循环缩进多远么。当然,也许这么同学的循环根本没有缩进。

当然了,使用更高深的学问,比如jump-table啦,比如尾递归啦,比如啥啥啦,我们当然可以避免40重循环以及可能带来的潜在问题和开发难度,但是 你导师要求你下个月就交报告,你怎么办。现学来不及,一个月写40重循环足够。当然,如果你想到是QQ求同学解决,不在讨论范围内,我们只谈你自己如何完 成任务,变身代理商的不算。

有同学会有这样的体会,我写了,就是糙快猛的路子,程序跑起来了,但是老师又说"用某某方法会更好",是不是白干了。

当然不是。老师又说"用某某方法会更好",是在你用现有知识整出来的情况下,才能学到的优秀指导建议。如果你没有用现有知识实现,导师连这句貌似有否定意味的评论都不会有,他会放弃你。

一旦工程开启是,此刻,就用你现在掌握的技能干,不学习任何新知识。所有新知识另开线程学习。没有人会为你拥有知识而付钱,只会为你(运用知识)解决问题 而付钱。你猜什么方法能行白扯,必须亲自操刀上阵干出来;或者你成为技术领导,要求别人干,那是很多年以后的事了,而且你得能活到那时候。

所以,先干起来,然后才有谋求批评指正的可能,然后才有进步。如果没有第一步,后面的就都没有。世界上最激烈的反对不是表达反对意见,而是淡漠。如果你不表现出弱点,老师就连纠正的机会都没有。

先糙快猛做出来,如果你真的有更优秀的模型,那么用新的模型重做一次。不要期待第一次就使用最优秀最完美的模型。

《囚徒健身》告诉我们,要打好前面的基础步骤,不要过早觊觎后面的大招;而且,前面的基础训练,即使没有更快地让你达成后面的目标,也是有帮助的;最关键的是,后面的不是目标,过程本身才是。学习 如何应用现有的知识 也是一样,过程才是最重要的。

看看下面的问题。

1. 打印10行怎么做,我还没有学会循环。我还没有学好循环/我想用递归/我想既不用递归也不用循环。

答案是: printf ("a\n");printf ("a\n");printf ("a\n");printf ("a\n");printf ("a\n");printf ("a\n");printf ("a\n");printf ("a\n");printf ("a\n");printf ("a\n");

2. 保存四则运算的式子,据说逆波兰最好了,但是我的编译原理学得一团糟怎么办啊。

答案是:不用逆波兰。比如保存字符串。

3. 四则运算的式子求值,老师说用二叉树求值最适合了,我不会,怎么办。答案是:不用二叉树。即使带有括号,三个数做四则运算一共几种可能,这是高中时的排列组合问题(数字电路或离散数学对求解总的可能性有帮助,不必须) 。穷举所有可能,switch-case。

时间,是工程目标中最重要的元素之一。我们考虑 成本 (人力、资源,时间) 、时间 (截止日期) 、范围、质量。截止日期在英文中是 dead line,原意是监狱外面不可跨越的边界,囚犯只要跨越就会被不问而击毙。要有这样的觉悟,只要越越截止日期,就会死。如果这样想,就会用各种脏的丑的代 码先解决了问题,然后再优雅。

过早优化,是万恶之源。只有被调用了三次的 (真正地被调用了,甚至不是预计),再考虑以重用为目的抽象。只有实现了以后 (或者真的很牛了以后) ,再用大招解决。

勇猛精进,不要犹豫。时间至关重要。不少人遗憾荆柯同学当年要是等那位高人而不是带秦舞阳一起动手就好了,但是,等到那位高手就能成功么,是不是那个时候秦军都已经攻克燕国了呢?

有的同学会问,那如果简单方法失败了呢?那就是命中该死,因为项目需要的必备的知识你以前没学会。排除现学现用这种可能吧。

有的同学会追问,那老师要进度要结果怎么办?

有一部电影,韩国的《刺客》,里面一位女士讲到他们这些以朝鲜独立为目标的人在满洲抗日,说了两段话。她说,在满洲房子坏了我们也不修,因为胜利了我们就 要回朝鲜了,为什么要修呢。事实上,从1910年日本占领朝鲜到1945年朝鲜光复,他们等待了35年,年青人变成垂垂老矣这么长的时间。她说,我们并不 知道什么时候能够胜利,我们甚至不确认能够胜利,我们斗争,不是为了得到胜利,而是告诉人们,我们没有屈服。

如果老师要结果,就用你以简单方法所写的失败的代码还有消耗的大量时间 (不包括焦虑,只包括思考和键入) 交给他。由于你的努力、由于你的态度,你不见得会得到成绩,但是你会得到过程中的收获,还有未来。

这样,你就掌握了应用 现有知识 的能力。
2f027119545834d5aa83b9e80e6af528_b
------------------------------------------------------------

博客会手工同步到以下地址:

[http://zhuanlan.zhihu.com/younggift]

[http://blog.csdn.net/younggift]

[http://giftdotyoung.blogspot.com] 我本人也访问不到了,blogspot暂停更新。