简单设计:小即是美

作者: _张逸_ | 来源:发表于2016-07-04 11:55 被阅读572次

博尔赫斯说:“写散文体的短文——寓言、神话、短故事——给了我某种神秘的满足。想起这些篇章,就仿佛想到硬币:实在、结实、闪光的小物体,更多的东西的样品。”显然,小物体之美,让博尔赫斯着迷。

同样,在软件设计领域里,小的设计同样让我着迷。这里所谓的“小”,并非绝对的小,而是强调一种恰如其分的设计哲学。在开发过程中,每一次迭代的目标不宜设立过大,需小步前行,避免过度设计。在设计开发时,整个系统最好由松散耦合的细小模块组成。这些细小模块由于功能相对独立而单一,因而更易于理解。

Dennis Ritchie

在设计系统架构时,我们要注意克制做大做全的贪婪野心,尽力保证系统的小规模。Unix的缔造者之一Dennis Ritchie就曾遭受过将系统做大做全的滑铁卢。他在贝尔实验室的第一个任务,是参与大项目Multics,即开发一个前所未有的、可以多人使用的、同时运行多个程序的操作系统。该项目由贝尔实验室、麻省理工学院和通用电气公司三方联合研制,但是由于设计过于复杂,迟迟拿不出成果,1969年贝尔实验室宣布退出。

痛定思痛,Dennis Ritchie和同事Ken Thompson之后在设计Unix时,就吸取了Multics设计复杂而导致失败的教训,提出了"保持简单和直接"(Keep it simple stupid)的原则,即所谓KISS原则。

遵循KISS原则,整个Unix系统由许多小程序组成,每个小程序只能完成一个功能,任何复杂的操作都必须分解成一些基本步骤,由这些小程序逐一完成,再组合起来得到最终结果。表面上看,运行一连串小程序很低效。但是事实证明,由于小程序之间可以像积木一样自由组合,所以非常灵活,能够轻易完成大量意想不到的任务。而且,计算机硬件的升级速度非常快,所以性能也不是一个问题。另一方面,当把大程序分解成单一目的的小程序,开发变得容易,Unix在短短几个月内就问世。

我们千万不要轻视小的力量。

专注的小可以保证独立进化

从“自治”思想看,它需要实现一定程度的自给自足,并保证对外交互的接口足够稳定。这符合老子的“大国小民”的思想。

这种专注的小首要在于分离职责。一种分离的角度是以“内外之分”观察核心与边缘的职责,然后以模块分离的方式分别为它们寻找到“安身立命之所”。在框架设计上,为保证框架的小,我们常常采用这样的观察视角,这就是所谓的“内核模式”,通过识别出整个框架的核心功能,以此作为整个框架的基础,而其余功能皆可视为框架的外围功能,根据关注的域对其进行切分。这些外围功能互相之间应尽量减少耦合,使其能够独立进化。

内核:即多个集合的共同交集

Spring框架的设计正是遵循了这样的设计理念。除了Spring IoC是整个框架必备的组件之外,Spring MVC、Spring Batch Job、Spring Data等之间没有依赖关系,可以根据项目自身情况酌情裁剪。

那么,如何才能保证设计的系统足够小?首先,在设计思想上要确立“小即是美”的美学观,要清晰地辨别且能够欣赏小的灵活之美完整之美轻盈之美。只有在思想上认同它,你才能顺势而为;只有从心理上感受到这种美丽,你才能响应它的召唤。

灵活之美,在于它能快速地响应变化,这种变化可能是局部的,也可以是整个设计方向的改变。例如,在多数企业系统和互联网系统中,都需要分离Online和Offline任务,以指定不同的架构决策。又例如,我们可以设计独立的、具有最小功能子集的Batch Job来承担后台任务。这些Batch Job可以作为一个单独的应用程序执行在单独的进程中。一旦需求要求我们对设计做出改变,我们也能将修改控制在足够小的范围中,从而保证对整个系统不会带来巨大的影响。

若遵循EDA(Event Driven Architecture)模式,我们可以根据业务领域的不同,设计出功能最小完整的自治组件。组件之间的通信通过事件来传播,利用发布者/订阅者的方式解除组件之间的耦合;又或者利用消息传递来处理业务逻辑,例如在AKKA中,我们可以设计出灵活而小的Actor对象;微服务(Micro Service)架构则从服务级别展现了设计的灵活之美。

轻盈之美,体现在它的功能并不臃肿,对外部的依赖较少,既容易在系统中快速引入,又不会使原有系统变得笨重,还能很方便地部署或者启动。

展现了轻盈之美的组件往往具有良好的可测试性。我们可以利用六边形架构将系统分隔为内、外两个边界,凡是系统对外的通信,皆通过端口(Port)和适配器(Adapter)完成,这样就能较好地解除对外部环境的依赖,提高系统的可测试性。而清晰的边界划分也是设计小组件的一种有效手段。

六边形架构:Port-Adapter模式

若对于框架或平台而言,则需要尽力降低框架或平台的侵入性。当年Rod Jonson之所以提出J2EE Without EJB,正是因为EJB的侵入性带来了诸多病症。当然,从另一个角度来讲,我们自己研发的产品或项目也要尽可能摆脱对外部资源的依赖,即所谓“稳定依赖原则”。Robert Martin提出的Clean Architecture清晰地勾勒出这样的思想。在Clean Architecture的表述中,他让外部易变的部分依赖于更加稳定的部分,如域模型,而非形成相反的依赖关系。这样还可使实现变得更易于变化;多变的部分依赖于稳定的部分。好架构就要能轻松地改变那些易变的决定

Clean Architecture

完整之美,在于它是自足的。完整并不意味着大而全,而在于它足够精简,没有冗余。当然,它同时应该是没有残缺的。残缺,意味着它无法在没有外部支持的情况下,完成自己应该完成的工作。这种美感符合“麻雀虽小,五脏俱全”的标准。Standalone的微服务,正好体现了这种自容器的完整之美。

小的益处还有一点,它可以使得我们在架构决策或技术选型时,可以变得更加从容。

譬如说,因为某些原因我们需要将整个企业系统(Monolithic架构)从WebLogic上迁移到JBoss上,无疑,这是一个艰难的决定,实施起来更是一个漫长的过程。如果系统是基于Micro Service的架构风格进行构建,每个服务根据各自情形选择自己的技术栈。倘若需要对某些服务进行技术栈迁移,相信这个问题不再变得棘手。——大象可以轻盈地跳舞,但付出的努力会百倍于一只敏捷的狐狸。

如今,Java已经发展到Java 8,引入的Lambda表达式等多个特性如此鲜嫩,让人垂涎不已。然而据我所知,国内多数企业的Java项目仍然停滞在JDK 6裹足不前。是JDK 8不够好吗?非也。盖因为求稳的他们仍然心存顾虑。即使Oracle号称这种JDK的迁移多么的平滑,多么的稳健,多数企业仍然不敢轻易做出迁移的决定。若因为迁移而带来未知的缺陷,可谓得不偿失。既然现在项目运行良好,何必冒此风险。

于是,我们这个行业因为系统的庞大而变得守旧老成,亦步亦趋。并非大家没有冒险的精神,实则是庞大的项目难以灵活地改变方向。倘若只是更新系统中的某一个库或框架,形势就截然不同了。记得在没有lambda的时代,当我们让客户看到了Guava的好处时,要引入Guava就轻而易举,真如顺水推舟了。

当我们发现某些功能具备独立和专注的特征时,都是可能做出小系统的机会。这些小系统并不一定是子系统或模块,它还可以是一个独立的应用或服务。

例如在一个税务系统中,需要生成复杂的税务报表。它的整个逻辑是相对独立的,不管是报表的动态生成,格式的转换,数据的查询以及流的处理和PDF文档的生成,都与系统其他部分关联不大。唯一可能与系统存在紧密关联的是数据库。但为了解决高峰期的性能问题,我们可以建立单独的数据提取器,又或引入流处理,定期将数据提取出来,放入内存数据库中。将这样相对独立的功能做成服务,就能够独立演化,并有效支持服务请求的可伸缩。这样的小型服务可以更灵活地应对变化。当我们发现内存数据库不能满足大量请求时,也可以轻而易举地将其迁移到NoSQL上,并根据数据的属性例如按照地域进行分区,支持水平扩展。

若要保证系统的小,我们还可以尝试使用脚本。在开发软件系统时,可以使用一些脚本语言来开发一些小工具,以应对灵活的需求变化,消除重复代码,实现某些步骤的自动化。例如用Groovy编写一些函数,用Ruby编写代码生成工具,又或者使用Gradle、SBT实现系统的自动部署,启动服务器等脚本。脚本语言具有很好的灵活性,而动态语言的特性也使得我们能够编写出短小精悍的超级小工具,甚至可以作为系统模块之间的粘合剂,如机器齿轮上的润滑油一般,让整个系统充满活力。

Russ Miles认为:团队的开发速度经常因编写代码体积和复杂度的增长而放缓。他认为组件结构在简化架构方面非常重要,并提出了Life-Preserver模型。这是一个环形结构,所有的基础设施软件都在环上处理集成,而核心业务组件在环内加入业务价值。这种模型的核心是利用事件来简化架构。

使用事件的一个显著特点是解耦,使得事件的发布者与订阅者都可以独立演化,也可以自由增加事件的订阅者数量。我们可以将事件的发布者与订阅者设计为独立的小程序,就像Unix系统中那些小工具一样,通过管道建立关联。这样的设计思想称之为EDA(Event Driven Architecture)。

当然,要做到系统的“小”,必然也是要付出代价的。奥卡姆剃刀定律认为:“若无必要,勿增实体”。剖析Kent Beck提出的“简单设计”原则,在满足了客户功能、无多余重复、清晰表达设计意图的前提下,需要遵循奥卡姆剃刀定律。盖因为系统分解得约小,就会因为“实体”数量的增加,引入额外的复杂度,包括对实体的管理、实体之间的协作等。显然,任何设计决策都有其两面性,我们需要放入到当下的上下文(Context)中做出正确的判断。正如爱因斯坦所说:“让它尽可能简单,但不要过于简单。”看来,我们对任何事情都需要把握一个“度”,水满则溢,月盈则亏,故而需要损有余而补不足。

相关文章

  • 简单设计:小即是美

    博尔赫斯说:“写散文体的短文——寓言、神话、短故事——给了我某种神秘的满足。想起这些篇章,就仿佛想到硬币:实在、结...

  • 设计原则

    1、拒绝重复代码/设计,重复的地方抽离作为独立函数或库 2、简单即是美,简单的东西意味这容易理解,容易修改。保持模...

  • 小即是美

    小即是美,船小好调头,猫有九条命,短小精悍,娇小玲珑,这些词语都表达了小的东西容易控制,具有反脆弱性。我很喜欢猫,...

  • 小即是美!

    我想为自己做一点点事,想在我每天的生命中,去发现和昨天不同的两个新鲜点!并坚持这个原则! 昨天,去看望一位做手术的...

  • unix/linux 哲学

    小即是美Linux 的哲学之一,软件开发应该力求简单,小的程序易于理解,易于组合使用。多个小程序的组合可以解决很多...

  • 人,越简单,越富有

    心灵越是简单,人生就越是珍贵和富有。多即是少,少即是多。简单到极致,才是生活的大智慧,才是生活的大美。 1664年...

  • less is more_简单即是美

    很多女生对于搭配衣服很是头疼 不知道在色彩上如何选择…其实你们知道吗?有一种可以同色系搭配的衣服 也是很实用的 特...

  • 互联网思维:商业颠覆与重构

    互联网发展太快了! 专注、极致、口碑、快 标签思维、 简约思维:少即是多,简约即是美、简约而不简单 NO.1思维:...

  • 美即是真,真即是美

    约翰·济慈(John Keats 1795-1821),出生于伦敦,是英国杰出的浪漫主义诗人,与雪莱,拜伦齐名。 ...

  • 美即是真,真即是美

    题记:我对肉眼看不到的世界充满着好奇。 拉莫娜详细描写了自己第一次读《审判》时的情景。约瑟夫不知道自己犯了什么罪行...

网友评论

    本文标题:简单设计:小即是美

    本文链接:https://www.haomeiwen.com/subject/rwbcjttx.html