接口最好从调用方倒着定义,别在实现还没稳定时先抽象
Go 学久一点以后,很多人都会记住一句话:interface 要小。但真到项目里,接口问题往往不是“大或小”这么简单,而是抽象出现得太早。实现只有一种、调用方式还没定稳,就先定义一堆 UserService、OrderRepository 接口,最后只会让代码多一层跳转。
Go 学久一点以后,很多人都会记住一句话:interface 要小。但真到项目里,接口问题往往不是“大或小”这么简单,而是抽象出现得太早。实现只有一种、调用方式还没定稳,就先定义一堆 UserService、OrderRepository 接口,最后只会让代码多一层跳转。
刚开始写 Go 的时候,很多人会觉得错误处理很重复:每层都要判断 err != nil,看起来很机械。可真到了线上排查问题时,最怕的不是判断多,而是最后拿到的错误只有一句 “open failed” 或 “query error”,根本不知道是哪一步出的事。
很多人刚写 Go 项目时,最有安全感的动作就是先把目录搭完整:controller、service、dao、model、utils 先分好,觉得以后扩展会方便。可项目在功能还不稳定的时候,包分得太细,往往比全写在一个地方更容易把自己绕进去。
第一次把 LevelDB 用进项目时,很容易被它的简单和直接打动:本地 KV、读写快、嵌入式、不用额外起服务。可也正因为它太像一个“很方便的本地抽屉”,很多人会自然把它当缓存来用,然后默认它应该顺便帮你解决缓存该有的那套问题。
Electron 最开始让人兴奋的地方,是你能用前端技术写桌面应用。可一旦真正接入 TCP 套接字、文件系统或者系统级能力,就会很快遇到另一个问题:主进程和渲染进程到底怎么分工?
VSCode 用久了之后,配置文件很容易变成一个巨大的杂物箱。今天装一个插件改一条设置,明天为了某个语言服务再补两条,过几个月回头看,自己都说不清哪些是个人习惯,哪些是项目要求,哪些只是某次临时实验留下来的痕迹。
Java 集合一学到 ArrayList 和 LinkedList,很多人就会形成一个很顺手的印象:前者适合查,后者适合增删,于是当某段代码出现“可能会插入删除”的需求时,就很自然地想把 LinkedList 搬出来。可真到业务代码里,这个选择远没有口诀那么简单。
学 Java 时,很多人第一次接触不可变对象,都会很快记住 final 这个关键字。于是项目里就容易出现一种误会:只要字段加了 final,对象似乎就安全、稳定、不会被改坏了。可真正写一阵业务之后你会发现,事情没这么简单。
刚开始学 Go,并发部分最容易让人紧张的词就是“死锁”。这当然没错,因为死锁一出现,程序常常会非常明显地挂在那里。可等你真正把 Go 服务跑起来一段时间后,会发现另一类问题更难受:goroutine 没有马上死掉,而是在后台一点点堆起来。
Java 集合遍历删除这个问题,很多人都知道有坑。
可真正麻烦的地方在于,它不是每次都立刻用最醒目的方式出错。有些代码在某个数据量、某种路径下能跑,看起来像是可用的,结果一换场景就开始报错或者漏删,这种“看起来能跑”的状态反而最危险。