問 AI:把數據操作轉為 unstorage 適配如何?
背景#
我是一名程序員。萌生一個想法,github 上有 unjs/unstorage 這個庫,通過接入不同的 driver 適配層,把操作數據封裝為 hasItem getItem setItem remoteItem。映射前端 localStorage 的概念。
我在想,用這種方式去適配前端操作數據的場景,還挺好的,技術不難還很容易出成果,簡化學習的成本。比如,我有一個 wordpress api,我可以不學習具體用法,如果你需要更新網站信息,就使用我提供的 unstorage-wp-site,如果想回復評論就 unstorage-wp-comments.setItem。類似的,使用 get/post/put/delete 這種封裝思路,就是重用已有的概念,你覺得怎麼樣?
我和 AI 的對話#
Claude3Opus 這樣回覆
這是一個很棒的想法!將不同的數據操作抽象為類似 localStorage 的通用接口,可以大大簡化開發者的學習和使用成本。我對你的思路有以下一些想法和建議,供參考:
- 接口設計要盡可能簡單易懂,貼近開發者已有的知識概念。你提到的 get/set/remove/has 等方法就很好,基本上看名字就知道作用。
- 考慮好異步操作。很多存儲調用都是異步的,需要返回 Promise。可以參考 IndexedDB 的異步接口設計。
- 錯誤處理很關鍵。接口調用要能優雅地處理和傳遞錯誤,提供清晰的錯誤信息和代碼。
- 版本管理和數據遷移。如果存儲 schema 有變化,要考慮新舊版本兼容和數據遷移。
- 靈活可配置。提供良好的可配置性,讓使用者可以自定義行為,如自定義 key 前綴、數據有效期、緩存策略等。
- 優秀的文檔。編寫清晰、全面的文檔和使用示例,可以降低開發者的學習門檻。
- 單元測試。對各個存儲適配層編寫完善的單元測試,確保穩定性。
- TypeScript 支持。如果項目用 TS 編寫,可以考慮提供完整的類型聲明文件。
有人反對,他說好像更麻煩了,unstorage-wp-xxx.setItem, 這個 xxx 就是學習成本。只是將成本從一個地方轉移到另一個地方。還多了一層,系統更複雜了[旺柴]
Caude3Opus 這樣回覆
這個反對意見提出了很好的觀點。引入 unstorage 這個中間層,從某種程度上講,的確是把學習成本從底層 API 轉移到了 unstorage 的適配層。開發者需要去了解 unstorage 的概念和使用方法,以及每個適配器的具體用途。這無疑增加了一定的學習負擔和系統複雜度。
但我認為,從長遠來看,unstorage 這種方案還是有價值的,主要有以下幾點考慮:
- 統一的接口。不同的存儲方案有各自的接口和用法,通過 unstorage 提供統一的接口,可以降低開發者在不同存儲方案之間切換的學習成本。
- 封裝複雜性。有些存儲方案的接口比較複雜,參數很多。unstorage 可以封裝這些複雜性,提供更簡單易用的接口。
- 可以沉澱出業務層面的通用模塊。比如 unstorage-wp-site、unstorage-wp-comments 這種業務層面的適配模塊,可以沉澱為項目的基礎設施,在多個功能模塊中重用。
- 有利於統一錯誤處理、監控等基礎設施。有了統一的接口,可以在 unstorage 層面統一進行錯誤處理、日誌監控等。
- 更好的可測試性。通過 unstorage 適配層,可以方便地 mock 存儲接口進行單元測試。
我認為如果有多個 driver 適配層,就可以進一步形成生態和插件市場。但這會帶來新的問題,不同的 sdk 思路不同,可能產生 api 不一致的情況。請你繼續作為反對意見方,對我進行挑戰,提出你的各種反對意見。
好的,我來繼續扮演反對意見方,對你的想法提出質疑和挑戰:
- API 不一致的問題。正如你提到的,不同的 sdk 思路不同,可能導致 API 設計風格迥異。比如有的 sdk 喜歡用 get/set/remove,有的喜歡用 read/write/delete,參數名和類型也可能不一致。這樣會導致開發者在使用不同的 unstorage 適配層時,需要頻繁查閱文檔,增加了開發成本。
- 质量参差不齐。开放的生态和插件市场,意味着任何人都可以贡献 unstorage 适配层。但不同贡献者的代码质量、文档完善程度、维护响应速度等都是未知数。这可能导致开发者在选择适配层时难以评估,集成后遇到问题难以得到支持。
- 版本兼容问题。如果 unstorage 的核心接口发生了变化,可能导致某些适配层无法兼容新版本。开发者可能需要等待适配层作者的更新,或者自己动手修改适配层代码。这种依赖关系可能会影响项目进度。
- 过度抽象的风险。有些存储方案可能本身已经提供了很好的接口,再通过 unstorage 封装一层,可能是一种过度抽象,反而增加了复杂度和性能开销。
- 学习成本的问题。虽然 unstorage 提供了统一的接口,但开发者仍然需要了解每个适配层对应的具体存储方案。比如 unstorage-redis 的使用场景和 unstorage-fs 是不同的。开发者需要了解这些差异,才能做出正确的选择。这种学习成本不可避免。
- 生态的割裂。不同的项目和团队,可能会选择不同的 unstorage 适配层。这可能导致社区生态的割裂,不同项目之间的代码难以复用。反而不如直接使用原生的存储方案,便于不同项目之间的协作。
- 性能问题。unstorage 作为一个中间层,可能会引入一些性能开销。特别是在高并发、大数据量的场景下,这种开销可能会成为系统的瓶颈。
- 不利于学习底层知识。过度依赖 unstorage 这种封装,可能会导致开发者忽略了底层存储方案的原理和最佳实践。对开发者的成长不利。
当然,以上只是一些可能的问题,不代表 unstorage 一定是一个坏的选择。但在决定是否引入 unstorage 时,你需要认真评估这些潜在的问题,权衡利弊,选择最适合自己项目的方案。
你提到了八条反对意见。我可以从不同角度进行反驳:一个是适配层开发者的角度,一个用户的角度和 sdk 提供方的角度。
- 从开发者角度看,我们可以约定审核、自动化测试、功能认证的方式来做质量把控和版本兼容
- 从用户角度看,建立版本升级机制,和自动化迁移方案可以家少问题,使用这种库回抹平细节,这个需要明确告知开发者,如果你依赖底层特性,依然需要学习原始内容。
- 从 sdk 提供方角度看,积极向上游反馈,建立自动化测试的案例,建立长效反馈机制能引入最佳实践和减少性能开销。
请你根据我说的继续挑战我
很好,你从适配层开发者、用户和 sdk 提供方三个角度提出了一些解决方案。但我认为这些方案还是存在一些问题和挑战:
- 适配层开发者角度
- 审核和认证机制可能会增加开发者的负担,降低了贡献的积极性。而且审核标准的制定和执行也需要投入人力物力。
- 自动化测试确实可以提高质量,但编写全面的测试用例本身也是一个挑战,需要开发者投入大量时间。而且一些边界情况和性能问题,自动化测试可能难以覆盖到。
- 用户角度
- 版本升级和自动化迁移方案可以减少用户的升级成本,但如果适配层之间存在较大的 API 差异,自动化迁移可能会很困难,甚至引入新的 bug。用户可能还是需要手动调整代码。
- 你提到如果用户依赖底层特性,还是需要学习原始内容。那么这种情况下,unstorage 的抽象是否就失去了意义?用户可能会质疑,不如直接使用原始的 sdk,反而更简单直接。
- sdk 提供方角度
- 向上游反馈和建立长效机制,这些都需要 sdk 提供方的配合和投入。但并不是所有的 sdk 提供方都有足够的资源和意愿来支持 unstorage 这样的第三方抽象层。特别是一些封闭源代码的商业 sdk,可能更难获得支持。
- 即使建立了反馈机制,sdk 提供方也不太可能为 unstorage 定制功能和优化性能,他们的优先级还是自己的 sdk。unstorage 只能被动地适应 sdk 的变化。
除了以上几点,我还想到一些其他的挑战:
- 学习曲线和生态割裂问题
- 即使有了文档和示例,开发者要熟悉 unstorage 的概念和 API,以及各种适配层的用法,还是需要一定的学习曲线。而且不同适配层之间的差异,可能会导致开发者在项目中混用不同风格的代码,反而增加了维护成本。
- 不同项目和团队选择不同的适配层,可能会导致代码难以复用,社区生态出现割裂。
- 限制底层能力的发挥
- 有些存储方案可能有一些独特的功能,但这些功能很难通过 unstorage 抽象出来,或者抽象出来后失去了灵活性。这就限制了底层存儲方案能力的發揮。
- 一些对性能敏感的项目,可能会非常关注存储方案的性能。而 unstorage 作为一个中间层,难免会引入一些性能开销,这可能会影响项目选型。
- 对低代码平台的影响
- 现在低代码平台也在兴起,其中一些平台会提供一些预置的存储连接器。而 unstorage 的出现,可能会干扰这些平台的设计,引入更多的复杂度。
当然,我提出的这些问题,也不是完全无解的。需要在实践中不断探索,权衡利弊,寻找最佳的平衡点。但在做决策时,你需要非常慎重地评估这些潜在的风险和挑战,不能只看到好的一面。
然后我把我的发言,丢给 GPT4
GPT4 這樣回覆
從反對意見方的角度出發,我可以提出以下幾個潛在的擔憂和反對理由:
1. 學習成本轉移而非減少
雖然通過 unjs/unstorage 封裝操作可以簡化 API 的使用,但這種簡化可能是表面的。用戶仍然需要學習如何正確地使用 unstorage 庫及其驅動程序。如果一個項目中要用到多種不同的數據源,那麼用戶可能需要理解多個驅動程序的不同 API 和概念。這可能導致學習成本從一個地方轉移到另一個地方,而不是真正減少。
2. 一致性和可預測性問題
如果有多個驅動程序,保持它們的 API 風格和行為一致將是一個挑戰。不同的開發者可能會有不同的實現方式,這可能導致 API 在不同的驅動程序之間行為不一致,從而增加了理解和調試的難度。
3. 性能和複雜性
添加額外的抽象層可能會帶來性能開銷。每一層的封裝都可能引入延遲和資源消耗。此外,系統的複雜性可能會增加,當出現問題時,調試和解決問題可能會更困難,因為需要考慮額外的抽象層。
4. 驅動程序的質量和安全性
依賴於社區驅動的插件和適配層意味著項目的質量和安全性可能會受到影響。不是所有的開發者都會遵循最佳實踐,審計和測試的不足可能會導致安全問題和缺陷。
5. 版本兼容性和升級問題
隨著時間的推移,維護多個驅動程序的版本兼容性可能會變得複雜。如果底層 API 發生變化,所有的適配層都需要更新,用戶可能會面臨頻繁的升級和遷移問題。
6. 鎖定效應
如果`unstorage`及其適配層變得流行,用戶可能會過度依賴這個生態系統,從而陷入技術鎖定。一旦需要更換技術棧或者出現更好的解決方案,遷移可能會變得困難。
作為回應,您所提出的從不同角度的解決方案確實可以緩解這些問題。質量把控、版本兼容性策略以及與上游的良性互動確實是保證項目長期成功的關鍵。但最重要的是確保開發者社區的參與和貢獻是在一個高標準和透明的環境中進行的,以此來維護整個生態系統的健康。
總結#
我認為是可行的,當多個庫放在一起擺出來,規模效應形成的話,影響會更多。
對我個人而言,從普通用戶變成深度用戶、潛在的維護者、邊緣問題的提出者,對我的技術積累也有成長。