不能想象没有书的世界 | 《路上观察学入门》

如果外星人登陆地球的话,做的大概也就是这些事情吧。 你有多久没有在路上细细观察一番了? 暂停耳机里播放的音乐,卸下沉重的背包,只需要儿童般纯真的目光,怀揣着轻松和自由,在街道上漫步。 哦~这里有两个垃圾桶,旁边靠着普普通通的电线杆。往前走两步,左面是条小河,河边停靠着一只破旧的小船,以前可从来没有注意过。再往前走,路边是片工地,所以附近的马路上都有些尘土,甚至还有狗狗路过时踩出的脚印。就这样,眼睛不停地在扫描周围的角角落落,每一处都显得新奇。 踏上从未驻足过的阶梯,在小巷子里来回穿梭,运气好的话,还能发现不少有趣的东西。 建筑,标牌,等等,你所看到的物件自然有它的实际用途,但是因为某些原因,会出现实用性之外的面向。阶梯本是用来供人上下方便,而这个纯粹阶梯,则“纯粹”无用。寻觅并观察它们,也就带来了“发现”的乐趣。 观看自然是观察的乐趣所在,那又何谓路上观察学? 既然是做学问,就得秉持科学的态度,要对观察的物件做调查和记录。可以手绘,或是拍摄照片,带来的感觉也不一样。 书中摘录了不少奇妙的观察体验。收集城市里的井盖,尾随狗狗发现全新的视角,像对待鸟儿和昆虫一样观察高中女生制服,还总结出了《东京高中女生制服图鉴》,又或者是一本正经地成立侦探团,潜入各种建筑内部探查一番。虽然动机和过程听起来让人不禁大笑,但是严谨的态度又令人肃然起敬,这样的对比也别有乐趣。 观察,记录,时间也被一次次地定格。 电线杆也好,烟囱也好,像这样令人熟悉的景物正在逐渐消失,整个世界渐渐改变为由埋在地下的电力所支配,只留下制度与系统。我觉得这样很可怕。所以要回头看:属于我们时代的起点究竟是什么?于是就会注意到铸铁制的井盖、博物画或儿童的科学。 周遭的世界,每一天都在发生着变化,科技在进步,矮墙变成了高楼。小时候可以在田边和荒地里自由地探索和冒险,而现在的小孩子,更多的时间,只能转移到室内玩耍,然后,“梦想完全被吞噬于无聊的日常生活和窠臼式的思考中”。 不论是为了体验观察的乐趣,还是记录时光的悄悄流逝,多到路上去走一走,看一看吧。如有不便,不妨先翻开这本《路上观察学入门》,试着感受一下其中奥妙。 合上书,立刻就想起,自己在路上所记录的一些有趣观察。 如果你也有记录一些奇妙瞬间,欢迎分享给我哦 ([email protected]),我们可以一起办个“展”。 草坪上突然出现的传送门 好吃的弄堂 假装是石狮子的柯基 在门口成双成对唠家常的滑板车 打开门满是落叶的空屋 今年过年带点特产回家 二十年面面面面馆 银河投影在投影仪上 挂在阳台晾干的机车 请给我一个归宿 育碧特色:穿模的消防栓 老凡尔赛了

April 23, 2021

不能想象没有书的世界 | The Curious Incident of the Dog in the Night-time

这是一本很可爱的英文小说。 去年的八月,多抓鱼上海店还在施工中,却悄悄地开启了快闪活动。店里闷热又潮湿,我在书丛中晃悠了几圈,抓住了这本画有卡通封面的小书。 故事发生在一个深夜,邻居家一只名叫 Wellington 的贵宾犬倒在了草坪上,它被人杀害了。故事的主人公,15 岁的 Christopher,想要找到凶手,发掘这个意外的真相,于是开始了自己的调查和冒险。 Christopher 是个很聪明的孩子。他喜欢科学,抬头看星星的时候,知道星星离地球很远,有些又飞的很快,以至于人们永远看不到那些光亮。他数学很好,这一本调查日记的每一章,都是用质数命名的。他做事很讲逻辑,思维缜密,还会根据路上车子的颜色来判断今天是不是个 Good Day。 但是 Christopher 患有自闭症。不开心的时候不愿意吃饭,也不会和人讲话。他讨厌别人碰他的手和肩膀,生气的时候会大喊大叫,甚至挥舞起口袋里常备的瑞士军刀。就像是《黑客与画家》里描述的“书呆子”,聪明,但不受人欢迎。 这不是一本简单的儿童读物。 随着冒险的展开,Christopher 闯入了大人的世界。爸爸妈妈为工作发愁,为婚姻发生争吵,有时候坐在楼梯口沉默不语,或是偷偷落泪,成年人的生活总是很麻烦。他们互相指责,但又能责怪谁呢?或许像是蛋堡说的,“因为我们都有问题”。 当然故事的最后, Christopher 会有光明的未来,因为聪明勇敢的他找到了狗狗被杀害的真相,数学考试拿了 A,期间还独自一人搭乘火车去伦敦找妈妈。做到这一切后,他有能力做到任何事情。 而对于我,这是我看完的第一本英文小说,增加了不少英文阅读的自信。自然,也会有下一本。

April 13, 2021

英语学习回顾 - Stage Two

距离上一篇 英语学习回顾 - Stage One 已经过去整整两个月了。 之前忘了提,在认真学英语之前,我的英语水平是大学英语四级裸考 475 分,考六级时看到作文题目就开始趴着睡觉,遂放弃。工作和生活中偶尔会翻看英文资料,但是阅读并不流畅,至于发音和听力… 众所周知,在语言学习里,听说读写,其中某一方面比较好,根本就是个谎言。 所以如果我能学好英语的话,你一定也可以。当然我们的目标是,简单高效!这就需要有针对性的学习策略,我也在积极探索和调整优化,接下来就和你分享一下,近期我的学习经历。 在这一新阶段内,我还是保持了每日的英语学习,一开始是背常用 7000 词,以每天 60 个新单词的速度推进。就这样持续了 20 天左右,按当时的进度,还剩 2/3 的新单词,背完需要两个月。日常也有浏览一些英文文章,粗略评估了一下,感觉单词的命中率并不高,两个月的时间投入很不划算。 期间我在 Youtube 上浏览了不少别人分享的英语学习经验,其中 Ella 的视频 中提到了一门语言中最基本的单词大概只有 3、4 千个。于是调整了一下策略,暂停学习常用 7000 的新单词,将单词源切换成了朗文 3024 词。先快速标记 3024 词中不太有印象的陌生词,同时复习之前的词汇。 使用 Anki 花了一周的时间完成朗文 3024 词的标记后,发现只有 20%不到的生词。以这个词汇量,生词基本不会影响对句子主要意义的理解,而且也多次遇到了,单词在不同上下文语境中,有不同于词汇表的含义。所以,索性直接放弃被动地背单词,all in 主动学习。 在进入主动学习之前,我对语法知识的整体框架还不是很清晰,也会影响自己对长难句的理解。就先过了一遍英语兔的 语法体系讲解,整理了一份思维导图,梳理了一下语法的各个知识点,也方便之后可以做针对性地深入学习。 关于主动学习的方式,目前主要是以下几块: 阅读 还是以兴趣为主,阅读自己感兴趣、想了解的内容。遇到生词也没有关系,只要不影响理解句子、文章的主要含义即可。在浏览器上使用英英的查词插件来理解生词,我比较懒,没有刻意去记忆,等他出现的多了,再笨的小脑瓜也会记得的,对吧? 3 月初,我订阅了互联网作家 David Perell 的 50 天写作小课堂,每天都会收到一封他的邮件,学习写作相关的知识,同时也是非常棒的英文阅读材料,他的 个人网站 上也有很多 blog 可以学习。当然还有订阅其他英文内容的 newsletter,P.S. 我自己的 newsletter: Sunday Musings ,创作想法之初就是源自于 David Perell 的 Monday Musings,感兴趣的话也欢迎你订阅哦! 最近从书箱里翻出了一本可爱的英文小说《The Curious Incident of The Dog in The Night-Time》,目前正在阅读。...

April 8, 2021

不能想象没有书的世界

“不能想象没有书的世界” 2013 年的春天,游戏制作人(我最喜欢的)小岛秀夫写了一本《我所爱着的 MEME 们》,在书的开头,写着上面这句话。“而在 6 年之后的现在,这句话仍然不变”,他在新书《创作的基因》的序章里这样回应。 时间真的过的很快。 17 年刚毕业的时候,朋友送了我一本《穷查理宝典》,大概是体会到了阅读和思考的乐趣,于是在 18 年给自己定下了一个小目标:一年看 20 本书。幸运的是,最后这个目标成功达成了,但是在最后的一两个月,为了完成这个承诺,有点囫囵吞枣地翻阅了几本。所以在这之后,也不再给自己定类似的 kpi,而是随性地保持阅读的习惯,有兴致就每天翻看,累了就多喝凉水。 翻开一本新书,都会拍上一张照打个卡,从 1 到 20,不知不觉中,数字暂时停留在了 47。 我是如何挑书的呢? 其实就是两个字,“随缘”。多半是出于好奇,又或许是因为封面好看,也有些是来自很重要的朋友的推荐(所以如果有喜欢的书,记得分享给我)。 我好像有点固执的,几乎只看纸质书,而且翻开了就一定要看完。遇到感兴趣的书的时候,总是兴致匆匆,在多抓鱼上抢书锁定,凑几本包邮后立马下单,然后发现书箱里还没看的书越堆越高。 我会在 OneNote 上记笔记,摘抄引起我注意和思考的内容,像是给这本书标上自己的索引,方便日后回来查阅。但是时间久了,就容易忘记当时阅读的感受,只剩下笔记里干巴巴的一些引用,有的甚至一片空白。 于是开始写读书笔记,想要记录阅读后完整的体验,和一些想要分享的思考。《如何阅读一本书》里提到,看书的时候,要问问自己四个问题:这本书是讲什么的?怎么讲的?讲的好吗?和我有什么关系?看完书后,顺着“哲学四问”,在读书笔记里写下答案,也算是没有白白读过吧。 我从这些书里得到了什么? 看完《自下而上》会认为一个人改变不了什么,但是看完《人类群星闪耀时》又觉得每个人都在闪闪发光。学习《简单的博弈论》、《简单的逻辑学》,研究足球的时候学习《数字游戏》。看《故事写作大师班》、《风格练习》,想学习写作但是没学会。盯着酒杯发呆的时候会想起《存在主义咖啡馆》里的萨特,照镜子的时候偶尔会想起《局外人》。《守门员面对罚点球时的焦虑》我体会不到,《哥德尔、艾舍尔、巴赫》曾经打败过我。《禅与摩托车维修艺术》告诉我感性和理性的结合会是卓越,而《基本美》,就是基本美。 原来真的看了不少书,那浪费的这些时间也就不足为过,再多看一点书吧。 之前写读书笔记的时候,没有想好名字,现在有了答案。 “不能想象没有书的世界”

March 31, 2021

Spring 事务事件监听,为什么会出现事务失效?

Spring 在 4.2 版本之后提供了@TransactionlEventListener 注解,可以很方便地在事务提交后做一些处理,但是如果使用不当,或者没有正确理解其背后的运行逻辑,很容易踩坑甚至导致线上故障。 之前工作中就遇到了一个问题,在事务监听时,做了一些事务操作,但是这个事务并没有生效。 今天我们就来深入了解一下,这个问题是怎么产生的,又该如何解决。 问题复现 我们来模拟一个很简单的场景:创建订单的时候会发布“订单已注册”的事件,在事件监听里保存操作记录,再发布“操作记录已保存”的事件,最后在这个事件监听里做一些逻辑。 以下代码中省略了一些不重要的实现。 首先是 OrderService,createOrder() 方法里保存订单记录,发布“订单已注册”的事件: public class OrderService { @Transactional public void createOrder() { String orderNo = "test_no"; Order order = new Order(orderNo); orderRepository.save(order); log.info("publish OrderCreatedEvent"); applicationContext.publishEvent(new OrderCreatedEvent(orderNo)); } } “订单已注册”的事件监听里,调用 operationService.saveOperation(): public class OrderCreatedEventListener { @TransactionalEventListener public void handle(OrderCreatedEvent event) { log.info("handle OrderCreatedEvent : " + event.getOrderNo()); operationService.saveOperation(event.getOrderNo(), "创建订单"); } } OperationService.saveOperation(),保存操作记录,并发布“操作记录已保存”的事件: public class OperationService { @Transactional public void saveOperation(String orderNo, String info) { Operation operation = new Operation(orderNo, info); operationRepository....

March 20, 2021

还没想好名儿的读书系列 | 《深度说服》

为什么要辩论? 是为了得到问题的答案吗?听双方激烈地争论爱情和面包哪个更重要,这个问题真的有答案吗? 答案自然是一句废话:“爱情和面包都很重要”,所以为什么要辩论呢? 如果你仔细想一想这个问题,可能会问问自己,爱情的定义是什么?爱情能给自己带来什么?在哪些情况下,财富更重要?在经过一系列缜密地思考、碰撞之后,你肯定也知道了答案“爱情和面包都很重要”,但是你对爱情和面包的理解,会更加清晰、深刻。如果真的到了爱情和面包的十字路口,相信你不再会一脸茫然,而是有信心和理由,坚定地走下去。 “辩论的目的是要找出有价值的观点,人们相信、接纳这个观点,从而产生更强的信念。” 这一本《深度说服》,就是教你如何思辨、反驳、提问和说服。 说起辩论,就有点双方互相博弈的意思,事实也是如此,书中的很多经验也都可以用博弈论来解释。当然,辩论的目的不仅仅是为了说服对方,现实生活中,也很难有机会与他人进行一场高质量、公平的“辩论”。辩论更重要的在于思考,在脑海中与自己进行“辩论”,最后得到的观点,就是你看待问题的方式,以什么样的方式看待问题,就能得到什么样的答案。表达能力也很重要,有时候觉得自己想明白了,但是支支吾吾就是说不清楚。我一直都觉得,说出来的言语是最能直接地体现一个人的思维方式和思考能力的,所以之前有和@92 一起录电台“怪话贩卖机”,一方面是为了满足自己的表达欲望,同时也是想借这个形式来锻炼自己的思维能力和表达能力。 针对思考、反驳、提问和综合说服,书中列举了对应的思路和原则,还很多实践方式,我就不再复述了。 既然是一本实践类的书,里面讲述的方法,真的有这么好用吗? 之前我自己没怎么接触过辩论,正好前段时间有朋友和我聊到奇葩说,书里也有提到,于是我就花了一点时间(都超过看完这本书的时间了!),挑了奇葩说里的一期,来简单复盘一下,看看辩论选手们有没有使用书中的技巧,效果到底怎么样。 下面我会将各位辩手的发言截取出来,并逐一分析,在括号里标注书中对应的技巧。 长图警告!!! 视频来源为奇葩说 S04E03,辩题是“外卖小哥惹毛我,该不该投诉他?”。 看到这个辩题,经常点外卖的你,拳头是不是已经暗暗握紧了? 不知道你是怎么想,反正蛋堡被惹毛后,软嘴唇都变硬了: 废话不多说,我们来看看奇葩说的各位辩手都怎么辩: 反方 - 卡姆 先由反方开始发言,卡姆的这段论述,主要表达了 3 个观点: 观点 1:“惹毛"这个词比较主观,行为让人生气,并不代表行为错误。 观点 2:投诉会让外卖小哥的努力白费。 观点 3:投诉可能会引起外卖小哥的报复。 中间穿插了一个女朋友的故事,以及“人在饿的时候最容易被惹毛”的信息支撑,增强了观点的代入感(综合说服 - 共情原则)。 正方 - 湉湉 正方湉湉开始反驳,“人在饿的时候最容易被惹毛”是明知故犯(归谬 - 抬升观点力度)。 然后引出自己观点 1: 投诉可以有效避免正面冲突。 接着反驳卡姆的观点 3 :投诉是匿名的(反驳 - 现象不存在),然后举自己打车的例子(综合说服 - 细节),以及表演“疯狗”的形象(综合说服 - 幽默 - 自损),增强了观点的可信度,也有不错的表演效果。 最后说明观点 2:投诉方便了那些不愿意投票的人。 反方 - 渐彪 首先反驳湉湉:投诉匿名的话,为什么会有报复性事件(反驳 - 现象不存在)。 然后话锋一转,“是情绪中的决定,为什么不留留手”,将讨论的重心转向理性思考和道德(反驳 - 受身)。 随后引出观点:外卖小哥和消费者权力悬殊。首先制造了价值冲突,然后对比鞭策和打击、挡刀和赶人,感情表达相当精彩(综合说服 - 制造感动)。...

February 18, 2021

英语学习回顾 - Stage One

说来也是奇妙,去年国庆从莫干山放空回来,突然就有了认真学好英语的想法。没有什么显而易见的缘由,总之是一种很强烈的“冲动”。倒也不能算作是冲动,它比冲动更坚毅,前提是能在转瞬即逝之前抓住它。 于是我立马联系了英语培训,下单买了全套的《English Grammar in Use》(英文原版有够贵哦)。“请问你是有打算考雅思或者托福?”,“我就是想学好英语”。怎样才算学好英语呢?这个目标不像考试驱动的学习,有个清晰明了的终点——分数。思考一下语言的本质,是信息交换的“等价物”,也是一套输入 -> 理解 -> 输出的系统。学好英语,就是构建好这一整套系统,从视听获得信息输入,理解并转化,然后通过言语输出,好的英语能力也能降低信息的折损率。当然之后也有计划考一下 PTE(Pearson Test of English Academic),可以全方位客观地验证下学习成果。 大致给自己安排了一整年的时间,时间紧,任务重,我开始找寻高效的方法论。《程序员学英语指南》 是一整套挺有干货的指南,里面有很多实用的学习方法。当然有一个好老师也很重要,big shout-out to my teacher Sissie! 截至目前已经学习了近四个月,接下来分享一下自己摸索出的学习内容和方法。 自然发音法 读书的时候学的英文发音,都是从认识音标开始的,遇到陌生的单词,没有音标的话都不知道怎么发音了,当然久而久之你会形成一些语感,去猜测单词大致的发音。其实母语为英语的外国人是不学音标的,从小就是模仿发音,身边也有大量的英文输入能帮助他们形成语感,纠正发音。音标是为了方便外语学习者才定义的。 上面说的语感就是“自然发音”,学习自然发音法就是掌握一套发音规则,例如字母 c + 字母 i/e/y,c 会发 s 的音。当然这套规则不能保证完全正确,因为英语中也有很多舶来词汇,或者特例。 如果遇到陌生的单词,就可以用自然发音法去猜测,然后验证,对于单词记忆和阅读还是很有帮助的。 词汇 没有什么好说的,词汇是基础,我也没什么记忆天赋,只能耐心背啦。艾宾浩斯遗忘曲线告诉我们遗忘的规律是先快后慢,所以需要间隔性重复记忆。我使用的记忆辅助软件是 Anki,以卡片的形式,按照给定的卡组和学习量,每天自动生成复习内容,而且开源跨平台,不过在 ios 上收费 163 元,我觉得还是挺值的哈。另外因为可以自定义卡组,Anki 也可以用来帮助记忆任何你想背的内容。 目前我在背的卡组是常用 7000 词,新单词先用自然发音法猜测,然后听发音确认并记忆,复习单词时自己先念出来,再校对。每天的背诵量就依个人情况量力而为,刚开始是每天 20 个新单词,近期调整为每天 50 个,半小时左右就能搞定新单词+复习。平时阅读遇到的陌生高频词我也会加入一个自定义的卡组,随机学习常用词+主动记忆高频词汇,效率还是挺不错的。 阅读 这一阶段有刻意地加大英文内容的输入量,主要还是以自己感兴趣的内容为主。我把 InfoQ 的站点切换成了英文版,有空时会翻一翻 Medium ,挑有兴趣的文章看一看,尽量找词汇量适合自己级别的,太多不认识的单词还是会带来一些挫败感。使用浏览器阅读的话还可以结合词典插件,顺带强化单词的记忆。 阅读除了浏览,还有朗读。平时没什么机会说英文的话,可以自己读文章。刚开始练习读的时候,读快了舌头会打架,连读时没有削掉辅音,而且没有什么腔调。看一些英语学习的资料上有推荐 shadow reading,但是我尝试了后觉得这一阶段做 shadow reading 还是有点难,TED 上有一期,史嘉琳教授分享了用 回音法 练习口语,感觉还挺合适的。后来意外地发现 Edge 浏览器的朗读功能很强,连读有消音,也有点腔调,还可以调整“工具人”的音色和速度。遇到好的文章就可以跟着 Edge 的朗读,用回音法一点点练习。 听力 听力也是日常英文输入的重要部分。基本上每天都会刷 Youtube,TED 的视频都是不错的听力练习材料,上下班的路上也会听一些 podcast。...

February 6, 2021

还没想好名儿的读书系列 | 《系统之美》

「他们可能会假定,通过系统分析,可以认清系统中的相互联系以及复杂纠葛,借助计算机的威力,最后找到预测和控制系统的钥匙。不幸的是,这是错误的观念,其根源在于工业时代根深蒂固的心智模式,即相信存在一把预测和控制的钥匙」 近期在系统分析领域进行了一些主题阅读,核心的理念基本没差,对于复杂系统,不要妄想用还原论解决,多观察系统的行为表现,判断整体趋势,调节并注重平衡。 相较于上一本《复杂》,这本书列出了系统分析领域常见的问题障碍、陷阱,以及相应的对策。 要素、连接和目标是构成系统的三要素,其中,改变要素对系统的影响最小,改变内在连接对系统的影响很大,系统的目标最不明显,但是最关键的决定因素。在足球世界中,如果球队的表现不好,换帅往往是第一选择 ( 今早兰帕德就被切尔西炒了鱿鱼 ) ,因为新的教练会带来不一样的技战术选择,调整球员之间的化学反应,而单单交易新的球员很难引发球队的质变。 之前在玩 FM ( Football Manager ) 时,会有点畏手畏脚,拘泥于一些技战术的教条,书中讲到“从系统的行为开始,强迫你自己关注于事实,而不是各种理论”,4-3-3 阵型的流行使得人人皆知“得中场者得天下”,但是贝尔萨的方形真空中场战术,带领利兹联近乎疯狂地升入英超,也是给主流足坛上了一课,“足球还是圆的”,对吧?游戏里提供了大量的数据统计分析,容易陷入数据陷阱,被水淹没,不知所措。虽然近些年数据科学发展迅速,但是目前 PA ( Performance Analysis ) 还不足以引导做出决策。数据分析的主要作用还是建立反馈回路,可以快速地看到决策带来的后果,例如 xG 值增加能反映进攻效率有所提升。 最近也有在深入学习、总结 DDD ( Domain-Driven Design ) ,DDD 的目标就是应对软件系统的复杂度。对应书中阐述的系统六大障碍,业务的需求就是“表象”,DDD 就是要拆解领域,分析、理解系统真正的内在结构,使用统一语言架起沟通的桥梁,然后划定清晰的上下文边界,以此来降低系统的复杂、混乱程度。 面对复杂系统自然没有“银弹”,但是这几本书能帮助我们更全面地思考、分析。就像哲学一样,系统分析能让你意识到问题,并很好地与之共存。 Trial and error, be humble. 以下是书中知识点的摘记,方便查阅。 系统的构成条件 要素、连接、功能或目标 一些关键词 系统基模 产生常见问题行为模式的系统结构 流入量 -> 存量 -> 流出量 人类的大脑似乎更加容易关注存量,关注流量的时候,更倾向于关注流入量 反馈回路 调节回路:保持存量稳定、趋向一个目标进行调节或校正 增强回路:强化系统原有的变化趋势 3 大特征 适应力 自组织 层次性 6 大障碍 别被表象所迷惑 在非线性的世界里 不要用线性的思维模式 恰好地划定边界 看清各种限制因素 无所不在的时间延迟 有限理性 8 大陷阱和对策 政策阻力:治标不治本 各个参与者的有限理性,目标不一致,任何一方增强的努力,导致其他所有人的努力也得到增强 对策:设法将各个子系统的目标协调一致,通常是设立一个更大的总体目标,让所有参与者突破各自的有限理性 公地悲剧 对策:教育和劝解,1....

January 26, 2021

Mockito饮用指南

介绍 Mockito是一个用于Java的开源测试mock框架,提供了非常清爽、简洁的API,这个名字来源于经典鸡尾酒 Mojito。 什么是mock?mock就是模拟,有了一个类或接口的定义,我们可以创建一个模拟对象来模拟它的行为,从而就不需要提供这个类或接口的真实实现。 这样在写单元测试的时候,我们只需要mock其他依赖,假设它们的预期返回,就可以专注于测试自己的实现逻辑。 听起来还不错吧,赶紧来尝一口试试。 先尝一口 引入 Mockito Mockito支持使用Gradle、Maven、Jar包引入,如果使用Spring Boot的话,spring-boot-starter-test默认已经集成了Mockito。 下文使用的Mockito,版本为3.6.0,项目代码基于Spring Boot。 入门操作 先来看一下官方文档上最简单的两个栗子 验证交互: import static org.mockito.Mockito.*; // mock创建一个 List List mockedList = mock(List.class); // 调用mock对象的方法 mockedList.add("one"); mockedList.clear(); // 可以直接验证方法被调用了 verify(mockedList).add("one"); verify(mockedList).clear(); mock调用返回: // mock创建一个 LinkedList LinkedList mockedList = mock(LinkedList.class); // 使用stub,假设mockedList.get(0)被调用时,会返回"first" when(mockedList.get(0)).thenReturn("first"); // 控制台会打印"first" System.out.println(mockedList.get(0)); // 控制台会打印"null",因为我们没有假设get(999)的返回值 System.out.println(mockedList.get(999)); 怎么样,看起来是不是很简单,语法也很贴近自然语言。 Mockito本质上是代理模式的应用,mock就是创建proxy对象,在proxy被调用前,使用stub的方式设置返回值,proxy还能记录并跟踪行为。 饮用搭配 doSomething() void方法或者spy对象,在mock行为时需要使用doThrow()、doAnswer()、doNothing()、doReturn()、doCallRealMethod() 注意区分mock和spy,mock就是完全代理,spy则是部分mock,可以调用真实方法,同时也能被跟踪验证 List list = new LinkedList(); List spy = spy(list); // 这里会抛出IndexOutOfBoundsException,因为调用了真实方法,而list实际上是个空列表 when(spy.get(0)).thenReturn("foo"); // 使用doReturn()来设置spy....

January 6, 2021

译 | 各种服务总线: 命令总线,服务总线和查询总线

本文为个人翻译,原文链接 上一篇文章讲了一个特殊的服务总线,即命令总线。现在我们回过头来看看其他服务总线,他们有什么相似或是不同之处。 什么是服务总线? 好像很难用简单的话来解释什么是服务总线。如果你在维基百科上查询服务总线,会看到一些关于企业级软件开发的术语定义,还列举了一些微软、IBM和Oracle的例子。这和我平时接触的PHP驱动的网络开发相比,完全是另一个世界。 我先用自己的话来总结一下什么是服务总线吧: 服务总线是组件之间传递信息的方式 消息是以DTO的形式,包含了需要执行的信息 “消息发送组件”会创建消息并传递给总线 “消息接收组件”会告知总线它想要消费的消息类型 当总线接收到消息时,会分发消息给接收者 总线是能够解耦组件的边界,发送者和接收者都不会感知到其他组件 由于解耦,总线能够让组件很高效地合作 而且因为总线是所有消息的“中间商”,可以给所有的消息增加功能,而不需要改动消息、发送者或接收者。例如给所有的消息加上日志打印或者给消息排序 希望这些描述能让你更清楚什么是服务总线。如果还不明白的话,可以看看我之前的文章,解释了什么是命令总线。那篇文章不会很抽象,而且有一些代码样例。 不同的总线 到目前为止,我们讨论了“通用的”服务总线。这个总线只会分发信息,无论如何也不会限定消息,或者是做一些处理。 你可以想象一下,不同类型的消息应该用不同的方式处理,这也是为什么我们有各种各样的服务总线,接下来我会讨论3种: 命令总线 查询总线 事件总线 我们来看一下它们的关键点 命令总线 消息(命令)标识了用户的意图。比如说“创建文章”或者“注册帐号”。 一个命令只能有一个确定的处理者 命令不会返回任何值 查询总线 消息(查询)标识了一次查询操作,注意不是数据库查询。比如“最新的文章”或者“文章的所有评论” 一个查询只能有一个确定的矗立着 查询会返回数据 查询不会改变应用的状态 事件总线 消息(事件)标识了一个已经发生的事件。比如“文章已创建”或者“用户已注册”。 一个事件可以有任意数量的处理者([0, inf])。 只会持有基础变量(字符串,整数值,布尔值),而不是整个类。 事件不会返回值 可以看到这些总线很相似,在我看来这也是他们很有用的原因。总线的概念很容易理解,使用也简单,可以给你的应用增强结构性和可预测性。 最后一点 验证 消息都应该被验证,这就意味着消息对象应该验证自己的入参,这样一来,只有有效的消息会被分发,也会带来一点限制。 “注册用户”命令应该需要(不考虑其他情况)一个用户名。这个命令应该要验证一下用户名是个字符串,并且字符的长度在6和100之间。而用户名是否唯一,这个需要由处理者来验证,而不是通过命令本身。 更大的模式 实现命令和查询是命令查询职责分离(CQRS)的一部分,当然你也可以不应用CQRS,直接使用服务总线。 命令和事件经常一起使用,比如“注册用户”命令完成后,会发送事件“用户已注册”。可以阅读 Matthias Noback 写的 From Commands To Events 。 拓展阅读 如果想更深入了解服务总线和消息: Mathias Verraes 写的 Messaging Flavours Robert Basic 写的 All Aboard The Service Bus Matthias Noback 写的 Some questions about the command bus 或者阅读我的其他文章:...

January 5, 2021