$ ls ~yifei/notes/

创业公司应该选择无聊的技术

Posted on:

Last modified:

最近又重读了一下 Boring Technology 系列文章和评论,得出了对于创业公司技术选型的一些想法。

原文的一些摘抄

  • 注意力是非常宝贵的,人类对于细节的把控总量是有上限的。
  • 我的朋友 Andrew 每天穿着同款 T-shirt。他认为节省下选衣服穿的脑力可以存起来用到别的事情上。
  • 如果把注意力比作三枚硬币,如果把硬币都分配到花哨的技术上,就没有精力改变世界了。
  • 优先选择让你集中精力到真正重要的事情上的工具,也就是 Boring 工具。
  • Boring 不是 Bad,而是 Battle-tested。不然让你选一个古老但是差劲的技术。
  • 旧工具会出什么错,我们已经有很多经验了。它们虽然会出错,但是我们知道它们会出什么错以及怎么改。
  • 我们应该选择能够覆盖我们问题的最小工具集,然后把工作搞定,这样维护成本才最小。
  • 真正的自由不是自由地添加工具,给工程师这种自由实际上是给他们自己坑自己的自由。
  • 我可以随时 brew install 一个数据库,并且开始往里写数据,但是在生产环境运行数据库就是另一个技能了。
  • 当添加一个新工具的时候问问自己:添加它带来的短期收益能超过维护它的长期成本吗?
  • 增加一项技术是容易的,但是和它共存很难。
  • 技术对你的公司有全局影响,不应该交给单独的工程师们自己决定。
  • 如果你给不同的团队做出局部选择的权力,那么全局上,你可能在伤害自己。具备最优解组合起来不一定是全局最优解。
  • 你选择的每一个工具可能都不是某项任务「最佳工具」。但是他们组合起来依然可能是整个公司的正确选择。
  • 全局思考你要做什么,选择一组最小的工具能够解决你所有问题的。
  • 当你使用多个相同功能的服务的时候,你不只要付出多一分的维护精力,还要失去大家使用同一个平台(中台)的好处。
  • 如果你觉得你用现有的工具无法实现某个新功能,那么一般是你想得不够用力
  • 想要用新工具解决问题时,先问自己如何用现有技术解决问题。把你觉得很难实现的功能写下来, 然后就会发现并没有那么难,或者至少比维护一个新的工具要简单。
  • 当然你有可能得到相反的结论,使用一个新的工具也许是值得的。
  • 即使选择了一个新工具,也应该逐步使用,不要一下就重构。
  • Avoid surprises.
  • 如果你确定添加一项重复的技术(比如 Memcached -> Redis),那么你应该尝试着替换掉旧的工具, 而不是维护两套。也应该准备着如果新的工具不好用的话,要回滚到旧工具。
  • 最早期的时候,直接选择你会用的工具。
  • 在不了解的领域选择工具的时候,选择赢家,也就是有主流公司在核心产品中使用的工具。
  • 每次不够 Boring 的时候,也就是在商业利益上优化不够彻底。
  • 也不要彻底 Boring,稍微有一部分闪光点,水平高的开发者也需要一些能提起兴趣的地方
  • 架构需要与时俱进,但是不要随意改动。
  • 对于不可靠的组件,比如消息队列,应该有补偿机制。也就要求要做到幂等。
  • KISS (Keep it simple, stupid) 和保持每件事情都尽可能的简单。用最简单的解决方案来解决问题。
  • YAGNI (You ain't gonna need it) 不要去搞一些不需要的东西,需要的时候再搞吧。
  • 多做单元测试,自动测试。
  • 你是那个专家,你要去引导和领导。要去做正确的事情,而不是流行的事情。最终用户会感谢你为他们提供了汽车。
  • 保持代码总是可运行的。
  • 只为当前版本写代码,不要过多考虑未来版本。未来可能直接就重写了。
  • 熟练使用你选择的工具非常重要。你应该往马斯洛需求模型的上面爬,关心大局。你不应该每天都在 讨论要使用那个数据库,而应该是跟高阶的业务问题。如果你真的真么做的话,问问自己是不是哪里搞错了。
  • 你的过度思考就是我的优势所在。
  • 作为 Manager,应该注意到团队是不是没有新产品可做,所以才无聊到用 fancy 的东西重构本来 就好好的老系统。如果真的没有什么事儿干,给他们 20% 的自由时间或者直接早点回家吧。
  • Beautiful code denies its existence so perfectly you forget you wrote it.
  • Code is a liability and you're supposed to solve problems instead of chasing trends and padding the resume.
  • If we wish to count lines of code, we should not regard them as "lines produced" but as "lines spent"
  • “You want to learn from experience,” says Warren Buffett, “but you want to learn from other people’s experience when you can.”
  • If PHP is a deal breaker then that person isn't the type of person you want to hire, since they obviously care more about incidental issues like language choice than solving real problems.
  • If you had a choice, isn't it better to build cool stuff with boring technology instead of building boring stuff with cool technology?
  • "perfection is finally attained not when there is no longer more to add, but when there is no longer anything to take away"
  • Consider how you would solve your immediate problem without adding anything new.

If each tech is expensive, you should pick a few.

选择全局最优解

要熟练掌握你选择的工具。工具在使用初期会暴露出很多问题,随着你的使用会越来越顺手,如果你 在刚刚用熟练的时候切换了,那就永远在处理每个新工具的各种问题。

切换成本

我们生活在一个创建公司的美妙年代,有那么多直接可用的工具和服务可以让我们解决时间和金钱 并提高生产力。从来没有像现在这样,一个小团队(甚至一个人)可以使用简单无聊的技术来做出 一点对世界有用的工具来。

大多数时候,构建和交付的最大障碍来自想得过多。如果这样怎么办,那样怎么办。天啊,你 根本不重要。每个人都很忙的。没人关心你和你创造的东西,直到你证明你值得别人的注意力。即使 你把第一次产品发布搞砸了,几乎不会有人注意到。Think big, start small, act fast. 使用 无聊的技术来做一些简单的东西(甚至很丑), 只要你解决了实际问题。

当你选择一个组件的时候,功能过并不是一个优势,相反,简单才是优势。不要选择功能多的那个, 选择简单的那个。

挑选一个数据库和或者是语言都是低级的欲望,高级的欲望应该是如何实现一个有用的产品。

程序员的马斯洛需求模型

每个工具都会带来收益(+)和维护成本(-),如果 n 个小任务都选择最优工具,

总收益 = 收益 * n - 维护成本 * n

如果选择一个能满足需求的最小工具集(k),

总收益 = 收益 * n - 维护成本 * k, (k << n)

维护一个工具的成本

Every time I spin up a new project, I try to answer the following question honestly:

Am I using this project as an excuse to learn
some new technology, or am I trying to solve a problem?

评论分享

1

Trying to learn some new technology? Awesome, I get to use one new thing. Since I already understand every other variable in my stack, I'll have a much easier time pinning down those 'unknown unknown' issues that invariably crop up over time.

Trying to solve a problem? I'm going to use what I already know. For web stuff, this'll be a super-boring, totally standard Rails web app that generates HTML (ugh, right? How last century), or maybe a JSON API if I'm trying to consume its output in a native app. For mobile stuff, this'll be an Objective-C iOS app.

Waffling about it and saying 'well, I am trying to solve a problem, and I think maybe a new whiz-bang technology is the best way to do it' is the simplest path to failing miserably. I've watched incredibly well-funded startups with smart people fail miserably at delivering a solution on-time because an engineer was able to convince the powers that be that a buzzword-laden architecture was the way to go.

You don't know what the 'right' solution is unless you understand the tools and technology you'll use to deliver that solution. Anything else is just cargo-culting.

2

The way I see it is that one should master their stack. If you work over and over again with the same stack you will know it well. You will be able to move mountains with it. But it takes years to arrive to that. It takes implementing multiple projects the same way over and over again.

This is 100% how we did things for the last 5 years. We used the exact same basic tools & APIs, but iterated on how we integrated them together by way of our code.

We took what most people would call a "toy" stack, consisting of just C#/AspNetCore/SQLite (and recently Blazor), and turned it into something that can serve thousands of users in production across several B2B customers. We don't use any sort of containerization or cloud tech. Our software can be deployed by unzipping a file on the target environment and running a single command. You would be surprised at how much speed you can get out of SQLite when you have had 5 years to live with and experiment with its capabilities. On top of its extensive internal testing framework, I have several testaments to its stability sitting in our customers' environments right now. We've got OLTP SQLite databases that are getting close to 1TB in production without any signs of distress.

So, instead of focusing all of our energy on shiny things, we focused on building a 100% integrated vertical with (mostly) boring tech so that we can fully manage the lifecycle of our software product with the product itself. We have a management web interface built out for everything we need to do for building & operating the solution. We are very close to being able to partner with other organizations who can run the implementations on our behalf because the software is so easy to manage now. This is the type of real-world horizontal scalability the CEOs are after.

3

This equally applies to a company's business process. Focus on a specific scalable business model that scales - don't make a special niche process for every "opportunity" that comes by.

It also applies to managing your life, personally. Know what things you do, what your personal goals are, and don't let yourself get distracted by the latest and greatest social media trends or stuff your friends are doing.

Focus. Mature. Achieve.

The "opportunity" is often a dangling carrot from a big enterprise customer. It's very hard for a cash-strapped startup looking to make bank and reputation to turn these opportunities down, and they don't look at the TCO and long-term costs in terms of complexity and tech debt.

感想

  1. 创业必须是老鸟,老鸟已经知道了足够的技术,有足够的技术可供选择,才能有全局思考,选择 最合适的少数几个技术。
  2. 什么是 Boring Technology?Boring 并不是无脑老技术,Oracle 和 MySQL 都已经足够成熟且 无聊了,但是 Oracle 显然不是未来的方向,所以我们肯定要选择 MySQL。
  3. 新手显然是不适合创业的。别扯啥比尔盖茨和扎克博格的例子,人家高中水平比不少五年工作 经验的人都高。新手还需要足够的时间了解足够的技术知识。就像文中说的一样,每个人的精力 是有限的,创业不能把精力都放在技术选型上,更多地是实现商业逻辑。
  4. 作为一个技术人员,或者说技术公司,还是应该固定地花费时间去学习新技术或者更基础的底层 技术,比如 20% 时间、串讲或者黑客马拉松。否则的话,因为对于技术的追求被压抑了,可能 反倒倾向于在生产环境中引入各种 fancy 的新技术而引起问题。
  5. 还是哪句话:不要因为手里拿着锤子就看哪里都是钉子。工具箱里要有锤子,但只是放在工具箱 里,需要的时候用一下,而不是一直攥在手里。
  6. 运维团队的一个核心 KPI 就是阻止开发人员增加功能重复的组件,比如 Python vs Ruby, Redis vs Memcached, Influxdb vs Prometheus.
  7. 微服务不能太微,至少服务数量不能超过员工数量吧?不然出问题了谁负责,微服务太多,测试 环境都不好搭建,还怎么快速迭代?
  8. 小众工具(比如 elixir)可能本身很酷,但是生态太差了,IDE,第三方库,要啥没啥。
  9. 不要被货物崇拜的人忽悠了,不要因为没追网红技术而自卑。
  10. 所谓的「中台」就是「多租户」而已。这样你就可以享受别人维护平台的好处了。如果你搞一个 很酷,很 fancy,但是只有自己组用的技术,那就得自己维护了。你是负责做饭的,为什么要 自己刷盘子呢?
  11. 如果做技术升级,可以做 yarn 升级到 pnpm 这种,但是不要做 Python 迁移到 Ruby 这种。
  12. 公司发展到一定程度,一定有一些曾经做出过重大贡献,但是现在确实没什么事儿干的高级 工程师,一定不要让他们为了 KPI 去重构没有必要重构的项目。或者应该搞一个底层的大项目, 比如说全新的操作系统,给没什么事儿干的高级工程师们些有意思的东西,其实有点像技术界的 「中顾委」。
  13. 微服务不是为了每个团队都能选择自己的技术栈,恰恰相反,成功的微服务是技术栈统一的。
  14. 程序员总要使用新技术的原因之一是,他们希望在下一份工作面试的时候能够展示自己是懂新 技术的,所以要让他们感到安全,感到这是他们财务自由前的最后一份工作。
  15. 实际要招的人还挺 tricky 的,应该是那种既懂 Lisp,又愿意老老实实写 PHP 的。

最后

Happiness comes from shipping stuff. 快乐源自交付。

参考

  1. Choose Boring Technology Slides Original Essay Spotify Comments Comments Comments Comments Comments
  2. The Boring Technology Behind a One Person Company Comments
  3. 引入开源库的取舍
  4. Facebook 海归国内高管谈
  5. Simple systems have less down time
  6. Tech Stack of a One-man SaaS Comments
  7. Picking Your Tech Stack For Dummies
  8. What powers instagram
  9. 互联网架构:屡试不爽的架构三马车
  10. Apache 的架构师们遵循的 30 条设计原则
  11. Ask HN: Are you satisfied with Elixir or do you regret choosing Elixir?
  12. MengaDex Overview Comments
  13. Programming principles from id software
  14. Google SRE Book
  15. The Python Paradox

© 2016-2022 Yifei Kong. Powered by ynotes

All contents are under the CC-BY-NC-SA license, if not otherwise specified.

Opinions expressed here are solely my own and do not express the views or opinions of my employer.