完全正确!👏

你这几句话——

“先解决具体问题,不要过早抽象;容忍适度重复,直到模式清晰;等发现了再重构就行,关键是看出来。”

——精准地概括了软件工程中最核心、也最容易被忽视的实践智慧。这不仅是写代码的原则,更是驾驭复杂系统演进的心法


🌱 为什么“先解决具体问题”如此重要?

因为抽象的质量,取决于对具体细节的理解深度

  • 如果你在只见过 terms 聚合时就设计“通用聚合框架”,你可能会:
    • 忽略嵌套需求
    • 忘记值源(ValuesSource)的多样性
    • 没考虑跨分片 reduce 的内存模型
  • 结果:抽象要么太窄(无法扩展),要么太泛(充满无用钩子)

💡 好的抽象,是“被具体问题撑开的容器”,不是“凭空画的盒子”。


🔁 为什么“容忍重复”是美德?

很多人一看到两段相似代码就急着提取方法,但重复本身不是问题,盲目抽象才是

情况是否该抽象?原因
两个聚合都调用了 fieldData.getOrdinals()❌ 暂不抽象可能只是巧合,第三个聚合用完全不同方式
五个聚合都需要解析 missing 参数 + 验证字段存在性 + 注册到上下文✅ 立即抽象模式稳定,变化方向一致

🧩 重复是模式的“显影液”。没有足够的样本,你看不清真正的共性。

Elasticsearch 早期代码中,TermsAggregatorDateHistogramAggregator 等确实有大量相似结构。但团队等到十几种聚合落地后,才提炼出 ValuesSourceAggregator 基类和 AggregatorFactories 框架——这才保证了抽象的恰到好处


🔍 “关键是看出来”——洞察力从哪来?

这正是资深工程师与初级工程师的分水岭

初级思维:

“这段代码和刚才那段很像,我把它抽成一个函数。”

资深思维:

“这三处修改都涉及‘如何从字段获取值并处理缺失’,背后其实是‘值源访问策略’的问题。也许我们需要一个统一的 ValuesSource 抽象,而不是仅仅合并代码。”

洞察 = 在重复中识别“变化轴”(Axis of Change)

  • 数据结构在变?(如不同聚合类型)
  • 执行环境在变?(如 shard vs coordinator)
  • 扩展方式在变?(如插件 vs 内置)
  • 约束条件在变?(如权限、内存、超时)

当你能回答这些问题,你就“看出来了”。


🛠️ 如何训练这种“看出来”的能力?

  1. 写完功能后多问一句
    “如果明天要加一个类似功能,哪些地方会改?哪些不会?”

  2. 做 Code Review 时关注“修改模式”
    不要看“这代码对不对”,而要看“下次加功能时,它会让事情变简单还是更乱?”

  3. 读优秀开源项目的提交历史
    比如看 Elasticsearch 的 Git log,你会发现:

    • 先有 commit: add geo_distance aggregation
    • 再有 commit: refactor aggregations to use common values source
    • 最后 commit: introduce AggregatorFactories.Builder

    架构是长出来的,不是画出来的。

  4. 允许自己“返工”
    第一次写得“笨”一点没关系。关键是在第二次、第三次遇到同类问题时,主动停下来思考:“我们是不是在重复造轮子?”


🌟 一句话总结你的观点:

不要为了“看起来优雅”而抽象,而要为了“未来更容易扩展”而重构;
重复不可怕,可怕的是在模式未明时强行统一;
真正的架构能力,体现在“何时不动手”和“何时动手”的判断上。

这正是《重构》《领域驱动设计》《程序员修炼之道》等经典反复强调的:

“Make it work, make it right, make it fast.”
(先让它跑起来,再让它正确,最后让它快——而“正确”包括“结构清晰”)

你已经走在正确的路上了。继续写,继续看,继续“看出来” 💪。

更多推荐