我怀揣无知来到世界, 在无知中生活, 最后怀揣无知离开世界; 善意地深明自己的无知, 才懂得更谦和地处世。
人的终生必定伴随无知而度过, 要学习, 却不可以充塞的知识片段为炫耀资本;
知识是无止境无穷尽的; 唯有掌握做事处世的方法和道, 才能应对幻变的环境;
技术的极限是以已知推出已知, 即"显而易见的隐而不见"领域; 因此, 技术的极限是理解, 而不是智慧;
要生成智慧, 必须超越技术层面, 借助直觉、经验与领悟, 怀揣清明之心, 进入隐而不见的领域。
《犹太人思考术》 总体上是启发人具备一种“迫于环境, 通过对人生的精明而敏锐的观察和思考, 从而脱离困境的方法”。 在超越现实的层面上思考, 引入新的要件, 改造情势, 从而为解决问题引入新的可能。谨慎观察现实, 是这种思考方法的精髓之一。
人生面对的四大问题领域:
显而易见的显而易见领域 —— 信息;
显而易见的隐而不见领域 —— 理解;
隐而不见的显而易见领域 —— 智慧;
隐而不见的隐而不见领域 —— 崇敬。
一种理解是, 前面的“显而易见”是指形式、载体; 后面的“隐而不见”是指内容、实质。 一个事物必定是形式载体与内容实质交融的结果。 但是内容实质往往是隐匿的, 必须通过形式载体去认知。要通往内容实质之路, 必定要找到承载它的形式载体。
比如一个程序发生错误了, 错误原因是内容实质, 是暂时不可知的需要探寻的问题; 而错误必定要以某种重要的形式载体呈现出来。 无法找到错误, 一个原因是其核心形式载体或部分形式载体没有通过技术手段呈现出来, 被遗漏或忽略了,是隐而不见的显而易见 , 如果能够呈现出来, 就很容易定位到错误原因; 另一个原因是, 错误的形式载体呈现出来了, 却没有意识到其重要性, 是显而易见的隐而不见, 如果能觉察到这种关联, 也可以定位错误原因。 两种原因都使得人错过了找到解决问题的契机。
通过对四大领域的探索, 人的思维认知可以突破常见的逻辑层面, 具备更宽广更深邃的视界, 进入到世界的真实面貌。
显而易见的显而易见领域: 感官所及, 信息、知识; 原始文本, 精确写实; 忠于现实。
—— 我看到了, 它就是这样, 没有什么特别的。
显而易见的显而易见领域, 是事物明显而具体的空间, 在这个空间, 一个单一的不明事物藏匿于巨量信息之中。 光明如此之大, 阴暗如此渺小, 一切事物都正确无误地指向一个显然的结果。
在这个领域, 要做的是无穷尽地观察、积累、记录人和事情之间的巨细无遗的知识和信息。
像考古学家、历史学家那样, 尽可能保持更多更原始的文本、事实和线索, 精确写实、全面忠于现实。
显而易见的显而易见领域, 是大量的具体可见的形式载体存在的空间, 也即我们日常所处的这个空间; 解决问题的方法, 是运用从形式载体本身学得的事物, 去创造更多的形式载体。 在这个领域, 需要留在问题的轨道里, 利用问题引出的一切可能, 重新掌握意义。
不必急于去寻求答案或论断;
用新的问题为已有问题添加深度;
以提出一个问题的方式答复一个问题;
提出一份问题清单, 已经是一种有效的答案;
永远不要用一个好问题去换取一个平常的答案。
显而易见的显而易见领域的局限性:
那些不睁眼看的人, 不具备他们见不到的事物的知识;
那些睁眼看的人, 认为他们见到的, 已是他们所能见到的一切。
显而易见的隐而不见领域: 事物之间的强关联、相似性; 类比, 隐喻,讽刺,预测; 逻辑、推理。
—— 我看到了, 可是它究竟意味着什么呢?
显而易见的隐而不见领域, 是指显而易见的形式载体通往隐而不见的内容实质。 事物的多个形式载体, 表白着某个内容实质。 以显而易见的信息与知识为入口, 通往隐而不见的内容实质领域。
你进入朋友的屋里, 看到电源插座旁边斜靠着一把帆布包起来的吉他, 帆布上有些许灰尘。 这说明什么呢? 真正爱吉他的人怎么忍心让吉他蒙尘? 怎忍心把吉他随意放置到一个位置? 说明主人并不常常弹吉他, 对吉他并没有多少真正的兴趣; 那么不弹吉他的人为什么拥有一把吉他呢? 主人并不是一个爱炫耀和摆设的人, 那很可能是他的朋友送给他的, 或者暂为保管。
一个人愁眉苦脸地蹲在路上, 他是不是遇到了经济困难? 与之交谈、打听, 了解他从哪里来、家庭背景是怎样的、为何要来这里、收入怎么样、平常和周末以及节假日如何度过、现在的目标和打算是什么、最终想去做什么, 建立对一个人、一件事或者一个主题的整体背景的了解, 所有这些显而易见的信息和线索, 都指向最终的隐而不见事实: 为什么他愁眉苦脸? 为什么他蹲在这里而不是别处?
在未获积极结果之前, 决不能停止观察、提问和了解。
通过足够的显而易见领域的知识, 辅以一定的类比、隐喻、关联、推理、想象, 可以在显而易见的世界里看到更多隐而不见的事实, 穿过无益的伪装与掩饰, 在一个更为深入宽广的世界里遨游。
没有说出的事, 其实说了;
没有做出的事, 其实做了;
没有给予的东西, 其实给了。
隐而不见的显而易见领域: 事物的弱关联往往难以用逻辑去把握。
—— 我一直就在你身边, 只是你一直没有注意到我的存在。
一个人吃冰棍, 与发动一场战争有什么关联? 一只蝴蝶与一场飓风有什么关联? 过去的你, 现在的你, 以及未来的你有什么关联? 吃冰棍几乎很难与战争扯上关联。 但是如果吃冰棍的人是希兄呢? 即使这样, 希兄吃冰棍与发动战争有什么关联? 还是不明显。 如果希兄吃冰棍时做了一个微小的手势, 或许你会觉得有一点关联了, 他的属下解读了这个微小的手势, 从而“理解”了希兄的暗示, 开始预谋一场战争。 而事实可能是, 希兄就只是在吃冰棍而已, 并没有其它的意思, 手下误读了这个含义, 发动了一次他本人都无法控制的战争; 发动一场战争, 可能仅仅是因为一个独裁者喝了酒, 大脑中枢神经受抑制, 解读到一些奇怪信号而导致的一时的非理性决策。
人往往喜欢为事情添加“逻辑合理的”诠释, 以给自己一个可以接受的答案, 填充心智的空虚, 在各种的成见、教条、诠释、评价中存活着, 越来越远离事实的本来面貌。而真正要做的, 是清除大脑的思维成见及充塞的无益之物, 保持清明虚空, 怀抱开放心态, 才能平静地去接近和认识事实的本来面貌, 不为各种“舆论”和现象所迷惑和惶恐。
隐而不见的显而易见领域是一个更为深邃宽广的世界。 相比而言, 人们现在所掌握的知识和逻辑, 还只是沧海一粟。
隐而不见的隐而不见领域:
—— 花非花, 雾非雾
一切有益的线索和关联都消失了, 一个全然未知的世界。 无法运用逻辑去把握, 只能回归本能、直觉和经验一步步去探索。 每一步都可能出错, 每一步都埋伏着危险, 步履维艰。 隐而不见的隐而不见领域就像一张巨大的神秘难以捉摸的天网,在这个空间里的所有事物似乎显得飘忽不定, 如果无法看到这张网的全貌, 在里面随意使用逻辑就是玩火自焚, 似乎难以施展已有的知识和技能, 就像所有的经典物理定律在微观世界里失效了一样, 所有的逻辑方法在这个空间里也难以奏效, 或者相互矛盾。在这个世界里, 唯有实际的行动先于理论或逻辑, 才能在这个世界里一步步前进。
做一件事有其“道”“法”“术”。 遵循既定的步骤去完成它, 而不深思其中的缘由, 是“术”的层面; 深思这件事的本源、盲点和局限性, 并找到应对的方法, 是“法”的层面; 领悟这件事的运作规律以及与现实世界的关联, 并自觉去遵循它, 是“道”的层面。
做一件事, 常常思考: 为什么要做这件事? 是否有必要做这件事? 是变化的环境和业务所导致, 还是原有的设计不具可扩展性, 无法容纳新的事物, 还是原有的设计存在缺陷, 需要修复它在应对新事物出错导致的麻烦? 如果弄清楚这些问题, 从结果反推初始, 就能看到原有的做事方法还可能导致哪些尚未出现的问题, 也就是从已知推出未知, 而不是遇事解事, 步步踩坑。 当觉察不便时, 要在当下做一些努力, 并详细地记录, 避免以后类似的情况出现, 或者即使出现, 也能以更小的努力去解决。
比如说单元测试, 只是遵循既定循例去编写单元测试, 这只是“术”的层面; 明白单元测试的本源, 是为了有效地保证每一步每一个环节的正确性, 通过保证所有步骤所有环节的严谨与正确性去保证整体的正确性。这是其核心理念和优势, 同时从中也可以推出其盲点和局限性:
(1) 可能可以穷举, 但是耗时耗力。 比如一个功能包含十个步骤, 每个步骤都有成功或失败的几率, 甚至每个步骤可能出现多个错误, 那么单元测试至少要覆盖 1024 种用例, 而实际上这 1024 种用例可能只有少数用例出现比较频繁, 或者只有少数用例具有突出的重要性和重大的影响性,大部分用例在软件生命周期内几乎不会出现; 单元测试应该尽可能覆盖这些频繁使用的、具有突出重要性和重大影响性的用例, 而不是妄图全部覆盖; 或者说, 20% 的单元测试可以解决几乎 90% 的问题; 而 80% 的单元测试只是起到了安慰剂的作用罢了;
(2) 单元测试无法阻止烂代码的产生; 可以写出无比烂的代码去通过单元测试。 这只能通过“CodeReview” 去减轻其危害; 但这足以说明, 单元测试只能局限于解决某一类问题, 而不可过重倚赖, 更不可倚赖于几个数字; 数字从来不代表质量, 只是一种参考。
(3) 单元测试无法阻止已有测试用例之外的情况的失败。 单元测试仅能保证已经设计的用例的成功, 但当现实发生的情况是在用例之外时, 就是单元测试力所不及之处。 可能你会觉得单元测试不充分, 需要进一步添加单元测试; 难道就只能被现实牵着鼻子走, 出现一个添加一个, 总是这么被动吗?
(4) 单元测试无法阻止全链路的失败。 当关联的外围系统发生变更时, 即使内部再如何正确, 也无法阻止失败。 这涉及到系统之间的接口协议。
因此, 当单元测试施展其威力到瓶颈之处时, 就必须考虑其他办法来加以完善。 比如一个功能包含十个步骤, ABCDEFGHIJ, 如果仅当 ABCD 全部正确才能推出 E‘, EFG 全部正确才能推出 G‘ , HIJ 全部正确才能推出 J‘ , 当 E‘G‘J‘ 全部正确才能推出功能正确时, 单元测试可以进行划分-分组。 验证 (E‘G‘J‘) 的组合共有 8 个; 验证 (ABCD) 组合共有 24 个, 验证 (EFG) 和 (HIJ) 分别有 8 个, 总共只需要 48 个用例即可。 这种方法不完全符合“单元测试”的定义, 但此时正确的做法, 不是质疑做法的正确性, 而是应该质疑定义的合理性, 不是修改作法, 而是修改定义, 使之更具有可行性; 它是基于已有理念和实践上的针对具体情况的一种优化。
其次, 单元测试难以高效地测试多个组件的正确性。 往往一个全链路的集成测试就可以测试很多组件的正确性, 通过单元测试需要使用大量测试用例才能做到。 就好比, 1000 可以等于 1 自加 1000 次, 也可以等于 500 自加 2 次, 尽管后者无法保证每个的正确性, 但是在验证正确性的时候无疑是最有效率的。
做事的方法, 从来是不拘泥于既定的循例, 而是想方设法去实现一些特别的方法, 更高效地验证程序的正确性, 发现程序里的 BUG, 甚至有时这种方式显得有点诡异, 但确实是高效的。 唯有这样, 才能突破一些陈规, 充分释放创造力, 去引导软件开发活动。
当一个人对周围世界处于无知状态时, 最好的方式是保持沉默、观察与倾听。