行业AI实战手册来了!洞察金融风险、辅助诊疗、检测缺陷、体验AI课堂,尽在AI...... 了解详情
写点什么

作死?放弃坚持 15 年的原生开发,1Password 用 Electron 重写了全部代码

2021 年 9 月 15 日

作死?放弃坚持15年的原生开发,1Password用Electron重写了全部代码

跨平台开发更便宜,原生开发更优质?


作为世界上最受欢迎的密码管理器,1Password 放弃了 15 年来始终坚持的原生开发方式,转向了 Electron 框架,并彻底地重写了所有的程序。


1Password 的联合创始人 Roustem Karimov 表示,“这是一次彻底的重写,没有复制以前的任何一行代码。重写我们所有的 Apps,是一个巨大的挑战,一般人不该这么做(Nobody should do this)。但是我们需要这样一个核心的根本性变革,能推动我们面向未来,为下一个十年取得成功奠定基础。”


大多数用户其实并不关心开发人员用什么来编写我们所使用的应用程序,但 1Password 的情况显然不同。8 月 11 日,沉寂多年的 1Password 发布了 Early Access 大版本,作为苹果平台上最流行的密码管理器应用, 这个版本一经释出,1Password 的用户社区就炸了!


“非原生是一个巨大的失误,在各方面都是巨大的倒退!”


“我对改用 Electron 感到非常失望。”



舆论几乎是一边倒,1Password 的技术 VP Michael Fey 不得不发了 一篇长文 解释他们为什么要做出使用 Electron 重写 Mac 版的决定。在文中,他说道:“这可能是我们必须做出的最复杂的决定。”


将 1Password 8 转向 Electron 的理由


1Password 拥有 15 年的历史,但这些年来他们构建应用程序的方式基本相同。


1Password 最初是 Dave 和 Roustem 的业余项目,他们的日常工作是作为程序员来构建网站,但他们厌倦了测试中需要不断地手动填写用户名、密码和联系信息,于是他们编写了一个工具来实现自动化。这个业余项目迅速取代了他们的全职工作,并由此催生出了一整个公司和一个相关行业。


1Password 的首个版本是一个 Mac 专用程序。当苹果之后公布 iPhone SDK 时,这支小团队继续努力、开发出相应的 iPhone 版应用。在此之后,他们又逐渐推出了 Windows 与 Android 等多个版本,并为各个平台聘请了独立的开发人员。这些开发者能够获得文件格式规范,了解应用如何在 Mac 及 iPhone 上运行,之后就自由为实际负责的平台创建原生版应用程序。


发展多年之后的结果,就是同一款应用程序在不同平台之上呈现出完全不同的使用界面。Windows 版本的 1Password 就跟 Mac 版在使用感受以及外观上存在巨大差异,Android 与 iOS 版之间也是如此。



而且苹果 Mac 是出了名的生命力顽强,目前仍有很多用户在使用不支持 SwiftUI 的旧版 Mac,1Password 开发商 Agilebits 就还需要做出一个艰难的选择——要么为这款应用程序创建两个 MacOS 版本,保证能够继续在较旧的 Mac 上运行;要么直接放弃陈旧 Mac 硬件,继续推动更新之路。当然,Agilebtis 也有第三种选择,就是把应用程序直接转向 Electron 平台之上。乍看之下,第三种选择似乎是下下之策,但琢磨之后这好像又是最好的方案。


Electron 是一套跨平台应用程序构建方案,能够帮助开发者在无需编写原生代码的情况下获得良好的跨平台运行能力。Electron 允许编码人员使用 JavaScript、HTML 以及 CSS 构建自己的应用程序。而且无论最终用户使用的是 MacOS、Windows 还是 Linux,Electron 编写出的应用程序都能使用相同的代码库。


目前,Slack、WhatsApp Desktop、Microsoft Teams 以及 Discord 等常用软件都在使用 Electron。但这套框架的问题在于,经它之手的应用程序往往要比原生版本占用更多系统资源,特别是内存。尽管如此,看起来 1Password 转向 Electron 已经成为板上钉钉的事实。


也正因为如此,不少人对转向 Electron 的决定表示不理解。毕竟既然考虑的是使用较旧 Mac 设备的用户,就应该注意到这类硬件的内存容量本来就有限。而且在运行这种应用程序时,我们还得同时启动另一位知名内存占用大户——谷歌 Chrome 浏览器。


这也是引发争议的根源。没错,这款软件源于 Mac,但其开发商却放弃了原生开发以扩展支持 MacOS 操作系统的更多版本——这着实令人感到不安。但至少可以明确一点,开发商并不打算放弃 Mac。他们做出的 Electron 框架使用决定虽然会占用更多内存,但核心目标确实是想让相同的代码库能继续顺利运行在旧版 MacOS 之上。


总之,将 1Password 转向 Electron 的基本思路,是为了减少 Agilebits 所需维护的应用程序数量。为了与更多 MacOS 版本保持兼容,开发者只能为同一操作系统构建两款不同的应用程序。对于最新版本的 MacOS,Agilebits 使用 SwiftUI 工具包进行 1Password 8 开发;但对于旧版本,开发人员只能提供基于 Web 的应用程序。


Electron 本身就基于 Web,因此 1Password 8 的 MacOS 版本有望运行在较旧的 Mac 设备之上。毕竟 SwiftUI 只支持 MacOS 10.15 以及更高版本。虽然调整之后,新版本的运行方式和使用感受可能与之前版本有所区别,但至少它还是能为简化开发流程贡献力量。我们只能希望它能比其他常规 Electron 应用程序少消耗一点内存。


尽管争议不断,跨平台仍然“真香”!


用跨平台 Electron 取代之前广受欢迎的 Mac 原生应用程序,这一举动引发的反响确实巨大,但关于跨平台应用程序技术的讨论始终围绕着一个简单到有些粗暴的前提:跨平台开发更便宜,原生开发更优质。



此话倒也不假,毕竟跨平台工具的超高人气确实主要来自更低的多平台开发成本。但这种心理模型并不一定能确切解释每一家选择走跨平台路线的软件开发商的真实诉求。每当有跨平台应用程序被推上互联网舆论的风口浪尖时,我们都会听到这样一个问题:“既然开发商有能力为不同平台分别开发应用程序,他们为什么要逼迫一部分用户放弃原生版本?


但在实践中,跨不跨平台所权衡的绝不仅仅是“便宜和优质”。有过开发经验的朋友们应该清楚,原生技术有时候也能带来低成本,而跨平台在特定情况下反而有助于提升软件质量。那么,我们在权衡跨不跨平台时,到底是在纠结什么?


核心权衡


宏观来看,跨平台 UI 技术优先考虑的并不是完善的用户体验、而是功能的顺畅协调。



我们设想这样一个典型的跨平台 UI 案例:有一款复杂的企业级应用程序,供数千名员工在各类平台上日常使用。他们需要用它处理工作内容,还需要接受相关使用培训——但是,这款应用程序需要取悦用户吗?并不需要。于是,“用着爽”就成了优先事项列表中垫底的一条,基本等同于“音效好听”和“支持游戏手柄”这个层级。只有先满足了跨平台一致性和成本效益等核心诉求,之后才可能考虑这些项目。


有鉴于此,企业当然更喜欢跨平台工具。企业软件最关注的就是功能支持效果,也向来是“不讲使用体验”的典型代表。对于跨平台工具的常见批评意见,就是它能快速让应用的质量达到预期的 75%,但余下的 25% 则再难寸进。不过只要 75% 已经处于可以接受的范围,那么投标合同应该就能顺利收款了,还费别的劲干什么呢?


于是很自然地,内部企业应用程序率先开始了跨平台 UI 融合之旅——尤其以 Web 为主。确实是难看难使,但就是能发挥正常作用,你说气不气。


而在面向客户的软件方面,情况就要复杂得多。体验成了决定产品生死存亡的关键,只有针对特定平台的 UI 代码能够触及“用户体验上限”,这类软件才能真正留住付费用户的心。从概念上说,一家愿意花大钱开发高质量原生 Mac 及 Windows 版本软件的厂商应该能够在竞争中压倒 Electron 版的 Slack、Figma 以及 Spotify 才对,但为什么实际情况不是这样呢?


协调成本的指数级增长


在小型产品团队中,让几款原生应用程序保持一致并不困难。在这样的规模下,原生工具的用户体验与便捷性完全碾压跨平台。但是,随着产品及组织规模的快速发展,一致性开始成为真正的难题。当我们快速招聘新员工、快速添加客户功能并逐渐需要为第三、第四乃至第五种平台提供支持时,情况将越来越危急。1Password 的 Michael Fey 在开发博文中做出了如下解释:


随着时间推移,大大小小的不一致性元素开始渗透到我们的应用程序当中。从平台间密码强度不同等小问题到搜索结果差异、再到不同版本间完全不互通的功能配置,情况变得越来越糟糕。


这很重要,因为随着平台之间功能、设计与 bug 的快速增加,对不同版本做出协调正逐渐变得不可能。


  • 这项功能要何时在 Mac 上推出?

  • 这份支持文档符合 Web 用户的情况吗?

  • 等等,这里的广告内容是指向哪个平台的?


起初,企业还可以向销售及支持团队提供资金支持来勉强维持统一,但随着设计冲突的积累,更加危险的问题出现了:产品团队越来越难以理解自己打理的产品。最终,各个平台团队已经不在同一个频道上,产品交流效率变低、密密麻麻的“路线”彼此交织、重要的细节惨遭忽略……


有些企业会始终坚持客户端应用程序的精简化,也成功避免了这种命运。只要能够保持团队纪律、让产品始终简单、不过度扩张平台、不快速提升团队规模,那么长期保持同步并不是难事。这里的关键策略,就是尽可能把复杂性体现在服务器端,而客户端应用程序则尽可能“无脑”,这样就不需要同时在多种客户端上迭代大量逻辑。


但只要团队规模与产品复杂性持续提升,并且需要在好几种平台上维护大量功能,那其中的不一致性终将失控。


  • 一位重要客户很生气,因为销售说新版本提供一项功能,但在对方的实际平台上根本找不到。

  • 有人在 Twitter 上批评我们,说我们的文档内容有误;产品经理进行了深入研究,并发现这部分内容只是不符合 Android 版本的情况。

  • 我们无法测试有希望的新改进,因为新功能必须同时在所有平台上运行,而 Windows 团队的正常更新进度已经严重落后了。

  • iOS 与 Android 产品团队之间的术语差异导致某个讨厌的 bug 在 iOS 上存在了 5 个礼拜,混乱的沟通反而让 Android 团队推出了一款没啥作用的修复程序。


总之,事情变得一团糟。


所以在具有一定规模的产品组织架构之下,一致性与协调性绝不像嘴上说说那么简单。产品体系需要借助更多流程才能让各平台保持代码库同步,开发者被迫将更多时间花在规程、说明文档与形式工作上。功能质量虽然更高,但开发进度变得更慢。而这种强一致性保障,同时也代表着产品的更新迭代做不出太大的变化。


总而言之,要保持多个平台上的代码库始终一致并非不可能,只是成本极高。我们需要雇用更多工程师来引入非零改进,但协调工作的成本会呈指数级增长(至少是超线性增长),导致每位新员工带来的额外产品开发增速极为低下。


缓慢而低效,最终会令你输掉比赛


对于产品开发商来说,缓慢是个致命的弱点。速度慢的产品团队往往会被行动更快的对手所击败。我们经常抱怨 Figma 和 Slack 之类的产品给不了原生使用体验,但为什么大多数人仍在使用 Figma 与 Slack 这些?因为它们的实际表现确实压倒了原生竞争对手。这些产品中当然还有很多可以改进的地方,但它们确实在自己设定的发展路线上做到了最好。


于是,跨平台与原生工具之间的权衡就成了大规模协调工作中的重要组成部分。没错,原生代码特别擅长构建起出色的用户界面,但如果大型产品团队与多种客户端代码库会极大拖慢更新进度,那么原生开发方法本身就是在破坏用户体验。



因此,我们得出一种非线性权衡,而不再是简单的“优质与便宜”之争。谁对跨平台工具最感兴趣?当然是那些希望能在多个平台上协调多种功能的团队,这意味着功能性的优先级要高于原生使用体验。而在移动平台上,开发团队通常不会贸然推出新功能、倒是愿意精心设计用户体验并加以润色,所以移动端开发往往比桌面端更倾向原生方法。


当然,我们也可以从多种跨平台方案中做出选择,尽可能把协调负担降下去。不同于此次 1Password 投向 Electron 所引发的巨大批评,之前他们决定将所有应用程序版本转向共享 Rust 库的决定就广受欢迎。有趣的是,近年来 Dropbox 及 Slack 等知名团队都发表过如何避免使用跨平台核心库来支持移动应用的文章——目前,双方都在使用完全原生的 iOS 与 Android 代码库。就目前的情况看,市场似乎分成了两大派别——一派宣布全面转向 React Native,另一派则决定彻底放弃 React Native。这也是个有趣的话题,以后有机会再单独讨论。


总之,我们能做的就是认真考虑不同技术善于解决哪些问题,并对判断保持足够的警惕。我们会观察技术的发展,与实际使用者交谈,并了解团队分享的哪怕一点点经验。只有这样,我们才有机会认清事实的全貌。


延伸阅读:


https://blog.1password.com/1password-8-the-story-so-far/


https://allenpike.com/2021/gravity-of-cross-platform-apps


2021 年 9 月 15 日 17:471

评论

发布
暂无评论
发现更多内容

Java9新特性-上篇

hepingfly

Java Java新特性

LeetCode题解:90. 子集 II,递归+for循环+回溯,JavaScript,详细注释

Lee Chen

算法 LeetCode 前端进阶训练营

架构师训练营第六周总结

邓昀垚

极客大学架构师训练营

嵌入式面试之《Linux系统编程100问》

哒宰的自我修养

Linux 线程 网络编程 进程

「架构师训练营第 1 期」第六周作业

张国荣

当AI入职FBI,克格勃直呼内行

脑极体

科大讯飞翻译系统变身“随身翻译官” 助力粤港澳大湾区一体化建设

Talk A.I.

甲方日常42

句子

工作 随笔杂谈 日常

架构师训练营第 1 期 -- 第六周学习总结

发酵的死神

极客大学架构师训练营

目标检测学习-比赛路线

Dreamer

央行数字货币亮相 吹皱一池春水

CECBC区块链专委会

数字货币 银行

2020年9月公有云性能评测:UCloud、腾讯云屈居二三名,冠军竟然是它?

博睿数据

云计算 公有云 评测 排行榜

TarsCpp 组件之 MySQL 操作

TARS基金会

c++ MySQL 数据库 微服务 TARS

架构师训练营第 1 期 第 6 周作业

李循律

极客大学架构师训练营

元模型驱动(三):构建我们自己的元模型-KAYA

KaYa

DDD Kaya MDA MDD 元建模

美国半导体十年计划中的NO.1,模拟硬件究竟有什么价值?

脑极体

如何构建一个通用的垂直爬虫平台?

Kaito

Python 爬虫 代理

2020年区块链行业十大趋势

CECBC区块链专委会

区块链 技术人才

架构师训练营第二周总结

lakers

极客大学架构师训练营

架构师训练营第二周

M.

有状态软件如何在k8s上快速扩容甚至自动扩容

东风微鸣

Kubernetes DevOps openshift

积极参与数字货币等国际规则制定,塑造新的竞争优势

CECBC区块链专委会

疫情 经济

架构师训练营第 1 期 -- 第六周作业

发酵的死神

极客大学架构师训练营

【面经】面试官:讲讲类的加载、链接和初始化?

冰河

架构 JVM 类加载 优化 性能调试

Scrapy 源码剖析(二)Scrapy是如何运行起来的?

Kaito

Python 爬虫 Scrapy 源码剖析

Scrapy源码剖析(一)架构概览

Kaito

Python 爬虫 Scrapy 源码剖析

CICD实战——服务自动测试

TARS基金会

微服务 单元测试 CI/CD

TarsCpp 组件 之 智能指针详解

TARS基金会

c++ 微服务 智能指针 TARS

架构师训练营第二周作业

lakers

极客大学架构师训练营

SpringCloud 和 SpringBoot 版本选型

hepingfly

微服务 springboot SpringCloud 选型

如何搭建一个爬虫代理服务?

Kaito

爬虫 代理

MySQL 核心特性与优化

MySQL 核心特性与优化

作死?放弃坚持15年的原生开发,1Password用Electron重写了全部代码-InfoQ