写点什么

优秀程序员的 30 种思维(29/100)

作者:hackstoic
  • 2022 年 4 月 18 日
  • 本文字数:6746 字

    阅读完需:约 22 分钟

优秀程序员的 30 种技术思维。

我会分五个部分来讲:理解认知, 设计思考, 行动准则, 分析总结, 技术执念。

理解认知篇

抽象思维

一句话解读:大处着眼,隐藏细节,抽象就是由实向虚,提取共性。

【举个栗子】如果分别问艺术家,生物学家和程序员,他们眼中的世界是什么,可能会得到三种不同的答案。艺术家: 蓝天,碧水, 绿草,白羊,美哉自然。生物学家: 雌雄一对,生生不息。程序员: 世界是 0 和 1 组成的。

如果是我们在用的 windows 系统, ios 手机系统,微信 app,最后都被编译成只有 0 和 1 构成的代码去运行。所以整个世界的 IT 系统都可以由 0 和 1 构成的,这个就是抽象。

分治思维

一句话解读:把大问题分解成若干小问题

【举个栗子】

如果我们要做一个会员系统,这个系统概念太大了,无从下手,我们可以将系统进一步分解成一个个模块,比如支付模块,账号模块,活动模块,商品模块等,每个模块再拆解成一个个功能,比如支付模块拆解开来有下单功能,查询支付结果功能,退款功能等等。

当然功能还可以进一步拆解为代码块,这样一层层拆解之后,我们就可以把大问题,变成一个个小问题来解决了。

分层思维

一句话解读: 应对和管理复杂性的思维武器

【举个栗子】

TCP/IP 协议的设计其实就是分层思维的一个很好的体现。

关于 TCP/IP 每层的作用和分层的好处,如下:

TCP/IP 协议族按层次分别分为: 应用层、 传输层、 网络层和数据链路层。

  1. 分层好处:改动自由:比如, 如果互联网只由一个协议统筹, 某个地方需要改变设计时, 就必须把所有部分整体替换掉。 而分层之后只需把变动的层替换掉即可。 把各层之间的接口部分规划好之后, 每个层次内部的设计就能够自由改动了。设计简单:值得一提的是, 层次化之后, 设计也变得相对简单了。 处于应用层上的应用可以只考虑分派给自己的任务, 而不需要弄清对方在地球上哪个地方、 对方的传输路线是怎样的、 是否能确保传输送达等问题。

  2. 各层的作用应用层 –>(可以想象成是快递打包过程)应用层决定了向用户提供应用服务时通信的活动。TCP/IP 协议族内预存了各类通用的应用服务。比如,FTP(File Transfer Protocol,文件传输协议)DNS(Domain Name System,域名系统) 服务就是其中两类。HTTP 协议也处于该层。

传输层 –>(可以想象成选择什么快递,比如顺丰、圆通)传输层对上层应用层, 提供处于网络连接中的两台计算机之间的数据传输。在传输层有两个性质不同的协议:TCP(Transmission Control Protocol, 传输控制协议) 和 UDP(User Data Protocol,用户数据报协议)。

网络层(又名网络互连层) –>(可以想象成快递途中走什么路线)网络层用来处理在网络上流动的数据包。数据包是网络传输的最小数据单位。该层规定了通过怎样的路径(所谓的传输路线)到达对方计算机,并把数据包传送给对方。与对方计算机之间通过多台计算机或网络设备进行传输时,网络层所起的作用就是在众多的选项内选择一条传输路线。

链路层(又名数据链路层, 网络接口层) –>(可以想象成快递运输的交通工具,飞机、火车等)用来处理连接网络的硬件部分。包括控制操作系统、硬件的设备驱动。NIC (Network Interface Card, 网络适配器, 即网卡),及光纤等物理可见部分(还包括连接器等一切传输媒介)。硬件上的范畴均在链路层的作用范围之内。

参考资料:TCP/IP 协议族分层及其作用[1]

设计思考篇

规划设计思维

一句话解读:为发展留空间

【举个栗子】

典型的案例是系统容量规划,比如购买服务器,需要提前为业务做规划,需要多大的服务器,需要预留多少空间等等

城市的道路规划,基础设施规划也是如此。

演化设计思维

一句话解读:三分设计,七分演化,在设计中演化,在演化中设计

【举个栗子】

现在的微信除了微信信息聊天之外,还有视频聊天,视频电话, 朋友圈,短视频,小程序, 但是最早的微信不是我们一开始看到的样子,只有文字聊天功能。

可扩展性设计思维

一句话解读:以不变应万变

【举个栗子】

对于很多互联网架构设计,可扩展性是一个基本的要求。

可扩展性的优点是在原有业务逻辑不变的情况下,通过增加机器,增加实例,让系统的处理能力得到增强。

接口化设计思维

一句话解读:对外提供自己的能力

【举个栗子】

Amazon 一开始是一个电商,后面开始做 AWS 云。 做云的时候,他们遵循了一个原则,将所有的能力接口化。产品与产品直接以接口的方式调用。这样做让整个平台更加开放和高效,而且可以定制化能力更强。现在各大云平台,比如国内的阿里云和腾讯云也采用了这种模式。

分布式设计思维

一句话解读:减少单点风险

【举个栗子】

区块链就是一个典型案例。以太坊的节点分布在世界各地。 任何一个节点宕机了,但不会影响以太坊的功能。

模块化设计思维

一句话解读: 用搭积木的方式设计软件,实现低耦合,高内聚

所谓的模块化设计,简单地说就是将产品的某些要素组合在一起,构成一个具有特定功能的子系统,将这个子系统作为通用性的模块,可以与其他产品或要素进行多种组合,产生不同功能或应用的产品。

简单概括就是要像组装积木一样组合出不同产品. 在生活和工业的各个领域都有典型的案例,比如汽车制造装配,宜家的家具, 手机等等

在研发领域,也常常用到模块化设计的思想,比如我们常说的微服务就是模块化设计思想的一种应用。

在产品设计里,模块化设计也有很多应用,比如要设计一个用户成长体系,可以把整个运营工具分为活动模块和奖励模块,这样就可以做各种灵活适配,不同的活动可以采用不用的奖励模式,另外奖励模块还可以进行复用,可以和其它的模块,比如任务模块对接,做到一个模块,多处使用。

为什么需要模块化计思维呢?模块化设计有哪些好处,总结下来有以下几点好处:

  • 能够有统一的输出

  • 便于维护,无论是开发还是定位问题,可以缩小维护范围

  • 实现了低耦合,高内聚,方便快速迭代

  • 降低了代码复杂度,增加了代码的重用性,扩展性,提高了开发效率

这里要解释一下,其实“高内聚,低耦合”才是软件开发的内在要求,“模块化设计”只是实现“高内聚,低耦合”的其中一种方法。

“高内聚”最精准的体现是“面向对象开发”,它的意思是从功能角度来衡量模块间的联系,也就是说一个好的内聚模块应当只做一件事;

“低耦合”的精准体现是“面向接口开发”,意思是从软件结构角度衡量各个模块之间的联系,耦合强弱取决于模块间接口的复杂程度、进入或访问一个模块需要调用的接口数量和次数;极端的低耦合是不需要任何接口,但一般很少见。

“高内聚,低耦合”是判断软件设计好坏很重要的一个标准。

本文部分观点和案例参考了相关文献:

  • B 端产品设计:从产品角度谈“软件模块化设计”[2]

  • 产品设计:模块化设计思想的应用[3]

  • 如何建立模块化工具设计思维[4]

复用思维

一句话解读:降本增效

初级程序员会陷入一个误区,就是大量的复制粘贴,产生很多重复性代码。看起来复制粘贴一时爽,殊不知维护起来火葬场。一旦逻辑需要改动,就需要在所有地方变更。

所以一般会强调复用代码,对逻辑做进一步的抽象,比如抽成函数, 很多的函数如果功能是相关的,又可以整合成模块进行复用,如果很多的模块功能相关,又可以抽象成服务。

现在很火的”中台“概念,我认为也是复用思维的一种体现。

往更大的范畴说,IaaS,PaaS,SaaS 也是复用思维的体现,都让更多的人和机构可以复用同一套服务,而不需要从头造轮子,从而达到降本增效的作用。

隔离设计思维

一句话解读:风险隔离,保护核心

业务模块总有”高低贵贱,远近亲疏“之分,这里是说,有核心的模块,也会有非核心的模块。 比如对于付费会员系统来说,会员模块, 支付模块就都是核心模块,如果出问题,会影响业务,影响用户使用,甚至影响到公司的收入。 而消息通知模块是一个非核心模块,对用户的影响相对很小,是一个附加功能。 核心模块和非核心模块的重要性程度不一样,对稳定性的要求也不一样,要进行区分对待,把更多的资源给到核心模块,让非核心模块对核心模块的影响降到最低。

举个例子,开通会员后会给用户发信息,但是发信息如果报错了,不能影响用户开通会员后的一些操作。 所以一般会把消息通知做成异步操作。 另外,对消息通知做容错设计,单独执行, 不影响主业务模块。

容错设计思维

一句话解读:允许错误发生

在互联网架构设计里,有高可用的需求。我们在架构里,经常要做一个假定,就是底层基础设施不可靠。比如你不能假定服务器就是稳定可靠的,要想着,如果服务器挂掉了怎么办? 应用还能正常运行么?因此有了分布式架构,有了负载均衡,有了水平扩展的概念的出现,来确保单台服务器宕机,不影响业务应用正常运行。

代码设计里也是一样的,要经常考虑,如果在某个流程出问题怎么办,是要把错误抛出来,中断流程,还是忽略错误,继续运行,要有一定的容错措施。

产品交互设计里,不能信任前端用户的输入,所有也要有防呆容错的设计,做输入校验,如果用户输错了,要做提醒。

以上都是容错设计思维的一些提现。

只有时刻思考什么时候错误会发生,才能在错误发生的时候降低业务的影响。

最小化权限设计思维

一句话解读:泛滥意味着不可控

安全里面有个最小化权限设计原则,当过度授权时,往往会出现不可控的情况。你很难避免分配出去的权限会不会被滥用,或者被黑客滥用。

很多管理系统或者数据库都会有权限系统。以关系型数据库 MySQL 为例。 其数据库的权限粒度很细,可以设置哪个用户在哪个 IP 范围下,可以对哪个数据库的那个表进行读操作还是写操作。 给程序分配一个合理权限的账号很重要,如果你分配了一个权限很大的账号给程序,但是程序又用不上,那么就可能面临一个风险,当程序出问题后,很可能对数据库的数据进行破坏。 而如果你设置了合理的最小化权限,那么有可能这个设置会变成一道屏障。

公有云平台会有一个访问控制模块,这个模块也是能够支持某个用户,可以对哪些区域下的哪些产品的什么功能进行操作。对用户进行最小化授权,在某种程度上可以提前阻止用户进行错误,甚至危险的操作。

可追溯性设计思维

一句话解读:为复盘提供可能性

现实的案例是飞机上的黑匣子,飞机上的黑匣子会记录飞机飞行时的各项参数,飞行员的对话等等,当飞机出现事故后,调查人员往往会找到黑匣子还原事情真相。 如果没有黑匣子,很难知道当时出现了什么情况,更不用谈真相。

同样的,在 IT 领域,可追溯性设计的例子也比比皆是。

  • 代码出 bug 了,怎么定位到具体的问题呢?在代码里,会有错误堆栈,捕捉到错误后,会一级一级返回,找到最先抛出错误的地方。

  • 系统出故障了,怎么定位到具体的问题呢?可以做告警聚合,可以为每个模块或者调用打上 traceID,方便追踪。这个在微服务系统里经常会用到,比如常用的分布式调用追踪系统 zikpin, skywalking, jaeger 等。

  • 安全出事故了,怎么知道在哪里出问题呢?一般系统会实时记录所有相关的操作日志,就能知道每个时间谁动了系统,做了什么事情,这样出问题后就可以回溯。

试想,如果没有错误堆栈,trace 记录或者操作日志,那么出问题后,是不是难于还原真相,进行复盘?

备份设计思维

一句话解读:反脆弱

中国有句古话叫: 未雨绸缪,有备无患。

说的是,提前为可能到来的坏情况做好准备。 IT 的设计里也会有类似的设计思维,比如在集群方案里,会假定一些主机可能会随时挂掉,然后会基于这个假定做架构设计,一旦某些主机挂掉,会自动切换,或者 rebalance(重新组建集群)。 再比如数据中心的设计里,会强调两地三中心,在不同的城市建设机房,将应用的实例或者数据库的备份放在不同城市的不同机房里,也是避免出现一些极端情况,比如数据中心挂了,发生火灾,光缆被挖断,或者发生火灾这种灰天鹅事件。

总而言之,备份设计思维是为了实现系统的反脆弱性,在架构师/程序员在系统设计有广泛的应用。

行动准则篇

重视实现

一句话解读:知道怎么做更重要

软件工程师重视方案的执行和落地,而不是仅仅停留在理论研究。

当接到一个需求之后,马上开始着手怎么去实现,同时提出多种方案,比较多种方案的优劣,实施难度,需要的资源,需要的时间。

自动化

一句话解读:效率就是生命

能用脚本和工具,就不用手动复制粘贴。 宁愿花 2 小时写代码解决 20 分钟手动就能处理的事情。虽然看起来好像很傻,效率变低了,其实不然,脚本可以反复使用和迭代,每次执行可能只耗费几秒钟,而手动每次花费的时间都是一致的。只有重复操过多次,自动化脚本的价值就体现了。

我们倾向于将一起可以自动化的事情自动化。 以自动化为荣,以手动重复为耻。

迭代思维

一句话解读:先求运行,再求正确,最后求快

我们追求完美和极致,但是追求的是动态趋向完美和极致。 如果一开始就追求完美,可能造成的问题是过度设计,或者造成迟迟无法上线。 互联网的快节奏和商业竞争的白热化,衍生了允许快速试错,快速迭代的文化。

灰度发布

一句话解读:循序渐进

如果有大的改动,需要发大版本,循序渐进的发布会优于一次性全部铺开。渐进式发布更改,一旦出现问题,方便及时止损,将影响控制在较小范围。

回滚

一句话解读:做好随时回滚的准备

在新版本上线前做好回滚准备,应对不可预料的错误和未被发现的 bug。特别是随着系统的复杂度越来越高,测试和生产环境的复杂度不一致,测试环境很难模拟生产的真实情况时,更可能出现一些突发情况。所以做好回滚准备非常重要。

分析总结篇

一切皆可量化

一句话解读:talk is cheap, show me data

无论是运营,测试, 性能评估,研发效能,还是销售,量化的思维都可以派上用场。

举个例子,销售招聘,培训和管理过程在大家印象中应该是最不容易量化的,可是国外的一个工程师接管销售团队之后,却给整个销售招聘,培训和管理过程都进行量化评估,收集了各个维度数据指标,进行评估和改进,最后将公司的销售业绩从 0 做到 1 亿美元。 这家公司叫 HubSpot。 大家如果对具体的实现过程感兴趣可以去看下这本书《销售加速公式》。

这个案例也说明了量化的思维可以带来不可思议的效果。 完全感性和主观的认知不具有复制性和且不利于自动化和规模化,但是一旦将一件事情量化之后,可以不断积累数据优化,将主观的经验转化为公式,方便和系统进行整合,从而实现自动化和规模化。

服务皆可监控

一句话解读:没有监控,容易失控。

在系统设计里,上线的核心功能一般都是要求可以被监控的。 最简单的监控是监测这个功能是否可以被正常调用,其次是性能指标,安全指标等。

很多著名的开源系统,比如监控系统 Open-falcon,它有很多的模块,每个模块都会开放一个健康检测接口,通过调用这个接口可以知道这个模块是否正常,方便对其自身做自监控。

反过来想想, 上线一个服务,如果没有监控,会出现什么情况呢?

如果没有监控,出问题之后,往往后知后觉,甚至系统崩溃了才会察觉到,会把影响扩大。

下一次系统或者模块设计的时候,记得要把监控的需求考虑进去。

A/B Test 思维

一句话解读:不确定性的方案解

相信大家在工作中会遇到这样的问题: 提出了几种方案,但是不知道哪个是有效的; 没有经过 A/B test 验证,导致全面推广后被业务吐槽。。。

上述问题都可以通过 A/B test 来避免和优化。

A/B Test 也称为对照试验,它是一种检验方法,通过合理的随机实验,科学地建立事物间的因果关系。比如当前产品的版本为 A,你针对某些问题提出了产品的优化方案 B,但是并不能确定 B 的效果会好于 A,于是你在线上同时部署了版本 A 和 B,将 1% 的流量导入 B,剩余 99% 的流量导入 A,通过持续观察数据指标或者其他方式决策方案的优劣。

如果 A 优于 B,重新修正方案 B 继续测试。如果 B 优于 A,尝试扩大流量比例,例如灰度 50% 的时候 B 是否也优于 A?如果最终确定 B 优于 A,再将流量推到 100%。

【参考资料】

互联网时代你需要掌握的 A/B Test 技能[5]

技术执念篇

........


更多请跳转自: https://mp.weixin.qq.com/s/SWCmFR-qbf_IBuIS8LW9Tw 查看


部分参考资料软件工程师的 10 个认知模型[8]

参考资料

[1]

TCP/IP 协议族分层及其作用: https://blog.csdn.net/yihui1314/article/details/79896995

[2]

B 端产品设计:从产品角度谈“软件模块化设计”: http://www.woshipm.com/pd/3806623.html

[3]

产品设计:模块化设计思想的应用: http://www.woshipm.com/pd/3841754.html

[4]

如何建立模块化工具设计思维: http://www.woshipm.com/pd/2597750.html

[5]

互联网时代你需要掌握的 A/B Test 技能: https://mp.weixin.qq.com/s?__biz=MzA4NTg4Njk0Mw==&mid=2247483862&idx=1&sn=3fc01618c59c62b013850c422feea022&chksm=9fd05366a8a7da70a79986dbd66a0d0ae30af54b040d570690d596c7ba86ee01640081230ecb&scene=27#wechat_redirect

[6]

怎么才能写好技术文档?这是我的全部经验: https://mp.weixin.qq.com/s/FXjzItLWZRW7N3TDrEfgWg

[7]

画一手好的架构图是码农进阶的开始: https://juejin.cn/post/7062662600437268493

[8]

软件工程师的 10 个认知模型 : https://xie.infoq.cn/article/c3ba2318ac3df2d72c09c4e61


更多请跳转自: https://mp.weixin.qq.com/s/SWCmFR-qbf_IBuIS8LW9Tw 查看

发布于: 刚刚阅读数: 3
用户头像

hackstoic

关注

还未添加个人签名 2017.11.24 加入

TGO深圳会员,某创业公司技术负责人, 专注领域:架构设计/技术管理/区块链/投资

评论

发布
暂无评论
优秀程序员的30种思维(29/100)_技术思维_hackstoic_InfoQ写作平台