HarmonyOS开发者限时福利来啦!最高10w+现金激励等你拿~ 了解详情
写点什么

最好的 Go 框架就是不用框架?

  • 2023-10-03
    北京
  • 本文字数:3090 字

    阅读完需:约 10 分钟

大小:1.58M时长:09:13
最好的Go框架就是不用框架?

 撰写本文时,我已经领导 Go 团队好多年了。我从初学者那里听到的最常见的问题是:我应该使用什么框架?

 

在使用 Go 的过程中最糟糕的事情之一就是遵循其它编程语言的方法。其它语言已经建立了“默认”框架:Java 的默认框架是 Spring,Python 的默认框架是 Django 和 Flask,Ruby 的默认框架是 Rails,C#的默认框架是 ASP.NET,Node 的默认框架是 Express,PHP 的默认框架是 Symfony 和 Laravel。而 Go 不同:没有默认框架。

 

更有趣的是,许多人建议你根本不应该(在 Go 中)使用框架。他们疯了吗?

 

Go 语言的哲学

 

Go 框架是存在的,但没有一个 Go 框架提供项其它语言框架那样的功能集。这点短期内不会改变。你可能认为这是因为 Go 生态系统比较“年轻”。但是还有一个更重要的因素。Go 是围绕 Unix 哲学构建的:

 

  • 一个程序只做一件事并把它做好。

  • 程序间协同工作。

  • 编写程序来处理文本流,因为这是一个通用接口。

 

这个理念来自 B 编程语言(C 语言的前身)的设计者肯·汤普森(Ken Thompson),他也是 Go 语言的设计者。

 

在实践中,Unix 哲学倾向于构建小而美的软件,而不是大而全的软件。你可以在你的终端中看到这些例子。例如:cat example.txt | sort | uniqcat 从文件中读取文本,sort 对行进行排序,uniq 删除重复行。所有命令都是独立的且只做一件事。这直接来自 Unix 哲学。得益于这样的设计,你可以独立开发比较小的自治命令。

 

在 Go 中,Unix 哲学在标准库中随处可见。最好的例子是应用最广泛的接口:io.Readerio.Writer 。最好的库都遵循这种哲学。

 

框架的设计违背这种哲学理念。通常,它们试图在一个框架内涵盖所有可能的用例。它们不是为了与其它工具一起使用而设计的,而且通常无法复用。这意味着不可能将开发成果转移到其它不兼容的框架。如果框架的采用率很低(或者就是死了),那所有的努力都白费了。

 

对你来说,什么是重要的

 

每个技术决策都有权衡,你的选择要对你和你的项目更有意义。

 

当你在从事一个短期项目(比如用时不到一周且用完即扔的概念验证项目)时,有些方案是有意义的。在这种情况下,最关键的因素是你能多快地完成它。但是如果你在从事一个持续很长时间的项目,并且你要与多人一起协作,那么这个决定的影响是巨大的。

 

对于大多数项目,最重要的参数是:

 

  • 你能以多快的速度启动项目

  • 从长远来看,你能以多快的速度开发项目

  • 对于未来的变化,项目的灵活度(这与前两点紧密相关)。

 

让我们开始评估我们的决定。

 

节省时间

 

框架最大的好处之一就是节省时间。运行一个命令就可以得到一个功能齐全的项目。框架通常提供一个固定结构的项目,而且如果你不知道如何做,它会有很大帮助。但与大多数其他技术决策一样,它不是没有代价的。

 

随着时间的推移,当项目增长时,你会很快触及框架在约定和限制方面的墙壁。框架作者的需求跟你的需求可能有所不同。框架创建者采取的决策可能适用于简单的 CRUD 应用程序,但无法处理更复杂的场景。如果继续使用,很容易就为了克服一个框架限制而迅速失去在项目启动上节省的所有时间。随着时间的推移,这可能会导致团队遇到很多挫折。

 

几年前,我在一家使用 Go 框架(我会略过框架名称)的初创公司工作。这家公司正在成长并创建新的服务。随着时间的推移,当我们想要支持的复杂用例越多时,我们就感到越痛苦。这个框架也是严重 Bugs 的来源。不幸的是,摆脱这个框架并不容易。

 

有一次,一些框架组件变得无法维护,与生态系统的其它部分不可兼容。我们被迫摆脱这个框架,而这个框架已经与整个系统紧密耦合。将其从数十个服务中移除是一个不小的任务,这需要一个跨团队的计划、需要多人数月的时间和努力,才能摆脱这个框架。即使这个项目最后成功了,我也不认为整个事情是成功的。如果有人更早做出不同的决定,所有花费的时间可以被利用得更好。整个项目都不是必要的。许多公司对开发团队缺乏信任也就并不令人奇怪了。

 

这是一个很好的例子,表明了一个小小的决定会在数年后变成一个代价高昂的需要“救援”的项目。

 


项目的可维护性

衡量项目的可维护性是一个有争议的话题——很难比较两个项目的可维护性。有些人说框架很棒,他们没有感到使用框架的痛苦。对其他人来说,框架可能是长期以来最大的噩梦。有些项目比其他项目更具挑战性,许多人认为与框架较劲只是工作的一部分。这就是为什么很难客观地衡量框架对项目可维护性的影响。

 

幸运的是,我们可以用一点科学知识来理解它。基于科学研究的《Accelerate: The Science of Lean Software and DevOps》一书,聚焦于找出表现最好和表现最差的团队的特点。对我们来说重要的是,良好性能的最重要的一个因素就是松耦合架构。

 

我领导的团队经常问我,“如何知道我们的架构是松耦合的”,最简单的方法之一是确保应用程序的部件可以轻易替换或删除。如果你的应用程序的部件很难删除,那么你的应用程序就是紧耦合的。这样的紧耦合会导致牵一发而动全身,引发多米诺效应。

 

为什么松耦合架构如此重要?需要承认,我们都是人,即使经过了最好的调研,我们也会犯错。当你选择了错误的库或框架,应该很容易替换而不需要重写整个项目。如果我们想要节省时间,我们应该考虑从长期来看有什么帮助,而不仅仅是在项目开始时。

 

请考虑一个场景,当你想要完全删除一个框架时,需要重写大量代码吗?它可以在多个服务上独立运行吗?如果不行,那么你需要花些精力将框架和核心逻辑分开。但是,这会牺牲框架一开始时带来的“省时”。

 

备选方案?构建服务时不用框架

 

你可能会觉得,在没有框架的情况下构建服务需要很长时间,尤其是如果你之前使用其它编程语言。我理解这一点,几年前当我开始用 Go 写程序时,我也有相同的感受。但是,不用框架并不意味着你自己需要构建一切东西,有许多经过验证的库会提供你需要的功能。

 

这意味着,你需要在调研上多花一点儿精力。如果你正在阅读本文,那你就已经在调研了!几个小时的调研时间在整个项目的生命周期中几乎不值一提。你这样做所带来的灵活性,很快会将你调研所花的时间“挣”回来。

 

如果你决定不使用框架,应该怎么办?一开始最大的障碍可能是如何构建一个服务。最简单的方法是一开始将所有东西放到一个文件中。你可以简单地开始,推迟一些决定,然后随着时间的推移演化你的项目。

 

如果有示例项目可以作为参考,那么这会很有帮助。你可以看看我在GoRemoteFest – github.com/roblaszczak/goremotefest-livecoding上的演讲“让我们用 Watermill 在 15 分钟内构建一个事件驱动应用程序”所用的项目。这个示例项目只需要两个外部库就可以运行了。

 

请随意 copy 这个代码库并根据你的需要调整,我确信这个示例不会有你项目所需的全部的库。我们发布了一篇文章介绍可以用来构建 Go 服务的 Go 库清单。这些库我们已经用了几年了,还解释了我们为什么使用这些库,以及如何识别类似的库是好还是坏。

 

文章链接:

https://threedots.tech/post/list-of-recommended-libraries/

 

当你的项目变得越来越复杂,而且你已经知道了你的库是如何协同工作的,那么你就可以开始重构它了。最后,你可能不需要那些看起来很关键的框架功能。得益于此,你可以得到一个更简单的项目并进行更少的调研。

 

总结

 

决定如何构建服务不是你应该走捷径的地方。从长远来看,做出错误的决定会对你的时间产生非常负面的影响。它会对团队的速度产生负面影响,更重要的是会影响士气。

 

在做出错误的决定后,你很快就会陷入沉没成本谬论的陷阱。与其成为解决自己制造的问题的英雄,我们应该避免制造这些问题。

 

作者介绍:

 

Robert LaszczakSlashID的首席工程师、三点实验室(Three Dots Labs)的联合创始人、Watermill库的创建者。

 

原文链接:

The Best Go framework: no framework?

2023-10-03 07:009558

评论 5 条评论

发布
用户头像
作者想表达的应该不是不用框架,而是别轻易用别人的框架,先做小而美的功能插件,最后整合成最适合公司业务的定制框架。 这样比直接用别人的框架,发现壁垒后再重构代价更小些。 当然自己整合一套扩展性,安全性,高效性都不错的框架也不是件容易的事,需要根据团队的时间和能力来考量。 所以这篇文章也只是根据作者自己情况的一个建议。
2023-11-16 23:09 · 广东
回复
用户头像
删了吧,你这个文章就是个笑话,框架的出现让企业级的应用喷涌而出,百花齐放,站在高出看问题,操作系统和应用程序完全不能类比,操作系统需要的是紧凑安全,富有扩展性生态,足够的灵活,大型应用需要的是规范,可扩展可和可维护性可靠性,至于性能都要往后稍一稍,流水的程序员铁打的项目,你说对了一半,编程和软件工程是个哲学问题,人们选择了它们就说明他们的必然性和正确性,存在即合理,不能张口就来,尝鲜是需要代价的,而且这个代价前人已经尝试过了,没必要写篇文章出来告诉我们封建专制的可持续发展性了优越性。
2023-11-02 13:52 · 上海
回复
用户头像
我们可以设计1w个小而美的组件,但是要有机、高效、安全的组合起来,还是离不开框架
2023-10-24 17:42 · 上海
回复
用户头像
设计框架是一个哲学问题,而不是技术问题。
2023-10-09 16:32 · 北京
回复
用户头像
项目做多了,之后把共用的部分提取出来还不是成了框架?如果框架不合适,何不自己从源码改造框架。如果没框架,每次做同样的服务,相同的层面不同的人有不同的做法,如何维护。
2023-10-04 16:46 · 广东
回复
没有更多了
发现更多内容

版本更新 | Towify V1.24.0 有哪些实用新功能?汇总来了!

Towify

时隔3个月,Uber 再遭数据泄露...

SEAL安全

数据泄露 uber 第三方风险 12 月 PK 榜

说说你对Vue的keep-alive的理解

bb_xiaxia1998

Vue

必会vue面试题(附答案)

bb_xiaxia1998

Vue

面试官:vue2和vue3的区别有哪些?

bb_xiaxia1998

Vue

一文盘点Zebec生态的收益模型

西柚子

实践丨GaussDB(DWS)资源管理排队原理与问题定位

华为云开发者联盟

数据库 华为云 12 月 PK 榜

教你用JavaScript完成简易贪吃蛇小游戏

小院里的霍大侠

JavaScript 编程开发 实战案例 初学者 入门实战

昨天,同事优化加锁方式时,出现死锁了

华为云开发者联盟

高并发 开发 华为云 12 月 PK 榜

社招前端二面react面试题整理

beifeng1996

React

NeurIPS 2022:基于语义聚合的对比式自监督学习方法

华为云开发者联盟

人工智能 华为云 论文 12 月 PK 榜

老生常谈React的diff算法原理-面试版

beifeng1996

React

最新前端面试总结

loveX001

JavaScript

vivo 云原生容器探索和落地实践

vivo互联网技术

机器学习 AI 容器 云原生 k8s

数据可视化图表系列解析——柱状图

Data 探险实验室

数据分析 可视化 数据可视化 BI 分析工具 可视化数据

问:React的setState为什么是异步的?

beifeng1996

React

分享一下MySQL数据库中好玩的14个小玩意

Java永远的神

Java MySQL 数据库 程序员 后端

京东前端高频vue面试题(边面边更)

bb_xiaxia1998

Vue

说说Vue响应式系统中的Watcher和Dep的关系-面试进阶

bb_xiaxia1998

Vue

promise执行顺序面试题令我头秃,你能作对几道

loveX001

JavaScript

关系型数据库设计三大范式

京东科技开发者

关系型数据库 数据库设计 范式 冗余 数据库·

程序员职场晋升:与阿里前P9的一次近距离互动

博文视点Broadview

ClassLoader 隔离性的基石是namespace,证明给你看

小小怪下士

Java 程序员 面试

Dubbo架构设计与源码解析(一) 架构设计

京东科技开发者

云原生 dubbo Java、 架构设计 分布式架构

HarmonyOS年度开发者活动,赋能逾万名开发者开启HarmonyOS学习之旅

Geek_2d6073

前端vue面试题集锦1

bb_xiaxia1998

Vue

web前端经典react面试题

beifeng1996

React

计算存储分离在京东云消息中间件JCQ上的应用

京东科技开发者

容器 中间件 存储分离 消息中间件 存储计算分离

关于Kubernetes中如何访问集群外服务的一些笔记

山河已无恙

12月月更

Spring Cloud 应用 Proxyless Mesh 模式探索与实践

阿里巴巴云原生

阿里云 微服务 云原生

Vue.$nextTick的原理是什么-vue面试进阶

bb_xiaxia1998

Vue

最好的Go框架就是不用框架?_编程语言_Robert Laszczak_InfoQ精选文章