《领域驱动设计》读书笔记(三):通过重构来加深理解

《领域驱动设计》读书笔记(三):通过重构来加深理解

我们面临的真正挑战是找到深层次的模型,这个模型不但能够捕捉到领域专家的微妙的关注点,还可驱动切实可行的设计。我们的最终目的是开发出能够捕捉到领域深层含义的模型。 要想成功地开发出实用的模型,需要注意以下 3 点: 复杂巧妙的领域模型是可以实现的,也是值得我们去花费力气实现的。 这样的模型离开不断的重构是很难开发出来的,重构需要领域专家和热爱学习领域知识的开发人员密切参与进来。 要实现并有效地运用模型,需要精通设计技巧。 重构就是在不改变软件功能的前提下重新设计它。 自动化的单元测试套件能够保证对代码进行相对安全的试验。 设计模式重构 — 为实现更深层模型而进行的重构。 代码细节重构 简称为“领域模型重构”。 学习以更高维度去看待问题。 《重构》一书中所列出的重构分类涵盖了大部分常用的代码细节重构。这些重构主要是为了解决一些可以从代码中观察到的问题。 领域模型会随着新认识的出现而不断变化,由于其变化如此多样,以至于根本无法整理出一个完整的目录。 建模和设计都需要你发挥创造力。 对象分析的传统方法是先在需求文档中确定名词和动词,并将其作为系统的初始对象和方法。 事实上,初始模型通常都是基于对领域的浅显认知而构建的,既不够成熟也不够深入。 深层模型能够穿过领域表象,清楚地表达出领域专家们的主要关注点以及最相关的知识。 戴久了的手套在手指关节处会变得柔软;而其他部分则依然硬实,可起到保护的作用。 柔性设计除了便于修改,还有助于改进模型本身。 Model-Driven Design 需要以下两个方面的支持:深层模型使设计更具表现力;同时,当设计的灵活性可以让开发人员进行试验,而设计又能清晰地表达出领域含义时,那么这个设计实际上就能够将开发人员的深层理解反馈到整个模型发现的过程中。 由于模型和设计之间具有紧密的关系,因此如果代码难于重构,建模过程也会停滞不前。 你需要富有创造力,不断地尝试,不断地发现问题才能找到合适的方法为你所发现的领域概念建模,但有时你也可以借用别人已建好的模式。 第 8 章 突破 Figure 1. 重构/突破 小改进可防止系统退化,成为避免模型变得陈腐的第一道防线。 重构的原则是始终小步前进,始终保持系统正常运转。 过渡到真正的深层模型需要从根本上调整思路,并且对设计做大幅修改。 不要试图去制造突破,那只会使项目陷入困境。通常,只有在实现了许多适度的重构后才有可能出现突破。 要为突破做好准备,应专注于知识消化过程,同时也要逐渐建立健壮的 Ubiquitous Language 。 第 9 章 将隐式概念转变为显式概念 深层建模的第一步就是要设法在模型中表达出领域的基本概念。 若开发人员识别出设计中隐含的某个概念或是在讨论中受到启发而发现一个概念时,就会对领域模型和相应的代码进行许多转换,在模型中加入一个或多个对象或关系,从而将此概念显式地表达出来。 概念挖掘 倾听领域专家使用的语言。有没有一些术语能够简洁地表达出复杂的概念?他们有没有纠正过你的用词(也许是很委婉的提醒)?当你使用某个特定词语时,他们脸上是否已经不再流露出迷惑的表情?这些都暗示了某个概念也许可以改进模型。 有些概念可能需要你自己去挖掘和创造。要挖掘的地方就是设计中最不足的地方,也就是操作复杂且难于解释的地方。 看书与咨询领域专家并不冲突。即便能够从领域专家那里得到充分的支持,花点时间从文献资料中大致了解领域理论也是值得的。 开发人员还有另一个选择,就是阅读在此领域中有过开发经验的软件专业人员编写的资料。 阅读书籍并不能提供现成的解决方案,但可以为她提供一些全新的实验起点,以及在这个领域中探索过的人总结出来的经验。 如何为那些不太明显的概念建模 显式的约束 约束是模型概念中非常重要的类别。它们通常是隐含的,将它们显式地表现出来可以极大地提高设计质量。 将约束条件提取到其自己的方法中,这样就可以通过方法名来表达约束的含义,从而在设计中显式地表现出这条约束。 下面是一些警告信号,表明约束的存在正在扰乱其“宿主对象”(Host Object)的设计: 计算约束所需的数据从定义上看并不属于这个对象。 相关规则在多个对象中出现,造成了代码重复或导致不属于同一族的对象之间产生了继承关系。 很多设计和需求讨论是围绕这些约束进行的,而在代码实现中,它们却隐藏在过程代码中。 如果约束的存在掩盖了对象的基本职责,或者如果约束在领域中非常突出但在模型中却不明显,那么就可以将其提取到一个显式的对象中,甚至可以把它建模为一个对象和关系的集合。 将过程建模为领域对象 对象是用来封装过程的,这样我们只需考虑对象的业务目的或意图就可以了。 过程是应该被显式表达出来,还是应该被隐藏起来呢?区分的方法很简单:它是经常被领域专家提起呢,还是仅仅被当作计算机程序机制的一部分? 模式:Specification 业务规则通常不适合作为 Entity 或 Value Object 的职责,而且规则的变化和组合也会掩盖领域对象的基本含义。但是将规则移出领域层的结果会更糟糕,因为这样一来,领域代码就不再表达模型了。
《卡片笔记写作法》之读书笔记(三):成功写作的六个步骤

《卡片笔记写作法》之读书笔记(三):成功写作的六个步骤

D瓜哥
不写,就无法思考。 — 卢曼 1992,53 最近把 《卡片笔记写作法》 读完了,深受启发,相见恨晚。 先分享一个小趣闻:看完这本书,想实践一下,就去购物网站搜合适的活页卡片。考虑到便利性,就选择了 A6 大小的活页。上网找了一圈,也没有找到标准尺寸的 A6 活页。考虑以后直接拿 A4 纸进行裁剪。现在的问题变成了如何把 A4 纸裁剪得标准一些。 看完全书,纵观卡曼的发展过程,特别叹服的一点是,他会不断反思自己的行为和学习方法,并且反复尝试改进自己的学习方法,以求达到最好的效率。反思自己,虽然总是耕读不断,虽然过程中也许捡了不少好砖,但是就像那个捡玉米的猴子,随捡随丢,终究没能垒起我的阅读城堡!可惜可惜! 闲言少叙,书归正传。读这本书,有几点印象特别深刻: 书中将记忆区分为两种机智:存储强度(storage strength)与提取强度(retrieval strength)。并且“存储与提取负相关”,也就是说,存入记忆越容易,提取出来越困难;反之,如果你有些吃力地存入,知识提取会更方便。这点有点意思。 书中一个比喻特别形象:卢曼卡片盒就像是复利投资,而特罗洛普的技术就像是储蓄罐。复利投资可以滚雪球,越滚越大,而且是指数增长。 书中还有一个概念很有意思:“思维网格”,如果知识既不是被孤立地保存,也不是被孤立地学习,而是聚集在一个思想网络中,或者说是“思维模型的网格”中,那么理解新的信息就变得更容易了。 卡片笔记学习法自然而然产生的自下而上写作法拥有一个巨大优势:我们所使用的想法都嵌入了丰富的上下文中,并且附带了可以使用的素材,而不是凭空产生的。这样做会带来另一个意想不到的收获,那就是我们会对新的想法持更加开放的态度。可以轻松避免由于预设结论导致的认知偏误。 卡片盒笔记的精华所在:以新的和意想不到的方式,将不同的想法汇集在一起,从而产生新的想法。卢曼的卡片不是简简单单地摘抄,而是自己组织语言的转述,需要加工再输出。不仅仅是摘录原文,更是思想的录像机与连接器,记录下当下的思想,建立与已有思想的链接。 一个巨大的误解是:如果不制订计划,就只能是漫无目的地乱写一气。其实我们真正该做的是构建适合自己的工作流程,让洞见和新想法成为推动我们前进的驱动力。 记笔记也不是最关键的工作,思考、阅读、理解和提出想法才是,笔记只是它们的具体成果。写,无疑是我们思考、阅读、学习、理解和产生想法的最佳催化剂。 书中的真知灼见数不胜数,可以通过D瓜哥的这几篇读书笔记“管中窥豹”。当然,更推荐大家去阅读原文。D瓜哥是在“微信读书”中阅读的免费版,礼尚往来,推荐一下。 D瓜哥把读书笔记整理一下。按照章节,分三篇来分享: 《卡片笔记写作法》之读书笔记(一):绪论 《卡片笔记写作法》之读书笔记(二):有效写作的四个基本原则 《卡片笔记写作法》之读书笔记(三):成功写作的六个步骤 第三章 成功写作的六个步骤 明确区分独立而又相关联的任务 全神贯注于每一项任务 根据一项引用量很大的研究,频繁出现的电子邮件和短信所造成的不断干扰,会使我们的工作效率降低40%,并使我们的智商至少降低10%。 我们正被越来越多的干扰因素包围着,并且提升注意力的机会也更少了。 考虑把微信和工作通讯录的提醒给关闭掉。 不要一心多用 虽然那些进行多任务处理的人感觉自己更有效率,但实际上他们的效率却低了很多(Wang and Tchernev,2012;Rosen,2008;Ophir,Nass and Wagner,2009),而且在数量和质量方面的表现都明显落后于一次只做一件事的人。 当我们认为自己在同时处理多项任务时,我们真正做的其实是在两件甚至多件事情之间快速转移注意力,每一次转移注意力都会消耗我们的转移能力,并会延长我们再次集中注意力所需要的时间。总的来说,一心多用会让人疲惫不堪,也会降低我们处理多项任务的能力。 写论文不仅仅是在键盘上打字,它还包括阅读、理解、思索、产生想法、建立联系、区分术语、寻找合适的词语、结构化、组织、编辑、修正和重写等。 自从20世纪70年代米哈里·契克森米哈赖(Mihaly Csikszentmihalyi)描述了“心流”状态——一种毫不费力就能高度集中注意力的状态(Csikszentmihalyi, 1975)[2 集中注意力不同于“持续注意”,后者指的是我们需要在较长的时间内保持对一项任务的关注,这也是学习、理解或完成某件事情所必需的。 好消息是,如果我们能避免同时处理多项任务,尽可能将不同类型的任务分开,使它们不会相互干扰,并排除可能的其他干扰,我们就能训练自己在更长时间内专注于一件事的能力。 不同的任务需要不同的关注度 校对则需要重点关注写作时用什么词表达更准确,因而校对需要的是更专注的注意力,而写作过程中寻找合适的词语则需要更多的漂浮注意力。 如果我们不用同时考虑文章的结构,就更容易集中精力琢磨正确的词语。这就是我们为什么应该把稿件的大纲打印出来,一直放在眼前的原因。我们必须搞清楚眼下哪些内容不必写,因为知道这些内容要写在其他章节里。 专业地阅读,不是指掌握一种方法,并将其应用于一切情况,而是根据不同的文本灵活地调整阅读的速度和方法。 “具体来说,杰出科学家解决问题的行为可以在‘对特定概念的超常专注程度’和‘对想法的有趣探索’之间交替进行。这表明,要想成功解决问题,可能需要根据任务和需求灵活地选择应对策略。”(Vartanian,2009) 真正的答案是有创造力的人需要以上两种能力,创造力的关键是能够在开放、活泼的思维和传统的分析框架之间灵活地切换。”(Dean,2013) 做专家,不做计划制订者 我们停止制订计划之时,就是开始学习之时。根据具体情况在最重要和最有前景的任务之间灵活地选择和切换,变得擅于产生洞见和写出好文章——这需要通过练习来实现。 学术写作是一个高度依赖认知和思考的过程,但人们误以为仅仅依靠有意识的决策就可以完成,这就是制订计划广受推崇的原因。如果真的想在学术写作方面取得进步,可以通过经验和刻意练习来掌握这门艺术。 不要害怕犯错,要在错误中成长! >要想成为专家,我们需要自由地、独立地做出决定,还要经历能够帮助我们学习的必要错误。 要想成为专家,我们需要自由地、独立地做出决定,还要经历能够帮助我们学习的必要错误。 根据德雷福斯的模型理论[4],正确运用学习到的规则,可以使你成为一个称职的“胜任者”(位于5层级模型中的第3层级),但它不会使你成为“精通者”(第4层级),当然也不会使你变成“专家”(第5层级)。 根据德雷福斯的模型理论[4],正确运用学习到的规则,可以使你成为一个称职的“胜任者”(位于5层级模型中的第3层级),但它不会使你成为“精通者”(第4层级),当然也不会使你变成“专家”(第5层级)。 经常只是一味地循规蹈矩,只会在“别人的规则”里打转! 这里所说的直觉不是指某种神秘的力量,而是一种融入了过去的经验,通过无数次成功或失败的反馈循环,深入学习、反复实践的沉淀。 写下来为大脑减负 心理学家过去在谈到短期记忆容量时的看法是一致的:我们最多可以同时在脑海中保存7±2件事(Miller,1956)。
《卡片笔记写作法》之读书笔记(二):有效写作的四个基本原则

《卡片笔记写作法》之读书笔记(二):有效写作的四个基本原则

D瓜哥
不写,就无法思考。 — 卢曼 1992,53 最近把 《卡片笔记写作法》 读完了,深受启发,相见恨晚。 先分享一个小趣闻:看完这本书,想实践一下,就去购物网站搜合适的活页卡片。考虑到便利性,就选择了 A6 大小的活页。上网找了一圈,也没有找到标准尺寸的 A6 活页。考虑以后直接拿 A4 纸进行裁剪。现在的问题变成了如何把 A4 纸裁剪得标准一些。 看完全书,纵观卡曼的发展过程,特别叹服的一点是,他会不断反思自己的行为和学习方法,并且反复尝试改进自己的学习方法,以求达到最好的效率。反思自己,虽然总是耕读不断,虽然过程中也许捡了不少好砖,但是就像那个捡玉米的猴子,随捡随丢,终究没能垒起我的阅读城堡!可惜可惜! 闲言少叙,书归正传。读这本书,有几点印象特别深刻: 书中将记忆区分为两种机智:存储强度(storage strength)与提取强度(retrieval strength)。并且“存储与提取负相关”,也就是说,存入记忆越容易,提取出来越困难;反之,如果你有些吃力地存入,知识提取会更方便。这点有点意思。 书中一个比喻特别形象:卢曼卡片盒就像是复利投资,而特罗洛普的技术就像是储蓄罐。复利投资可以滚雪球,越滚越大,而且是指数增长。 书中还有一个概念很有意思:“思维网格”,如果知识既不是被孤立地保存,也不是被孤立地学习,而是聚集在一个思想网络中,或者说是“思维模型的网格”中,那么理解新的信息就变得更容易了。 卡片笔记学习法自然而然产生的自下而上写作法拥有一个巨大优势:我们所使用的想法都嵌入了丰富的上下文中,并且附带了可以使用的素材,而不是凭空产生的。这样做会带来另一个意想不到的收获,那就是我们会对新的想法持更加开放的态度。可以轻松避免由于预设结论导致的认知偏误。 卡片盒笔记的精华所在:以新的和意想不到的方式,将不同的想法汇集在一起,从而产生新的想法。卢曼的卡片不是简简单单地摘抄,而是自己组织语言的转述,需要加工再输出。不仅仅是摘录原文,更是思想的录像机与连接器,记录下当下的思想,建立与已有思想的链接。 一个巨大的误解是:如果不制订计划,就只能是漫无目的地乱写一气。其实我们真正该做的是构建适合自己的工作流程,让洞见和新想法成为推动我们前进的驱动力。 记笔记也不是最关键的工作,思考、阅读、理解和提出想法才是,笔记只是它们的具体成果。写,无疑是我们思考、阅读、学习、理解和产生想法的最佳催化剂。 书中的真知灼见数不胜数,可以通过D瓜哥的这几篇读书笔记“管中窥豹”。当然,更推荐大家去阅读原文。D瓜哥是在“微信读书”中阅读的免费版,礼尚往来,推荐一下。 D瓜哥把读书笔记整理一下。按照章节,分三篇来分享: 《卡片笔记写作法》之读书笔记(一):绪论 《卡片笔记写作法》之读书笔记(二):有效写作的四个基本原则 《卡片笔记写作法》之读书笔记(三):成功写作的六个步骤 第二章 有效写作的四个基本原则 写作是唯一重要的事情 有了想法只有自己知道,就等于没想法,而无法重现的论据也根本算不上论据。 教授不是为了学生而存在的,学生也不是为了教授而存在的,两者都只为真理而存在,而真理永远属于公共事务。 专注于写作,并不意味着要减少阅读量,因为它是写作材料的主要来源;专注于写作,并不意味着要少参加讲座或研讨会,因为它们不但能为你提供写作的思路和值得解答的问题,而且是了解研究现状的最佳途径之一,更不用说它为提出和讨论问题提供了平台;专注于写作也并不意味着要停止做演讲或寻找其他方式将自己的想法公之于众——没有什么比这更好的途径为你的想法提供反馈了。 努力找寻你“应该”做的事情并不是在浪费时间,相反,借助于此,你会努力以尽可能高的效率去学习,从而迅速找到那个开放性的问题,也是唯一值得写作的问题。 简洁是最重要的 越简单的想法往往具有越强大的效果(并且在一开始总被忽视)。 马尔科姆·麦克莱恩(Malcom McLean)的集装箱思想和实践,改变了世界贸易格局。 1956年4月26日,麦克莱恩把“理想X号(Ideal X)”邮轮改装成可以装载58个集装箱的邮轮起航的时候,仅仅是因为这种直接装卸集装箱的分装方式比整船装卸货物的方式便捷,能免于在港口漫长的等待几天。 麦克莱恩比别人更明白,重要的不是船东的观点,而是整个贸易的目的,即把货物从生产者那里带到最终目的地。只有将运输链的每一个环节——从包装到运送,从设计船舶到设计港口——都统一起来之后,集装箱的潜力才能够得到充分释放。 从这个地方也可以看出,不要只谋求一城的得失,要从战略的高度看全局的胜负。做笔记也一样,不是写完就完事了,整理输出再加工更加重要。 当他们读到一个有趣的句子,就在下面画线;当他们想要评论时,就写到空白处;当他们有一个想法时,就写进笔记本;当他们觉得一篇文章足够重要,就努力摘抄。 传统的笔记系统中,主要问题是人们把某条笔记存放在了哪个主题下;而卢曼卡片盒笔记系统中,主要问题则是考虑想在哪个主题下再见到它。 有点举一反三的灵动,也有反其道而行之的逆向思维。 这里还有一个问题:一些潜在关联不能及时发现,需要后续逐步探索才能慢慢展示出来。 所有的努力只为一个目的:发表有价值的观点。 传统的笔记系统是为了找到你意图搜索的东西,让你的大脑疲于回忆,而卢曼卡片盒笔记系统则是为了给你呈现你已经忘记的想法,让你的大脑专注于思考。 要达到群聚效应的最佳点,关键是要分清楚三类笔记。 闪念笔记(Fleeting Notes):这类笔记只是对收集信息起提醒作用,可以用任何一种方式来写,最后会在一两天内被扔进垃圾桶。 永久笔记(Permanent Notes):这种笔记以一种永久可以理解的方式包含了必要的信息,并且永远不会被扔掉。它们总是以同样的方式存放在同一个地方,或者是在文献管理系统中,或者按出版标准写好放在卡片盒中。 项目笔记(Project Notes):它们只与某一特定项目有关,保存在特定项目的文件夹内,项目结束后即可丢弃或存档。 第一个典型的错误是很多勤奋的学生都会遵循“要像写科学杂志一样记笔记”的建议。 由于他把每一条笔记都划分到“永久笔记”的范畴,导致优秀的笔记被其他或许只与特定项目有关、或许实际上不那么好的笔记淹没了,因此永远也无法实现群聚效应。 第二个典型的错误是只收集与特定项目有关的笔记。 第三个典型的错误当然是把所有的笔记都当作闪念笔记。 这三种类别的混乱有一个共同点,那就是记笔记的好处会随着你保存笔记数量的增加而减少,笔记记得越多,就越难找到恰当的那个,越难以自如地将相关的笔记整合到一起。 闪念笔记只有在你能在一两天内回顾它们,并将它们变成以后可以使用的适当的笔记时才有价值。 永久笔记不只是思想或观点的备忘录,而是以书面形式包含实际思想或观点的文本,这是一个至关重要的区别。 与项目有关的笔记可以是以下内容: 手稿中的评论;
《卡片笔记写作法》之读书笔记(一):绪论

《卡片笔记写作法》之读书笔记(一):绪论

D瓜哥
不写,就无法思考。 — 卢曼 1992,53 最近把 《卡片笔记写作法》 读完了,深受启发,相见恨晚。 先分享一个小趣闻:看完这本书,想实践一下,就去购物网站搜合适的活页卡片。考虑到便利性,就选择了 A6 大小的活页。上网找了一圈,也没有找到标准尺寸的 A6 活页。考虑以后直接拿 A4 纸进行裁剪。现在的问题变成了如何把 A4 纸裁剪得标准一些。 看完全书,纵观卡曼的发展过程,特别叹服的一点是,他会不断反思自己的行为和学习方法,并且反复尝试改进自己的学习方法,以求达到最好的效率。反思自己,虽然总是耕读不断,虽然过程中也许捡了不少好砖,但是就像那个捡玉米的猴子,随捡随丢,终究没能垒起我的阅读城堡!可惜可惜! 闲言少叙,书归正传。读这本书,有几点印象特别深刻: 书中将记忆区分为两种机智:存储强度(storage strength)与提取强度(retrieval strength)。并且“存储与提取负相关”,也就是说,存入记忆越容易,提取出来越困难;反之,如果你有些吃力地存入,知识提取会更方便。这点有点意思。 书中一个比喻特别形象:卢曼卡片盒就像是复利投资,而特罗洛普的技术就像是储蓄罐。复利投资可以滚雪球,越滚越大,而且是指数增长。 书中还有一个概念很有意思:“思维网格”,如果知识既不是被孤立地保存,也不是被孤立地学习,而是聚集在一个思想网络中,或者说是“思维模型的网格”中,那么理解新的信息就变得更容易了。 卡片笔记学习法自然而然产生的自下而上写作法拥有一个巨大优势:我们所使用的想法都嵌入了丰富的上下文中,并且附带了可以使用的素材,而不是凭空产生的。这样做会带来另一个意想不到的收获,那就是我们会对新的想法持更加开放的态度。可以轻松避免由于预设结论导致的认知偏误。 卡片盒笔记的精华所在:以新的和意想不到的方式,将不同的想法汇集在一起,从而产生新的想法。卢曼的卡片不是简简单单地摘抄,而是自己组织语言的转述,需要加工再输出。不仅仅是摘录原文,更是思想的录像机与连接器,记录下当下的思想,建立与已有思想的链接。 一个巨大的误解是:如果不制订计划,就只能是漫无目的地乱写一气。其实我们真正该做的是构建适合自己的工作流程,让洞见和新想法成为推动我们前进的驱动力。 记笔记也不是最关键的工作,思考、阅读、理解和提出想法才是,笔记只是它们的具体成果。写,无疑是我们思考、阅读、学习、理解和产生想法的最佳催化剂。 书中的真知灼见数不胜数,可以通过D瓜哥的这几篇读书笔记“管中窥豹”。当然,更推荐大家去阅读原文。D瓜哥是在“微信读书”中阅读的免费版,礼尚往来,推荐一下。 D瓜哥把读书笔记整理一下。按照章节,分三篇来分享: 《卡片笔记写作法》之读书笔记(一):绪论 《卡片笔记写作法》之读书笔记(二):有效写作的四个基本原则 《卡片笔记写作法》之读书笔记(三):成功写作的六个步骤 中文版序 卡片盒笔记依赖一种非线性的方式,即缓慢而稳定的改进,促进思维产生持续、微妙的变化,并且事物间相生相依。朱利安发现这些主题在中国哲学中被讨论得更为广泛。 我欣喜地发现,并非我一人有此体验:卡片盒笔记法——关联的、分散的、自下而上的方法不仅比一些教育者们所推崇的线性的、自上而下的方法更为自然,而且衍生出了诸多写作及笔记记录工具。 卡片盒笔记的精华所在:以新的和意想不到的方式,将不同的想法汇集在一起,从而产生新的想法。 随着可使用工具的快速变化,我决定让这本书尽可能地与工具无关。书籍有着不同的生命周期,因此应该更多地关注不受时间影响的方面。 推荐序一 像卢曼一样写卡片 我写作时,手边会放着纸质的卡片。我一般会先在卡片上写下一些灵感,然后再用卡片写作软件将它们正式整合成文章。同样,在阅读时,我也会不断地使用纸质卡片盒与卡片写作软件写下读书心得。 日本知名学者梅棹忠夫在《智识的生产技术》中提到的“京大卡”,他认为卡片要大一些,大概是B6开本大小,更容易保存写作灵感。而我带队研发的“写匠”,更多地参考了美国知名作家纳博科夫的卡片写作法——使用索引卡,通过任意打乱卡片次序完成自己的写作。 尼克拉斯·卢曼是20世纪德国重要的社会学家,而且其影响力已远远超出了社会学领域。 传统的卡片写作法,像纳博科夫,是只使用一个盒子,用一个盒子来保存自己写作的内容。而卢曼多了一个盒子,对自己卡片写作的内容进行索引和整理。 比约克率先区分了记忆竞争的两种不同类型:存储强度(storage strength)与提取强度(retrieval strength)。 “存储与提取负相关”,也就是说,存入记忆越容易,提取出来越困难;反之,如果你有些吃力地存入,知识提取会更方便。 第一类是主题索引。当某个主题的内容积累得足够丰富,卢曼就会做一张主题索引卡,对这个主题进行概览。主题索引卡上会汇集所有相关笔记的编码或链接,每条笔记会用一两个词或一个短句简要说明核心内容。这类索引,相当于给了你一个进入某一主题的入口。第二类与主题索引类似,只不过不是对某一主题的概览,而是针对盒子里相近位置的卡片所涉及的所有不同主题进行概览。第三类是在当前卡片上做索引,标明这条笔记逻辑上的前一条是什么、后一条是什么(这些卡片在盒子里的位置可能并不挨着)。第四类,也是最常用的索引形式,就是简单的“笔记-笔记”连接。两条笔记可能完全没有关系,把它们关联在一起,往往会产生出乎意料的新思路。 我经常推荐的是德国科学家丹尼尔·卢德克(Daniel Lüdecke)开发的开源软件——卡片盒笔记(Zettelkasten)。 一是将文本的颗粒度拆分得更细。组块(block)是认知科学上的一个常用概念,文本组块正是这个概念的具象化。 以大的单位很难记住,拆分成小的单位就更容易记住。写作时,用大脑直接记住的东西越多,写作就越不容易被打断,节省的脑力就越多。 二是建立了一个“双向引用”关系。什么是“双向引用”? 推荐序二 外脑思考,突破思维局限的写作法 我和作者的兴趣一样,也是外脑思考(Thinking Outside the Brain)。 但工具功能很难改变人的思维习惯,而需要配合课程、书籍或教练服务。 千里之行始于跬步的道理中国人都懂,但没人教过我们在一步一步地、枯燥地踏在探索未知的路上时如何保持热情,如何坚持,如何充满信心,如何时刻和自己对话,以及如何走好每一步。书中介绍的工作流和原则,是卢曼等人利用卡片盒实践过的,他们完全无须坚持就充满乐趣地达成了非凡成就。 深知全世界的人仅凭意志力和坚持,绝无可能完成那种极限挑战。只有完全换另一种思维方式,才能心情愉悦地、安全地达成目标。创业如此,做产品如此,写论文亦如此。 把诸如拖延、坚持、压力、焦虑、知识管理、时间管理等热词从脑海里划掉。 使用卡片笔记写作法,我们可以不定期地提取先前的想法和事实,并将它们与其他信息联系起来,这正是专家们推荐的学习方式。 推荐序三 用卡片笔记积累你的知识复利 书中主要介绍的是德国社会学家尼克拉斯·卢曼自创的一套笔记方法,利用这套方法,他一生积累了90000个知识卡片,写了58本书和其他大量出版物。 就是把你感兴趣或者将来可能会用到的知识收集起来,然后用一种像集装箱一样标准化的方式,去处理这些笔记,建立笔记之间的联系,供你使用。 重要的不是记录,而是更好地思考。
日志最佳实践探究

日志最佳实践探究

加入公司以来,参与了很多个项目的开发维护;也排查处理过很多线上问题;为了写 Mock 测试,也专门去日志系统上扒拉过不少日志等等。在整个过程中,对日志的认识有了不少更深刻的认识和体会。也发现不少问题。这里先从存在的问题展开论述。 日志存在的问题 从个人的眼光上来看,当前的系统存在如下问题: 必要日志没有打印出来,导致在追踪问题或测试代码时,带来不必要的麻烦。比如查看一个接口的返回值用于 Mock 测试;再比如 RPC 调用报错,返回值以及错误信息没有打印到日志中,不知道具体错误原因是什么。 日志抽取中日志路径配置错误,导致日志重复收集,带来不必要的处理和存储成本。 日志代码不规范,导致不必要的性能消耗;或者大促时,日志降级不生效。 日志框架繁多,造成造成冲突,遗漏部分日志。 日志配置不规范,不利于日志的采集和清洗。 日志和调用链路物理隔离,查看一个请求的整个调用链路上的日志非常不方便,不利于问题的快速排查和定位。 大家的系统中,存在什么样的日志问题?欢迎留言交流讨论。 针对这些问题,我觉得有些地方值得发力一下。然后,做了一些探索,总结一下,以备后续使用。 日志最佳实践探索 对于日志的使用,相信所有的开发人员都比较清楚,网上也有大量资料,相关日志框架的官方文档,也写的非常详尽,这里就不再赘述。 本文从一个角度对日志规范进行探究:在排查问题时,能否通过日志来尽快地了解系统运行状态,定位问题原因?另外,由于 Java 的日志框架特别多,有一些比较容易迷惑的问题,尝试做出一点总结。 系统运行后,不严格地说,再去观察系统运行状态,就类似于在黑夜中行走。此时,向你扔过来一块板砖🧱,那么,事后如何追责呢? 请问:你能否成功躲开这块叫做 Bug 的板砖🧱? 日志用来记录用户操作、系统运行状态等,是一个系统的重要组成部分。然而,由于日志通常不属于系统的核心功能,但是在日志对于排查问题,有无可替代的作用,理应得到所有开发人员的重视(不重视,怎么甩锅?!)! If dog is a man’s best friend, logs are software engineer’s best friend. — Geshan Manandhar Logging best practices 好的日志可以帮助系统的开发和运维人员: 了解线上系统的运行状态 快速准确定位线上问题 发现系统瓶颈 预警系统潜在风险 挖掘产品最大价值 可以将一个流程完整串起来(比如orderId) …… 不好的日志导致: 对系统的运行状态一知半解,甚至一无所知 系统出现问题无法定位,或者需要花费巨大的时间和精力 无法发现系统瓶颈,不知优化从何做起 无法基于日志对系统运行过程中的错误和潜在风险进行监控和报警 对挖掘用户行为和提升产品价值毫无帮助 …… 日志从功能来说,可分为诊断日志、统计日志、审计日志。统计日志一般由运维组负责;而审计日志,一般是需要通过代码来实现。这里重点来说说诊断日志。 诊断日志, 典型的有: 请求入口和出口 外部服务调用和返回 资源消耗操作: 如读写文件等 容错行为: 如云硬盘的副本修复操作
《领域驱动设计》读书笔记(二):模型驱动设计的构造块

《领域驱动设计》读书笔记(二):模型驱动设计的构造块

遵循“职责驱动设计”的原则, “契约式设计”思想。 开发一个好的领域模型是一门艺术。 Figure 1. 模型驱动设计语言 第 4 章 分离领域 模式:Layered Architecture 在面向对象的程序中,常常会在业务对象中直接写入用户界面、数据库访问等支持代码。而一些业务逻辑则会被嵌入到用户界面组件和数据库脚本中。这么做是为了以最简单的方式在短期内完成开发工作。 如果与领域有关的代码分散在大量的其他代码之中,那么查看和分析领域代码就会变得异常困难。对用户界面的简单修改实际上很可能会改变业务逻辑,而要想调整业务规则也很可能需要对用户界面代码、数据库操作代码或者其他的程序元素进行仔细的筛查。这样就不太可能实现一致的、模型驱动的对象了,同时也会给自动化测试带来困难。考虑到程序中各个活动所涉及的大量逻辑和技术,程序本身必须简单明了,否则就会让人无法理解。 要想创建出能够处理复杂任务的程序,需要做到关注点分离——使设计中的每个部分都得到单独的关注。 Layered Architecture 的基本原则是层中的任何元素都仅依赖于本层的其他元素或其下层的元素。 Figure 2. 应用分层 给复杂的应用程序划分层次。在每一层内分别进行设计,使其具有内聚性并且只依赖于它的下层。采用标准的架构模式,只与上层进行松散的耦合。将所有与领域模型相关的代码放在一个层中,并把它与用户界面层、应用层以及基础设施层的代码分开。领域对象应该将重点放在如何表达领域模型上,而不需要考虑自己的显示和存储问题,也无需管理应用任务等内容。这使得模型的含义足够丰富,结构足够清晰,可以捕捉到基本的业务知识,并有效地使用这些知识。 关注点的清晰分离可以使每一层的设计更易理解和维护。 在连接各层的同时不影响分离带来的好处,这是很多模式的目的所在。 各层之间是松散连接的,层与层的依赖关系只能是单向的。上层可以直接使用或操作下层元素,方法是通过调用下层元素的公共接口,保持对下层元素的引用(至少是暂时的),以及采用常规的交互手段。 如果下层元素需要与上层元素进行通信(不只是回应直接查询),则需要采用另一种通信机制,使用架构模式来连接上下层,如回调模式或 Observers 模式。 最早将用户界面层与应用层和领域层相连的模式是 Model-View-Controller(MVC,模型—视图—控制器)框架。 只要连接方式能够维持领域层的独立性,保证在设计领域对象时不需要同时考虑可能与其交互的用户界面,那么这些连接方式就都是可用的。 最好的架构框架既能解决复杂技术问题,也能让领域开发人员集中精力去表达模型,而不考虑其他问题。 不妄求万全之策,只要有选择性地运用框架来解决难点问题,就可以避开框架的很多不足之处。 领域层是模型的精髓 “领域层”则是领域模型以及所有与其直接相关的设计元素的表现,它由业务逻辑的设计和实现组成。 如果领域逻辑与程序中的其他关注点混在一起,就不可能实现这种一致性。将领域实现独立出来是领域驱动设计的前提。 模式:The Smart UI“反模式” Smart UI是另一种设计方法,与领域驱动设计方法迥然不同且互不兼容。 如果一个经验并不丰富的项目团队要完成一个简单的项目,却决定使用 Model-Driven Design 以及 Layered Architecture,那么这个项目组将会经历一个艰难的学习过程。团队成员不得不去掌握复杂的新技术,艰难地学习对象建模。(即使有这本书的帮助,这也依然是一个具有挑战性的任务!)对基础设施和各层的管理工作使得原本简单的任务却要花费很长的时间来完成。简单项目的开发周期较短,期望值也不是很高。所以,早在项目团队完成任务之前,该项目就会被取消,更谈不上去论证有关这种方法的许多种令人激动的可行性了。 即使项目有更充裕的时间,如果没有专家的帮助,团队成员也不太可能掌握这些技术。最后,假如他们确实能够克服这些困难,恐怕也只会开发出一套简单的系统。因为这个项目本来就不需要丰富的功能。 在用户界面中实现所有的业务逻辑。将应用程序分成小的功能模块,分别将它们实现成用户界面,并在其中嵌入业务规则。用关系数据库作为共享的数据存储库。使用自动化程度最高的用户界面创建工具和可用的可视化编程工具。 如果一个架构能够把那些与领域相关的代码隔离出来,得到一个内聚的领域设计,同时又使领域与系统其他部分保持松散耦合,那么这种架构也许可以支持领域驱动设计。 如何让一个有效的领域模型和一个富有表达力的实现同时演进。 第 5 章 软件中所表示的模型 一个对象是用来表示某种具有连续性和标识的事物的呢(可以跟踪它所经历的不同状态,甚至可以跨不同的实现跟踪它),还是用于描述某种状态的属性呢?这是 Entity 与 Value Object 之间的根本区别。 领域中还有一些方面适合用动作或操作来表示,这比用对象表示更加清楚。这些方面最好用 Service 来表示,而不应把操作的责任强加到 Entity 或 Value Object 上,尽管这样做稍微违背了面向对象的建模传统。 Service 是应客户端请求来完成某事。
AWK 简介

AWK 简介

这周需要处理一个日志文件,有一次体会到 AWK 强大和方便,但也认识到自己对 AWK 了解的粗浅。所以,写篇文章再深入学习一下。 根据维基百科显示,AWK 于二十世纪七十年代在 Bell Labs 创建;其名字来源于三位创始人: Alfred Aho、Peter Weinberger and Brian Kernighan。AWK 是一个现在几乎每台 Linux 机器上都会有这个命令。 AWK 是一种领域专用语言,专用设计用于文本处理,常用于提取文本或者生成报告。 AWK 也像 Shell 一样,方言和实现众多。D瓜哥这里选择最常用的 GNU AWK 实现。 AWK 是以行为单位来处理文本的。它不仅仅是一个命令行,而且是一门语言。 先展示一下我们的实例程序: $ cat employee.txt ajay manager account 45000 sunil clerk account 25000 varun manager sales 50000 amit manager account 47000 tarun peon sales 15000 deepak clerk sales 23000 sunil peon sales 13000 satvik director purchase 80000 AWK 的基本用法如下: # ① 基本格式 $ awk 动作 文件名 # ② 标准 I/O 格式 $ cat 文件名 | awk 动作 先给大家来个 Hello World:
《领域驱动设计》读书笔记(一):运用领域模型

《领域驱动设计》读书笔记(一):运用领域模型

序 控制复杂性的关键是有一个好的领域模型,这个模型不应该仅仅停留在领域的表面,而是要透过表象抓住领域的实质结构,从而为软件开发人员提供他们所需的支持。 在领域建模过程中不应将概念与实现割裂开来。 概念与实现密不可分的最主要原因在于,领域模型的最大价值是它提供了一种通用语言,这种语言是将领域专家和技术人员联系在一起的纽带。 领域模型并不是按照“先建模,后实现”这个次序来工作的。 真正强大的领域模型是随着时间演进的,即使是最有经验的建模人员也往往发现他们是在系统的初始版本完成之后才有了最好的想法。 既品尝过成功的美酒,也体验过失败的沮丧。 前言 真正决定软件复杂性的是设计方法。 很多应用程序最主要的复杂性并不在技术上,而是来自领域本身、用户的活动或业务。 领域驱动设计是一种思维方式,也是一组优先任务,它旨在加速那些必须处理复杂领域的软件项目的开发。 领域驱动设计的实质就是消化吸收大量知识,最后产生一个反映深层次领域知识并聚焦于关键概念的模型。 极端的简约主义是解救那些过度追求设计的执迷者的良方。 实际上, XP最适合那些对设计的感觉很敏锐的开发人员。 XP过程假定人们可以通过重构来改进设计,而且可以经常、快速地完成重构。 首先需要深入研究模型,然后基于最初的(可能是不成熟的)模型实现一个初始设计,再反复改进这个设计。每次团队对领域有了新的理解之后,都需要对模型进行改进,使模型反映出更丰富的知识,而且必须对代码进行重构,以便反映出更深刻的模型,并使应用程序可以充分利用模型的潜力。 第一部分 运用领域模型 模型是一种简化。它是对现实的解释——把与解决问题密切相关的方面抽象出来,而忽略无关的细节。 模型正是解决此类信息超载问题的工具。模型这种知识形式对知识进行了选择性的简化和有意的结构化。 领域模型并非某种特殊的图,而是这种图所要传达的思想。 对这类知识严格的组织且有选择的抽象。 领域建模并不是要尽可能建立一个符合“现实”的模型。 建模更像是制作电影——出于某种目的而概括地反映现实。 在领域驱动的设计中,3个基本用途决定了模型的选择。 模型和设计的核心互相影响。 模型是团队所有成员使用的通用语言的中枢。 模型是浓缩的知识。 软件的核心是其为用户解决领域相关的问题的能力。所有其他特性,不管有多么重要,都要服务于这个基本目的。 第 1 章 消化知识 有效建模的要素: 模型和实现的绑定。 建立了一种基于模型的语言。 开发一个蕴含丰富知识的模型。 提炼模型。 头脑风暴和实验。 语言和草图,再加上头脑风暴活动,将我们的讨论变成“模型实验室”,在这些讨论中可以演示、尝试和判断上百种变化。 高效的领域建模人员是知识的消化者。 领域模型的不断精化迫使开发人员学习重要的业务原理,而不是机械地进行功能开发。领域专家被迫提炼自己已知道的重要知识的过程往往也是完善其自身理解的过程,而且他们会渐渐理解软件项目所必需的概念严谨性。 模型永远都不会是完美的,因为它是一个不断演化完善的过程。 高效率的团队需要有意识地积累知识,并持续学习。 业务活动和规则如同所涉及的实体一样,都是领域的核心,任何领域都有各种类别的概念。知识消化所产生的模型能够反映出对知识的深层理解。 当我们的建模不再局限于寻找实体和值对象时,我们才能充分吸取知识,因为业务规则之间可能会存在不一致。 知识消化是一种探索,它永无止境。 第 2 章 交流与语言的使用 领域模型可成为软件项目通用语言的核心。 模式:Ubiquitous Language 如果语言支离破碎,项目必将遭遇严重问题。领域专家使用他们自己的术语,而技术团队所使用的语言则经过调整,以便从设计角度讨论领域。 日常讨论所使用的术语与代码(软件项目的最重要产品)中使用的术语不一致。甚至同一个人在讲话和写东西时使用的语言也不一致,这导致的后果是,对领域的深刻表述常常稍纵即逝,根本无法记录到代码或文档中。 翻译使得沟通不畅,并削弱了知识消化。 然而任何一方的语言都不能成为公共语言,因为它们无法满足所有的需求。 Ubiquitous Language(通用语言)的词汇包括类和主要操作的名称。 将模型作为语言的支柱。确保团队在内部的所有交流中以及代码中坚持使用这种语言。在画图、写东西,特别是讲话时也要使用这种语言。 通过尝试不同的表示方法(它们反映了备选模型)来消除难点。然后重构代码,重新命名类、方法和模块,以便与新模型保持一致。解决交谈中的术语混淆问题,就像我们对普通词汇形成一致的理解一样。 要认识到, Ubiquitous Language 的更改就是对模型的更改。 领域专家应该抵制不合适或无法充分表达领域理解的术语或结构,开发人员应该密切关注那些将会妨碍设计的有歧义和不一致的地方。 改善模型的最佳方式之一就是通过对话来研究,试着大声说出可能的模型变化中的各种结构。
关于 MySQL 新版连接驱动时区对齐问题的研究

关于 MySQL 新版连接驱动时区对齐问题的研究

D瓜哥
在一个项目开量验证过程中,发现 createDate 字段不正确,比正确时间晚了十四个小时。调研发现,这是一个非常典型的问题。现在把定位问题的思路和解决办法给大家做个分享。 首先,检查数据库配置,查询线上生产环境配置,结果如下: Figure 1. MySQL 变量 同时,检查线上生产环境 MySQL 版本,为问题复现做准备: Figure 2. MySQL 版本 从数据库配置上来说,基本正常,没有发现什么问题。(持续运行了这么长时间,有问题应该早就发现了。) 其次,检查数据库连接配置,正式环境的链接配置如下: jdbc:mysql://<host>:3306/<schema>?createDatabaseIfNotExist=true &characterEncoding=utf-8&useUnicode=true&connectTimeout=2000 &socketTimeout=2000&autoReconnect=true 数据库连接也没有问题。 第三,询问 SA 线上服务器时区配置,回复上是 CST,这个和数据库对应,没有问题。 Figure 3. 与 SA 沟通 配置检查正常,那么只好在本地搭建环境,重现问题,再寻求解决方案。由于项目是基于 Spring Boot 2.3.7.RELEASE 开发的,相关依赖也尽量使用 Spring Boot 指定版本的,所以,很快把开发环境搭好了。 在配置服务器环境时,遇到一点小小的问题:我一直以为有个时区名称叫 CST,就在网上去查怎么设置,结果徒劳半天也没有找到。后来上开发机检查开发机时区配置,发现是 Asia/Shanghai。将测试服务器设置为该时区,数据库内部查询时区,显示和服务器一直。 调试代码中,发现 MySQL 连接驱动的代码中,有配置时区的相关代码,如下: com.mysql.cj.protocol.a.NativeProtocol#configureTimezone /** * Configures the client's timezone if required. * * @throws CJException * if the timezone the server is configured to use can't be * mapped to a Java timezone.
Raft 论文摘要(二)

Raft 论文摘要(二)

D瓜哥
在上一篇文章中,通过阅读 《In Search of an Understandable Consensus Algorithm》 前三节的内容,对论文的大致内容做了简介,简单说明了一下 Replicated state machines 的用途以及 Paxos 本身存在的问题。 4. Designing for understandability several goals in designing Raft: it must providea complete and practical foundation for system building; it must be safe under all conditions and available under typical operating conditions; it must be efficient for common operations. Our most important goal — and most difficult challenge — was understandability. 从这里可以看出,Raft 设计的初衷就是为了易于理解和便于构建。 There were numerous points in the design of Raft where we had to choose among alternative approaches.