架构整洁之道导读(一)

我是《架构整洁之道》(Clean Architecture) 中文版的技术审校者,在审校的过程当中略有感悟,所以希望通过撰写导读的方式分享给大家。

书名的由来

《架构整洁之道》是Clean Architecture的中文译名。看似简单地延续了《代码整洁之道》(Clean Code)的翻译传统,但事实上,对于取中文名字这件事,我们还是花了不少气力的。拿到译文初稿时,编辑提供了几个备选的译名:《架构简洁之道》,《架构至洁》和《Clean Architecture》,这些名字各有各的考量,在没有了解这本书的核心思想之前,我也没有办法给出恰当的判断。所以在通读了原作和译作之后,我在ThoughtWorks咨询群里发起提案,讨论的过程很精彩,最终在骨灰级架构师新哥的建议下,结果大致趋向了整洁架构。

新哥说:“整本书在说依赖治理(管理),也就是如果降低依赖复杂度,和DDD中分离子域分层架构等想法是一致的;如同你整理你的房间,把东西分门别类放好,从这个角度,整齐比简单更合适,或者清晰也可”。所以我最终合并了整洁和清晰两个词,用整洁二字概括之。

除此之外,对于《架构至洁》这个候选项,大魔头的态度是架构不要提至洁,总让人感觉脏脏的。个中深意,自行体会。而读MBA的岳岳和XR(XR说他没读过MBA)从用户思维出发,认为《代码整洁之道》和《架构整洁之道》可以相互增强记忆,更容易激发用户的购买行为。

即便敲定了“整洁架构”,大家对“之道”也有不同的看法。《代码整洁之道》对应的原标题和副标题分别是Clean Code - A handbook of Agile Software Craftsmanship,而《架构整洁之道》对应的原标题和副标题分别是Clean Architecture - A Craftsman's Guide to Software Structure and Design。我们知道“道”是一种形而上的精神层面,老实讲,把Craftsman(手艺人)译做“道”是有点夸张的。

形而上是精神方面的宏观范畴,用抽象(理性)思维,形而上者道理,起于学,行于理,止于道,故有形而上者谓之道;形而下是物质方面的微观范畴,用具体(感性)思维,形而下者器物,起于教,行于法,止于术,故有形而下者谓之器。

道法术器择其一?其实凡事总有权衡,遵循前人的译法往往不会太坏。就像鲍勃大叔书中总结的稳定依赖原则,当我们依赖一种译法次数越多,它就更加稳定,这种稳定先不说能否形成品牌效应,单是SEO就能省去不少功夫,何乐而不为呢?

鲍勃大叔的文字平铺直叙、浅显易懂,尤其喜欢用他自己生活中的经验做例子。而且这本书是没有知识断层的,即便是初级程序员,也能在鲍勃大叔的循循善诱里,慢慢形成新的认知。因为他总是从最基础的知识点切入,自底向上,一步步地搭起架构的形状。

范式的实质是约束

编程范式是程序员喜闻乐见的话题,就像Vim和Emacs编辑器地位的旷日之争。它们的沉浮过往俨然就是风云诡谲的江湖。结构化编程英雄迟暮逐渐淡出程序员的视野,觊觎已久的面向对象编程(OOP)以迅雷之势称霸武林,独居一隅的函数式编程(FP)隐忍多年终于等来了一次机会。2012-2014年,江湖唱衰OOP的声音不绝于耳,FP就像一名拯救程序员于水火的侠士想要撼动这片天地。硝烟过后,眼前却不是你死我亡的惨状,而是你中有我、我中有你的大团圆结局。当Java这位OOP的保守党融汇了FP的特性lambda表达式,这场范式的冲突之争也算落下了帷幕。

程序员谈编程范式,喜欢党同伐异,作为FP的拥趸,我也不例外。可是鲍勃大叔却娓娓道来,所谓编程范式不过是约束程序的执行,告诉我们什么不能做而已。

  1. 结构化编程是对程序控制权的直接转移的规范和限制
  2. 面向对象编程是对程序控制权的间接转移的规范和限制
  3. 函数式编程是对程序赋值操作的规范和限制

Goto considered harmful

GotoConsideredHarmful

学习C语言编程的第一天,老师就告诉我们不要在程序中使用goto语句,因为goto会破坏程序的结构化。Dijkstra在论文Go To Statement Considered Harmful中证明了goto语句阻止了将大程序递归分解成更小的可证明的单元,这意味着大量使用goto语句的程序是不能被证明的。这里,不能被证明的语义是不可判定,类似说谎者悖论——“我在说谎”这句话不能被证明和证伪,所以不用goto其实保证了小的程序单元可判定。可惜的是,Dijkstra并没有证明程序单元,这项工作被另一项日后广泛使用的科学试验方法——测试取代了。在保证程序单元可判定的前提下,测试是一种可以对其可证伪的科学方法。例如,命题“天下乌鸦一般黑”就是可以被证伪的,虽然我们不可能枚举天下所有的乌鸦,但是直到哪天出现了一只白乌鸦,我们就可以说这个命题是错误的,这个过程就是证伪。Dijkstra所言“测试只能说明bug存在,而不能证明不存在”也是同样的道理。

测试可以保证,在当前已知情况下程序单元是正确的。一旦有新的测试用例导致程序单元出错,那么我们就可以修正程序,让程序更加接近真相。这或许就是TDD(测试驱动开发)的妙处所在。

去除了goto语句之后,我们发现具备顺序,循环和分支判断能力的计算过程还是图灵完备的,也就是说goto的有无并不会影响计算能力。那么goto的在程序中的作用便是弊大于利的。再加上goto的滥用会导致程序结构容易混乱,不利于程序员理解,这更得尽力避免。所以结构化编程限制了对程序直接转移的控制权。

Pointer considered harmful

PointerConsideredHarmful

人人都知道面向对象编程有三大特征:封装,继承和多态。

封装是为了构造抽象屏障(Abstract Barrier),到达隐藏信息的目的。任何编程范式都不会缺少封装,因为这是人的需求,是人类简化问题认知的方式。

继承是一种函数(过程或者API)复用的方式,以前我们想在多个结构相似的数据上使用同样的函数,需要通过强制转换到函数可接收的数据类型(结构体指针)上,这必然存在风险。面向对象的世界里,我们不再需要手动强制转换,只要通过显式地表明继承关系,编程语言就能在运行时自动做到这点。

多态(polymorphism)是一种将不同的特殊行为和单个泛化记号相关联的能力,和多态概念对应的参考实现——运行哪段代码的决策叫做分派,大部分分派基于类型,也可以基于方法参数的个数及其类型,而分派的具体执行过程则仰仗函数指针。当作为单个泛化记号的函数被声明出来,它的具体实现可以多样化。通过这样的记号,事实上,我们解耦声明和实现,而这种解耦的过程恰恰是通过函数指针间接地找到目标函数完成的。所以面向对象编程限制了对程序间接转移的控制权。

Mutability considered harmful

MutabilityConsideredHarmful

Neal Ford在《函数式编程思想》(Functional Thinking)中提到面向对象编程是通过封装可变因素控制复杂性(makes code understandable),而函数式编程是通过消除可变因素控制复杂性的。函数式的一个显著的特点就是不可变性。但是依据常识,不可变性往往意味着更多的内存消耗和更差的性能。其实不尽然。像Scala,Clojure这些基于JVM上的函数式编程语言大量使用了持久化结构(如:Persistent Vector[1]),在不损失效率的前提下,实现了不可变的数据结构。这样的数据结构在高并发的环境下具有非常巨大的优势,尤其相对于面向对象编程中为人所诟病的临界区和竞态条件。

不可变的数据结构是无法重复赋值的,所以函数式编程限制了对程序的赋值操作。

小结

综合上述关于编程范式的观点,鲍勃大叔一针见血地指出,过去50年我们学到的东西主要是什么不应该做。这等于给全书奠定了基调,以此类推,其实良好的架构也在传达同样的道理——什么不应该做。

我一直留有一个问题:为什么要从编程范式开始谈起?在审阅完整本书过程中,我慢慢发现鲍勃大叔其实在传递一种设计理念:架构设计里,自顶向下的设计往往是不靠谱的。就连本书的目录也在言说同样的逻辑,从程序的基础构件,谈到组件,最后才谈到架构,这个涌现的过程非常符合系统之美[2]中描述的系统的自组织特征。

可是,为什么自顶向下的设计往往不靠谱?本书的第4部分“组件构建原则”会有部分答案,且听下回分解。


[1] 架构整洁之道导读(二)组件聚合
[2] 架构整洁之道导读(三)组件耦合

于 2018-10-21

架构整洁之道

  1. 函数式编程简介

  2. 系统之美

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,193评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,306评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,130评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,110评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,118评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,085评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,007评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,844评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,283评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,508评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,667评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,395评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,985评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,630评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,797评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,653评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,553评论 2 352

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 172,061评论 25 707
  • 用两张图告诉你,为什么你的 App 会卡顿? - Android - 掘金 Cover 有什么料? 从这篇文章中你...
    hw1212阅读 12,711评论 2 59
  • 现实生活中,我们认为的成熟并不是变得简单了,而是变得复杂了。 虽然很多人都知道,简单可以带来快乐,但...
    阿辉Ahui阅读 204评论 0 0
  • 一如既往的007不写就出局作业雨来了,继续记录起来吧!点评94班战友~@黄新蒲|007-7103|践行 点评战友新...
    ElingHo期待的美好日常阅读 94评论 0 0
  • 人性到底是什么?孟子说:人性本善。荀子说,人性本恶。后世对此争论不休。有人说人性善中有恶,有人说人性恶中有善,也有...
    禾麦清风阅读 2,560评论 0 1