我的 2023 年度技术总结

时光荏苒,一年匆匆又过去。年末在出租车上,听另一位拼车乘客和司机聊天,乘客说,我身边的人,最大的感触就是,2023 年就是活着,什么值得说的事情都没有,司机深以为然,我想这可能也是大部分普通人的状态。而我最大的芥蒂,则是去年贴春联时“步步高升”的横批被卡在了门牌号下面这件事,作为受过专业训练的前科研人员,谈论这件事会导致我价值观念的一种冲突,但不说归不说,我终归有情感上的需要,要在某个地方提一提这件事。

人生的意义,在于不断的将意义赋予生活本身。离开了这种赋予,就似乎一种行尸走肉,算不得真正的生活,这也是本文写作的动机。

在技术上,这一年学习了两种新语言:Rust 和 Lua,前者是出于对性能敏感程序开发的需求,后者则是为更好利用 Redis 作为主数据库,发挥 OpenResty 网关的能力而学习的。其中我尝试将 Rust 和自己现有的技术栈结合起来,包括火热的 Rust 后端 + Flutter 前端方案,Rust in Web 方案等,不过由于 Rust 距离高效率应用开发的距离实在是太远,因而现在只作为知识储备,倒是 Lua,广泛活跃在我的 OpenResty 网关里,以及 Redis 操作的后端代码中,我有一个项目甚至完全采用 Redis 作为主数据库。我还尝试将 Lua 和公司的 OSGi 项目整合,将可变部分用 Lua 编写,然后和 Java Library 互相调用,最后不了了之。

在后端领域,今年最火的就是 Java 的虚拟线程,不过我早在 JDK 19,也就是去年就引入了这一特性,因此这一年则更多是从实践出发,将我的各个应用都改成了异步和虚拟线程混合模式,改造了支持 Loom 的 PostgreSQL 库,并且多次压测了虚拟线程的能力,现在基本可以撞到网络和 CPU 瓶颈。我也积极尝试了将 GraalVM 引入开发中,包括基于 GraalVM 的 Quarkus 和 babashka,探索 JVM 应用的云原生可能性,不过还是 AOT 后的脚本写得多,应用出于调试、开发的便捷性,一般还是回归 Hotspot 的传统 JVM 上。对于 Clojure 而言,读了 《Brave and True》和《Learn ClojureScript》这两本书,在实践中探索了宏。对于数据库和网关而言,则研究了 Redis,在我的服务中严重依赖了 Redis 的各种能力,包括缓存、鉴权、限流、订阅发布、MQ 等,OpenResty 也读了几本书,并广泛引入到项目中。此外,还有一些新式的数据库,包括基于 DataLog 的 Datomic 和 XTDB,其中 Datomic 最让我欣喜,函数式、不可变,带有时光机的,结合了 Redis 和 PostgreSQL 的读性能可无限扩展的分布式关系型数据库,不过大部分时候,因为 PostgreSQL 和 Redis 就能完成大部分工作,因此也仅作为知识储备。最后,学习了 ElasticSearch,并自己搭建了一套 ELK 环境用于支持故事、新闻搜索等需求。在运维方面,深入学习了 Docker、Kubernetes,了解了一些常见的发行版,比如采用了 k3s 和 minikube 等作为开发环境,由于同区域云环境虚拟机不足,因此自己的各种云服务仅仅是 docker 化,而没有使用 kubernetes,这是一个遗憾,缺少环境继续研究服务网格。

在前端领域,深入研究了 CSS,一些 CSS 解决方案,比如 tailwind,此外我对 React.js 也进行了学习,但前端工程化方案,包括 Vite、Hook、Redux 等,相比较 ClojureScript 生态还存在差距,且由于对 React Hook 导致各种工程问题的担忧,因此我仅读完了 Next.js 文档,研究了 Antd,并且魔改了一个 Next.js 项目并上线自己的博客外,并没有投入太多的精力。

在客户端领域,我读了《Thinking in SwiftUI》并深入研究了 SwiftUI,开通了 Apple Developer,但受限于应用版号审批,加之没有很好的 IDEA,在不断开发自己的 SwiftUI 应用,积累了一定经验之后,考虑到 SwiftUI 技术封闭,应用开发需求疲软,随处可见的语言黑魔法和实际并不算很高的开发效率,我逐渐将应用开发转移到了能覆盖更广平台的 Flutter 上。这一年中,我使用 Flutter 作为界面开发的应用,探索了包括客户端集成 SSH、视频播放、画板、WebView、复杂图形、动画等多种需求,主要使用场景覆盖了 Web 平台,iOS、iPadOS 平台,Windows 平台和 Android 平台,通过自研构建脚本集成了包括阿里云 OSS、SSH 连通虚拟机、Github Action 等多方 CI/CD 编译和生产系统,基于 Riverpod 的状态管理极大的增强了大规模应用开发、部署和集成的效率。

我于去年年初,为记录打卡工时而开发的 Go 服务端 CyberMe,在整合了自己内部 Clojure/Script 项目 ICE Manager 代码遗产的基础上,在这一年里陆续合并了之前我基于 Scala Play、Java Spring 等多个服务,合并成了现在的 CyberMe 前端与后端 Clojure/Script 项目。我不断的往这个项目中塞需求,包括车票管理、HTTPS 证书管理、Wireguard 组网管理、OSS 图床、影视剧更新推送、GPS 持续定位追踪、快递追踪、工时追踪、微软待办管理、苹果健康管理等等功能,不幸的是,基于 Clojure/Script 的技术架构,正如同近两年前我第一次接触到它一样,当我看到 Ring 中间件,脑袋里都是 SHE 那句“Ring 呀 Ring 呀 Ring”,我在这些年陆陆续续学习过十三门编程语言,接触过不计其数的框架和类库,但从来没有一套解决方案,在开始带给我欣喜后,能让我在连续两年的时间里持续保持兴趣,以至于不论怎样探索它的能力和边界,都乐此不疲的程度。作为对比,我对于 Flutter 的兴趣,很快随着应用规模上升而消失,虽然最后总是能被 Riverpod 拉一把,但都比不上我写了三四万行 Clojure/Script 代码后仍然能保持兴趣的地步。这一年 CyberMe 中开发的大部分特性,都通过 Web、SwiftUI 客户端和 Flutter 客户端提供服务,其中重心也从私人服务转变到了公开服务,包括短链接系统、图床系统,喷嚏图卦 PWA、Bing 壁纸和 CyberWeather 天气、PsychMe 心理学量表系统等,这些服务内部极大受益于我对 Redis 的使用:缓存、解耦、监控和统计。当然,上述前端、后端和服务端中学到的其他技术,也大多在 CyberMe 项目中得以使用和验证,或者说大部分时候是由于需求才不得不学习这些新技术。经过这一年的开发,加上我自己搭建的 ESXi Server 和 Git Server,大部分软件和服务,起码用户界面和产品侧,目前都做到了自给自足,当然,背后依赖于第三方服务,比如微软的 Graph API、彩云天气、Mini4K、阿里云 OSS、Github 等等。

最后,作为社会心理学者,这一年我在各个项目中,形成了一套敏捷软件开发的模型,包括基于 Figma 的原型设计,以及如何利用微小动机促进应用交付的最佳实践,状态管理,高可用服务,CI/CD 工作流等。此外,我探索了一些常见的产品设计认知偏差,对于 CyberMe 的 Clojure/Script 开发极大的改变了我的软件理念:Simple make Easy,我的产品设计也是这样做的。在社会侧,这一年我读的最好的书是《置身事内:中国政府与经济发展》,这本书通俗易懂,作为整体框架对财经可以有很好的理解,这本书引申而来的很多书籍中,我都深受裨益,比如路风的新火,孔飞力的叫魂等。