面对新技术的态度

最近看苹果无创检测血糖技术实现突破,专家说精度不足1的新闻,及前一段时间大火的 ChatGPT 都让我有一种感受,一项新技术的出现,总会出现两种人的声音,一种是及其看好,把其堪称为颠覆和突破,另一种则是觉得新技术各种瑕疵,无法替代现有方案。 两种看法都是相对来说片面的,技术是会迭代的,在迭代的过程中可能发展向第一种看法,打造出颠覆性的解决方案。也有可能迭代的过程中依然无法解决核心的问题,那么就可能永远无法颠覆现有解决方案。 飞机最初的发明思路,是按照鸟的飞行结构去设计的,但是鸟由于骨架轻等特点可以用自身的结构实现飞行,但飞机显然是不可以的,飞机的自重加上载重如果利用鸟的飞行结构去设计显然是无法飞行的。 我们回到刚刚发明飞机的那个时间节点去看,有人觉得飞机会颠覆出行,有人觉得飞机连飞都飞不起来,不可能替代现有出行方案,双方观点截然相反,但又有各自的道理。而从事后来看飞机显然成为现代出行必不可少的交通工具,但是如果飞机在设计的时候没有空气动力学的支持,飞机可能永远也无法飞起来,那么后者的观点也就成了对的。 既然两个观点都是片面的,应该如何看待一项新技术的产生?我认为我们应该用乐观的态度和发展的眼光看技术的突破,也就是更倾向于第一种观点了。 原因是任何技术的诞生之初都是不完美的,悲观的态度只能阻碍其发展,而乐观却不同,乐观能够更大程度的促进技术发展,即便是技术没有实现落地,至少也努力验证了其不可行性,也能为后续的技术的发展提供一个不可行案例,也是存在贡献的。悲观可能会导致直接放弃,对于技术发展而言是没有任何贡献的。 所以不管是对一项技术还是人生中在做的事情,我们都应该用积极的态度去面对,也许用尽各种努力最终还是失败,失败只是结果,但在努力的过程中是一定会有所收获。 从结果上看,努力尝试和直接放弃最终都是失败,但是收获上来看是完全不同的。 References 苹果Apple Watch将实现无创测血糖?专业人士:物理检测 精度不足 (10jqka.com.cn) ↩︎

February 27, 2023 · 1 min · 云溪

如何避免代码的熵增

在开发中与别人交流或在程序员社区中,经常会有关于烂代码的讨论,并且为其起了一个打趣的名字”屎山“。 仅从名字上也不难看出,大家对于这种代码是十分的厌恶的。其实随着需求的变化和增加,项目不可避免的会变的混乱,在物理学里有个名词叫“熵增”。 熵增过程是一个自发的由有序向无序发展的过程 既然代码会膨胀,并且会变得混乱,如何做能够尽量的避免这种情况的发生呢? 核心办法就是主动做功,在规划、实施、复盘等各个阶段有意的去做治理,从而避免代码的混乱。 勾勒整体 在需求开发之前,要建立对需求的整体的认识,从整体拆分细节,从细节着手开发。这么做的主要目的就是对需求有一个全局的规划,确定需求边界,就不会再开发的时候迷失方向,导致整个需求的实现变得混乱,代码和思想都没有清晰的表达。 在整体确定,边界清晰的时候,还需要考虑一点:当前需求与已有功能的关系时怎么样的,如何能花费更小的成本将新增需求融入现有系统。 完成上面说的还有一步就是追问,此方案是否为最优方案,是否还存在更为简化更易于理解的放啊的方案,如果回答全部为是,那么关于整体这部分的考量也就到此结束了。 化繁为简 我对专业的定义是:可以将自己领域的复杂问题简单化的能力。把简单的事情做复杂是庸才,把复杂的事情做复杂是通才,把复杂的事情做简单是天才。 在程序开发中,以易读为第一要务。写代码的主要目的是给人阅读,其次才是机器执行。在开发中,应该以代码的可读性为最高优先级,其次才是性能或其他指标。 大道至简,做到简不容易,需要通过不断的练习与反思,才能窥其门径。 摒弃过度设计 好的程序设计应该是立足业务的基础上长出来的,在业务不是很明朗的时候,应该更专注于方案和代码的简单而不是过度设计。 业务不明朗的时候大多数的设计是无用的而且一些设计会带来代码复杂读的增加,虽然可以美其名余曰有更好的扩展性,没有用的扩展性等于没有扩展性。 好的设计应该是以对业务有深入理解后,通过重构的手段展现出来的,而不是在业务一开始就过分的考虑设计。 不断重构 重构的时机有三种: 对业务有更深入理解的时候 在原有功能扩展新功能的时候 已有功能存在设计缺陷的时候(性能,扩展性,易读性) 重构不应该等”有时间“的时候,”有时间“就等于没有时间。重构应该发生在发现问题的时候,发现问题就解决问题。 就像打扫卫生一样,每发现一个地方乱了,就顺手整理一下,虽然没有刻意的花时间去进行整理,但是整个房间依然会保持整洁。 应该缩小重构的粒度,增加重构的频率,使重构变得小而频繁。 总结 除了上述说的情况之外,保持学习也是很关键。思而不学则殆,通过学习他人项目治理的思想,来增加自身的理解,并在开发中不断的去验证、思考和改进,从而写出更简洁高效的代码。 纸上得来终觉浅,绝知此事要躬行。学习只能是觉知,关键在于实践,知行结合,才是真正把知识内化为己所用。希望本文能对你有所帮助,个人观点难免会有疏漏和偏颇,如果有不同观点,欢迎留言讨论。

February 20, 2023 · 1 min · 云溪

我用了近两天的时间,只为了写三行代码

事情发生在我们线上的一个遗留问题,问题大致情况是我们引入的一个库会导致服务在运行一段时间后出现死锁,并且会造成整个网站无法访问。 我们发现通过配置库的一些参数可以避免死锁的情况发生,但是会引发事务无法回滚的新问题。 由于后者相对故障等级更低一些,我们首先进行了故障降级,选择了优先保障服务运行。 后面则是排查为什么会新的配置会出现事务无法回滚,这个事情由我负责排查。 从部门同事那了解了问题的详细情况后我就开始着手进行排查。首先是对问题进行梳理把新引入的库与框架之间的关系以及整体的一个运行流程进行了梳理。 如果要对整个流程做详细的了解,需要阅读的代码量是十分庞大的,不仅需要阅读库,还需要对框架源码进行阅读。 就解决问题而言,我认为需要做粗略的流程梳理即可,通过对整个流程的一个大致了解,然后确定问题的具体发生位置,然后对具体位置进行详细了解。 在粗略梳理的过程中,我从新引入库开始着手,主要是由于库的代码量相对较少,阅读起来相对更快一些,且如果仅从库层面就能解决问题,也可以省略的框架代码的阅读。 对于库源码的了解我通过 wiki + 源码的方式,这样能够更省力的了解库的整个运行机制。 然而了解了库的运行机制后,我发现问题可能出现在库与框架的配合上。需要涉及到框架源码的阅读。 在开始阅读框架源码前,我决定在本地构建一个复现环境,通过对构建出的本地环境对源码进行 debug 调试。 经过反复的 debug 最终终于确定了问题出现的原因,是由于新库引入后,事务开启时新建一个数据库连接,而通过 ORM 进行数据库查询时会创建另一个数据库连接。这就导致事务和 SQL 的执行不是在同一个数据库连接中,也就造成了数据库事务无法生效的问题。 确定了问题的原因解决方案就好确定了,我们只需要保证事务和 SQL 执行在同一个连接中即可,而解决这个问题只写了三行代码,既保证了功能的完整,没有侵入库和框架进行底层源码的改造。 这次问题的排查让我想到了福特公司用一万美元画一条线的故事。 画一条线,1美元;知道在哪儿画线,9999美元。 这次的问题离不开部门同时的帮助,在排查的过程中和同事进行了 2-3 轮的沟通。不仅让我对问题有一个全面的认识,也几次在我遇到困惑时,给了我解决问题的灵感,包括在最后解决方案制定后的论证,都蕴含了整个团队的心血。 也希望这次的一个排查经过能够对看文章的你有一些启发,欢迎你分享你的感悟和思考。

August 27, 2022 · 1 min · 云溪

Casbin 入门

Casbin 是一个强大的、高效的开源访问控制框架,其权限管理机制支持多种访问控制模型。 通俗来讲就是一个权限管理的框架,把常见的权限管理集成在框架中,使用者只需要根据框架规范就可以很方便的实现相应的权限控制。 Casbin 支持的权限管理如下: ACL (Access Control List, 访问控制列表) 具有 超级用户 的 ACL 没有用户的 ACL: 对于没有身份验证或用户登录的系统尤其有用。 没有资源的 ACL: 某些场景可能只针对资源的类型, 而不是单个资源, 诸如 write-article , read-log 等权限。 它不控制对特定文章或日志的访问。 RBAC (基于角色的访问控制) 支持资源角色的RBAC: 用户和资源可以同时具有角色 (或组)。 支持域/租户的RBAC: 用户可以为不同的域/租户设置不同的角色集。 ABAC (基于属性的访问控制): 支持利用 resource.Owner 这种语法糖获取元素的属性。 RESTful: 支持路径, 如 /res/* , /res/: id 和 HTTP 方法, 如 GET , POST , PUT , DELETE 拒绝优先: 支持允许和拒绝授权, 拒绝优先于允许。 优先级: 策略规则按照先后次序确定优先级,类似于防火墙规则。 Model 概念 Model 相当于框架的配置文件,如我想在系统里有可能实现 是ALC 或者 RBAC ,应该如何告诉 Casbin 框架,我实现的是那种类型的权限控制呢?...

July 29, 2022 · 2 min · 云溪

golang 简洁架构介绍

在 go 开发中,首先遇到的一个问题,应该怎么设计开发架构。一个好的架构可以在后续的项目开发中能够更好的使用项目的推进,同时能够让团队的配合更加的顺利。 一个简洁的架构应该具有如下几个特点: 不依赖框架:好的架构应当是独立的,不依赖框架可扩展的 不依赖 UI:UI 应该很容易修改,而不需要改业务部分代码 独立于数据库:不绑定数据库,可以在不改动业务代码的情况下,更换其他数据库 可测试的: 能够比较方便测试用例的编写 下面目录结构引自 《go 整洁模板》 ├─cmd 应用入口 │ └─app ├─config ├─docs // 存放文档 ├─internal │ ├─app │ ├─controller // 控制器 │ │ ├─amqp_rpc │ │ └─http │ │ └─v1 │ ├─entity // 实体层 │ ├─middleware // 中间件 │ └─usecase │ ├─repo // 数据库操作 │ └─webapi // RESTful API ├─migrations ├─pkg //以被外部程序安全导入的包 │ ├─crypto │ ├─httpresponse │ ├─httpserver │ ├─logger │ ├─mysql │ ├─postgres │ ├─rabbitmq │ └─redis 分层介绍 层级调用是通过外层->内层,内层是不知道外层的存在的。在内层代码中,不应该引用外层声明的:变量、类、方法,结构体。...

June 29, 2022 · 1 min · 云溪