关系经济人类预测化学自然
中准网
自然科学
知识物理
化学生物
地理解释
预测理解
本质社会
人类现象
行为研究
经济政治
心理结构
关系指导
人文遗产

简单是容易之母

12月12日 喵小咪投稿
  前言
  本文整理自Clojure语言发明人RichHickey发表于2011年的一次题为《SimpleMadeEasy》的演讲,该演讲虽然年代久远,但一直备受推崇,也曾推荐为每个程序员都要看的十大技术演讲之一,可以说是相当经典。
  在这次演讲中,RichHickey从辨析简单和容易的词义开始,清晰地指明了它们的辩证关系,以及复杂性的根源,同时也给出了如何构造简单系统的方法,以及我们使用的语言中,哪些是可以用来帮助我们构造简单系统的工件,而哪些又蕴含着复杂性。整个演讲风趣幽默,又不乏金句,虽然并不一定所有的观点都正确,但足以带给我们很多启示,值得反复观看,每次可能会有不同的收获。
  RichHickey提要
  由于文章篇幅较多,又有很多晦涩难懂的地方,赶时间的同学可以看看这些核心观点:软件和其构造是不同的层面。软件面向用户,追求的是功能、质量和可靠性,重点在对问题域的求解能力,而其构造(代码)则面向开发者,追求的是易于理解、易于更改、易于扩展等。我们无法将可靠性建立在我们不理解的东西上,我们应该以简单作为构造目标,因为简单是可靠性的先决条件。简单常常被误认为容易,实际上是完全不同的。容易表示近在咫尺,唾手可得,其反面是艰难。而简单则是复杂的反面。简单具有客观性,而容易则和具体人相关。复杂表示事物缠绕编织在一起,而简单则只专注于某一方面。语言中像状态、方法等很多工件都编织了不同的东西,具有一定的复杂性。我们应该用函数、值等相对简单的工件来构造系统,以达到简化的目的。简单与容易的关系
  简单是可靠性的先决条件。埃德舍尔迪克斯特拉
  如果我们需要建立一个好系统,那么应该建立的是一个简单的系统,而这一点通常不被我们重视。
  研究单词的起源很有意思,可以让我们了解它的本义,从而更精确地使用它。
  Simple(简单)这个单词由sim和plex两个词根组成,表示一次折叠。它的反义词Comlex(复杂)则表示多次折叠、编织在一起。
  常常与Simple(简单)混淆的一个词是Easy(容易)。而Easy首先关联到古法语单词aise,又(被RichHickey强行)追溯到拉丁语单词adjacens,找到它的本义为躺在。。。附近。而Easy的反义词为Hard(艰难),词义并不是躺的很远,而是曲折。
  那么,什么是简单的东西呢?
  简单的东西应该只有一个角色,它们只完成一项任务,或是只有一个目标,只关乎一个概念,一个维度,比如安全性。
  当你在寻找简单的东西时,你希望它专注于某一领域,而不是把东西组合在一起。
  但是我们也不能机械地执着于一个,简单并不意味着只有其中之一,并不意味着接口只有一个操作时才称得上简单。简单最重要的特性是没有交织,而不是只有一件事。
  简单还有一个重要特性,那就是客观性,和具体人没有多大关系,这是和容易显著的区别。
  再来看容易。
  上面说了,容易的本义是就在附近,意味着物理上很接近,唾手可得,手到擒来,易如反掌等等。
  容易也可以引申为与我们的理解接近,或者就是我们已经拥有的技能,就是对我们来说很熟悉。
  区分简单和容易还有一个关键点,那就是容易是相对的,拉小提琴对于某些人来说很容易,而对于大多数人来说很难。所以,容易是一个相对术语,是主观的。软件开发领域对简单的误解
  对于软件,首先要区分制品和构造。
  制品是软件用户所关注的东西,功能是否好用?性能如何?这些都是软件制品的属性,而不是其构造的。用户不会看着我们的源代码,说这太令人愉快了!
  但是,对于软件开发人员来说,软件构造的使用体验却是需要关注的。我只需要输入几个字符,就可以添加新的特性!,这种便利性是我们需要关注的。
  对于老板来说,除了关注软件制品的特性外,同样也会关注软件构造的便利性,会考虑程序员的可替代性。
  然而,人们关注软件构造的容易性时,主要关注的是对代码、库、工具的熟悉程度,而不是代码的简单性。简单对软件开发的重要性
  我们只能把可靠性寄希望于我们能够理解的东西上。而这通常是需要做出权衡的,因为太注重扩展性和动态化的东西可能在理解上就变得不容易。
  然而,我们的理解能力总是有限的,对于那些我们试图理解并需要确保正确的事,终会受限于我们的理解力。我们只能同时处理少数事情,当许多事情纠缠在一起时,我们就无法单独对待其中一个。
  如果每次我认为我拿出软件的一个新部分时,我需要理解它,然而它与另一件事有关,我不得不把另一件事拉到我的脑海中,因为我无法撇开其中一个思考另一个。这就是它们纠缠在一起的本质。因此,每一个相互纠缠的因素都在增加我们理解事情的负担。所以,从根本上说,这种复杂性,我的意思是这种事物的相互牵扯,将限制我们理解系统的能力。
  介于这种情况,我们将如何来修改已有的软件呢?
  我在今天的一次演讲中听说,敏捷和极限编程已经表明,重构和测试可以使我们能够以零影响进行变革。我不能确定,这实际上不是一件可知的事情。有测试保障,并不鼓励不加小心地修改代码。
  如果你要修改软件,你需要分析它的作用,并决定它应该做什么。你知道,我的意思是,至少你将不得不去问,这种潜在变化的影响是什么?我需要去软件的哪些部分来实现更改?无论是使用XP还是敏捷或其他任何东西,都不能回避这个现实问题。如果你不能对你的程序进行推理,你就无法做出这些决定。
  对于软件来说,通常都需要做两件事情,一件是添加新功能,另一件则是修补现有功能。
  让代码通过类型检查,通过所有测试,这是一种护栏编程,并不能为我们指引方向,引导我们到达期望的目的地,我们必须对程序进行推理。
  什么样的跑步者能从比赛一开始就跑得尽可能快?答案是只有那些短跑的人。
  在软件开发中,如果你忽视复杂性,你终究会放慢脚步,时间越长越是这样。
  当然,如果你正在做一些非常短期的事情,你不需要任何这些。你甚至可以用1和0来写它。
  对于大多数软件项目,如果选择了容易,会很快有进展,但随着时间的推移,累积的复杂性最终会把项目扼杀掉。你每次只能进展一点儿,而多数时候在重复已经做过的事情。而如果选择了简单,项目启动速度会变慢,因为必须在开始之前对问题进行一些思考。
  容易的东西也可能是复杂的,我们经常会碰到描述简洁、熟悉且易于使用的复杂构造,我们把这种复杂性称为偶然复杂性。
  具备简单性的软件有什么好处呢?至少是容易理解的,也是可以轻松更改的,调试起来也很方便,最终也带来了灵活性。
  通过模块化和将事物分开,将赋予我们调整和移动它的能力。当我们让事情变得简单时,就会在决策上拥有更大的独立性。
  拥有一个测试套件和重构工具会让改变编织的城堡比改变乐高城堡更快吗?不可能。
  如何让事情变得简单?
  我们可以学习更多的东西,通过熟悉来让各种事情变得容易,但是我们不能让我们的大脑变得更聪明,必须通过简化事物来接近它。
  即使最了不起的杂耍演员,也最多在空中抛9到12个球,但是不能多达20或100个。与我们面对的复杂性相比,我们整体都处于同一级别,非常有限的级别。
  因为我们只能玩这么多球,所以必须做出决定,希望这些球中有多少是偶然的复杂性,有多少是你希望成为问题的复杂性?还能多出多少球?
  Lisp程序员知道每样东西能带来的价值,但是从没有成本的概念。
  以上是一句挖苦Lisp程序员的话,也反映出了程序员只喜欢强调新工具或新方法的好处,但很少提及缺点或权衡。
  来看一下我们的工具包中的对象。
  状态(State)和对象(Object)是复杂的,而值(Value)更简单一些,许多情况下,可以用值来替换对象。
  方法(Method)是相对复杂,而函数(Function)和命名空间(Namespace)则简单些,这是因为方法通常在一个类中,在一个很小的、不好的命名空间中。
  变量(var)是复杂的,而托管引用(Mangedref)相对简单。
  继承、Switch、模式匹配都很复杂,可选的多态策略则是简单的。
  语法是复杂的,而数据是简单的。
  ORM很复杂,而声明式数据操作很简单。
  最终一致性对于程序员来说很难,需要同时思考相关的东西。复杂的工件为何复杂?
  组合就是单纯地放在一起,它是简单的,而一旦相互交织在一起则是复杂的,将简单的组件组合起来也会是简单的,这就是编写强大软件的方式,我们可以通过模块化来创建简单的系统。
  简单意味着可以方便地垂直分区和水平分层,但是能够分区和分层并不一定是简单的,复杂的东西也可以做到,但不会带来任何好处。
  在系统中处理状态从来就不是一件简单的事,这是因为状态天然是一个由值和时间构成的交织体,你没有能力脱离时间去获取值。
  状态的复杂性是无法摆脱的,即使用上了模块化的方法,因为有状态的东西封装起来还是有状态的。你每次使用相同的参数去调用它,然而得到的却会是不同的值,复杂性就油然而生。相当于你每次问它相同的问题,却总是得到不同的答案,这就是复杂性。
  请注意这种复杂性和并发性无关,我们谈论的是你如何理解你的程序。
  一些闪亮的新语言,也有变量和引用,但是却没有让状态变得简单。
  另一些把不可变作为默认特性的语言,大大减少了对状态的使用,是非常好的。
  而Clojure和Haskell在这方面就显得特别优越,它们通过一些小的构造将时间和值组合在一起,并提供某种抽象来通过时间获取到值,真正回到了简单的路上。
  首先是状态,它将时间、标识和值三者混编在一起,让我们无法分解开来。
  方法则编织了函数和状态,甚至在有些语言中还将命名空间编织进来。
  语法则编织了含义和顺序,无论你多么喜欢你使用的语言中的语法,它都不如数据简单。
  继承则编织了类型,将两个类型彼此编织起来。
  Switch和Match(匹配)将多对谁将做什么以及将发生什么编织在一起,并且局限在一个地方完成所有这些操作,这非常糟糕。
  变量会将时间和值密不可分地编织在一起。我们只能从内存地址获得一个单词、标量,却无法获得一个复合对象。
  循环编织了你正在做什么和如何做这两件事。高阶函数也同样地暗示了事物的顺序。
  条件判断散布在整个程序中,编织了整个程序的组织结构。如何用简单的东西编写复杂的系统?
  获得更简单生活的第一步就是选择更简单的东西。
  如果你想获取一个值,多数语言都有声明不可变值的语法,如final、var等。但是比较困难的是获得一些值的聚合,你需要一种叫可持久化数据结构的东西,这时就要寻找一个好的库,或默认具有这种特性的语言(指Clojure)。
  函数也是一种简单的工具,多数语言都支持,它就像是无状态方法。
  命名空间是真正需要语言做的东西,而多数语言做的并不好。
  数据其实很简单,多少年来,数据的本质没有太大变化,还是Map、Set、线性表、顺序数据这些。但是我们创建了数十万个变体,这些变体与本质无关,却难以操纵。我们应该操纵数据的本质,这并不难。
  编程不是打字,而是思考。
  我们如何设计简单的东西?首先就是使用简单的构件。
  但我们有时必须编写自己的构件,如何抽象才能简单呢?要一次又一次地把一些东西拿开,将事物的物理特性剥离出去。
  有时人们通过抽象粗暴地隐藏一些东西,这不是抽象的本质,不会真正地帮助到你。
  关于如何正确抽象,可以从两方面进行。首先是去做5W1H分析,把这些东西分别列出来,然后通过回答这方面是关于谁的这是关于它的哪一方面这些问题来将事物拆开。然后是通过确定哪些东西我不知道,也不想知道来把它们解开。
  〔微风〕What
  What就是操作,就是我们要完成的事。我们所要做的就是,为功能、由相关功能组成的功能集赋予一个名称来形成抽象,可以用手头的编程语言支持的任何东西来实现它,如接口、协议、类型类等。所以,抽象就是一组功能的规格声明。
  但是抽象应该非常小,比我们通常看到的都要小。分解包含巨型接口的程序将困难很多,最好将它们多态化。
  这些抽象只是规格声明,而不是实现。所以,要只通过值和其它抽象来定义它。
  最重要的是,抽象表达的是What(是什么),千万不要和How(如何做)编织在一起,将它们严格区分开来,是为他人避免问题的关键所在。
  〔微风〕Who
  Who指的是数据或实体,这是我们的抽象最终要连接的东西,用来实现抽象。
  在构建较大的组件时,将子组件作为参数传递,不要将他们硬连接到他们的父母身上,以提升灵活性。
  要使用更多而不是更少组件,以利用小接口的简单性。
  不要将组件和组件之间、实体和实体之间编织起来,不要尝试去了解对方的细节,从而避免提升复杂度。
  〔微风〕How
  How代表的是如何做,是真正用来完成工作的代码。最好用多态性将它们和抽象、实体连接起来。如果使用了switch和模式匹配,那么就会带来把所有东西都混在一起的问题。
  要尽可能地隔离实现,避免和其它任何东西编织在一起。
  〔微风〕When、Where
  关于何时、何处的简化规则很简单,就是不要把任何东西和它们编织起来。但是,人们在设计一些直接连接对象的系统时,问题就会溜进来。如果A调用了B,那么你就把它们编织了起来。调用时,你需要知道B在哪里,而A什么时候调用B。
  解决这种问题的方法就是使用队列(Queue),如果您没有广泛使用队列,则应广泛使用队列,你应该立即开始。
  〔微风〕Why
  Why是关于程序的策略和规则的部分,这部分是很难简单化的。我们通常将它们直接放在应用程序中,如条件判断、控制流等。这样,当你与用户讨论应用是如何做的时候,就必须坐下来一起看源代码,这非常困难。
  为此,你需要把这些东西放在系统外面,比如使用声明式或规则引擎系统,来保持简单。
  〔微风〕信息
  对象不是被设计用来作为信息载体的,不要把对象用于信息,它是复杂的,会破坏我们构建通用数据处理的能力。
  ORM也将业务逻辑与数据展现编织在一起,带来了复杂性。
  所以,数据就是数据,把它放在那里,语言中如果有Map、Set,直接用它们就好,不要专门为信息创建类。
  〔微风〕Work
  我们选择简单的工具,写出简单的东西,有时不得不去简化别人的东西,简化问题空间或者别人写的代码,这本质上也是一种解开。总结
  我们的底线是把简单性当成我们的选择。我们天生有一种复杂性的文化,要把简单作为选择,需要时刻保持警惕,需要足够敏感和保持关注,必须培养对纠缠的敏感性,必须拥有一个纠缠雷达。
  在开始之前,我们需要花一些时间对事情进行简化。在简化事情的过程中,我们往往会得到更多的东西。简单并不是数量少,我们宁愿让更多的东西整齐划一,而不是让少数东西纠缠在一起。把这些编织的东西分开的美妙之处在于你可以获得更多的能力。
  简单是最复杂的。莱昂纳多达芬奇。
投诉 评论 转载

极简生活之消费降级今年我基本没买过衣服,自己年初立的不买衣服的flag,还算执行得不错。目前家中欠110万的商业贷款,和90万的公积金贷款,我们计划在4年内还清商贷,在月供过万的基础上,一……女排最佳自由人林莉家贫志不贫,挣钱为父母买房,王梦洁的榜样原生家庭是每个人生命的最初,也是人生中至关重要的关系,原生家庭对一个孩子的影响是一生的,它不仅塑造了孩子的性格,也会决定孩子的起点,这种潜移默化的影响也会伴随着孩子的一辈子。林……Ok组合被称为最强二人组,厉害之处在哪里?他们的厉害之处在于奥尼尔和科比两位球员在内线和外线都是无敌的存在。大家对于奥尼尔和科比都是非常熟悉的,大鲨鱼在内线就是一个bug,横冲直撞无人可挡,科比更不用说了作为联盟响当当……SHUii水爱好花洒,让生活拥抱温暖随着经济水平的提高,在洗浴方面,用户的要求也在不断提高。普通的花洒功能单一,已经不能满足人们的需求,现在市面上的恒温花洒,制作精良美观和功能更加人性化,深受用户喜爱。新一代健康……轻体的利器膳食纤维看膳食纤维如何解秘,让你一身轻松轻体减重期间,能量摄入少,肠道蠕动减慢,往往会出现一减重就便秘的情况。加上春季干燥的天气本来就容易上火,如果在饮食上不注意的话,就会加剧便……芯由我生,华为超导量子芯片实现弯道超车,喜迎突破头条创作挑战赛芯片,人类最高智慧与顶尖科技的最终结晶,素有工业粮食,经济血液,电子产业基石之称,一颗小小的芯片制约之一个国家的科技发展,更能阻挡经济前进的脚步,更是占据一……立秋后,不管贫富,别忘记吃这肉,营养全面,适合贴秋膘虽然迎来立秋节气,但是还没有结束酷暑时节,现在还处于三伏天阶段,一股股热浪袭来,让人皮肤都晒黑了,经常容易出汗,身体特别不舒服,身体的钾元素大量流失,影响全家人的胃口。立……简单是容易之母前言本文整理自Clojure语言发明人RichHickey发表于2011年的一次题为《SimpleMadeEasy》的演讲,该演讲虽然年代久远,但一直备受推崇,也曾推荐为……龙江航空几岁小孩坐飞机能无人陪伴,龙江航空无人陪伴儿童票价格关注〔航旅在线〕了解更多出行小技巧。众所周知,儿童机票要比成人票更便宜,但较少人知道航空公司还有无人陪伴儿童机票,其机票价格与成人票也有区别,并且和普通儿童票的服务也有些……自然最新封面研究发现最古老DNA新民晚报讯(记者姜燕)《自然》(《Nature》)杂志发布的最新封面研究论文显示,研究团队分离出200万年前的环境DNA片段,而曾经发现的最古老DNA序列时间是120万年,几乎……约基奇,想走就走吧!这一次,掘金是真对不住你啊掘金本大好局面,现在却因为小波特的顶薪合同,直接切断了自己的退路。拥有说是顶薪,用潜在的垃圾合同来形容,其实更加贴切。只打了9场,背部老毛病又犯了,传言将接受……你知道中国前十大央企都在哪吗?说到我国前十的央企大家可能都会想到中国烟草,但是中国烟草却不在其中。因为中国烟草不参与排名,而且它属于国企。中国烟草总公司是全民所有造企业,是全国性的农工商贸一体化的、具有法人……
04月16日NBA附加赛鹈鹕vs快船全场录像Mysql的安装中国多地迎来迁徙候鸟绘成一幅幅美丽和谐的生态画卷曹文轩细米读后感三篇你知道怎么吃鸡肉养生娇韵诗双萃精华怎么把内管的挤出来娇韵诗双萃精华用姚明是NBA2002年的状元,他那一届有哪些大神,成就如何?小青菜长虫能吃吗福斯特合伙人建筑事务所近几年完成的4个中国作品2023年石家庄马拉松开跑在即这些你需要知道毛主席画像会挂在天安门广场上久?其实邓公早已经给出了答案SpringBoot整合websocket实现及时通信聊天
非法鉴定胎儿性别罪如何处罚?牢记辅食添加3句口诀!比吃肉更重要,千万别忽略2023,开启新征程母儿血型不合溶血病要做哪些检查秋天多给孩子炖鱼汤,补营养防秋燥,教您正确做法,肉嫩汤鲜初二班主任工作总结肾结石碎石要多少钱(肾结石体外超声波碎石多少钱)【诚邀】2019。境外非政府组织合作与共进研讨会报名开启啦!怀疑家中老人患失智症做儿女的该怎么办?空调漏水是什么原因?空调漏水怎么处理?老年人如何有效预防骨折柳叶马鞭草和薰衣草的区别,4大外形特征区分两者

友情链接:中准网聚热点快百科快传网快生活快软网快好知文好找菏泽德阳山西湖州宝鸡上海茂名内江三亚信阳长春北海西安安徽黄石烟台沧州湛江肇庆鹤壁六安韶关成都钦州