Why change-impact analysis is surprisingly hard in Ruby on Rails
Why change-impact analysis is surprisingly hard in Ruby on Rails
为什么在 Ruby on Rails 中进行变更影响分析出奇地困难
Refactoring a mature Rails app often starts with a simple question: If I change this method, what else could break? In a smaller codebase, grep might be enough. In a larger Rails app, not really.
重构一个成熟的 Rails 应用通常始于一个简单的问题:如果我修改了这个方法,还有什么会受到影响?在较小的代码库中,使用 grep 可能就足够了。但在大型 Rails 应用中,这显然不够。
A method can be connected through: callbacks, associations, routes, background jobs, mailers, concerns, templates, tests, and indirect Ruby callers. And because Ruby is dynamic, even resolving something that looks like a simple method call can become ambiguous. That made change-impact analysis an interesting problem to work on. 一个方法可以通过以下方式产生关联:回调(callbacks)、关联(associations)、路由(routes)、后台任务(background jobs)、邮件发送器(mailers)、关注点(concerns)、模板(templates)、测试(tests)以及间接的 Ruby 调用者。由于 Ruby 是一门动态语言,即使是看起来简单的函数调用,其解析过程也可能变得模糊不清。这使得“变更影响分析”成为了一个值得研究的有趣课题。
The rule I chose early: I’d rather miss an ambiguous relationship than confidently invent one. So instead of pretending every relationship is certain, the analyzer records evidence and confidence around what it finds. For example: ripple-effect inspect 'BillingService#charge'
我早期确立的原则是:宁可漏掉一个模糊的关联,也不要凭空捏造一个。因此,分析器不再假定所有关系都是确定的,而是记录下它所发现内容的证据和置信度。例如:ripple-effect inspect 'BillingService#charge'
The goal is to answer questions like: Who calls this? Which Rails components depend on it? What can reach it indirectly? Which tests are likely relevant? Why does the analyzer think this relationship exists? Where is it unsure? You can also inspect the impact of a branch: ripple-effect diff main
其目标是回答诸如以下的问题:谁调用了它?哪些 Rails 组件依赖于它?什么可以间接访问它?哪些测试可能与之相关?为什么分析器认为存在这种关系?它在哪些地方不确定?你还可以检查某个分支的影响:ripple-effect diff main
The result became RippleEffect. RippleEffect is an open-source Ruby gem for static change-impact analysis in Rails apps. It does not: boot the Rails app, connect to the database, evaluate application code, upload source, or call an LLM. Everything is analyzed locally and deterministically. 最终的成果就是 RippleEffect。RippleEffect 是一个用于 Rails 应用静态变更影响分析的开源 Ruby gem。它不会:启动 Rails 应用、连接数据库、执行应用程序代码、上传源码或调用大语言模型(LLM)。所有分析都在本地以确定性的方式完成。
I’ve been testing the first release against real Rails codebases including Lobsters, RubyGems.org, Solidus, and Mastodon. There are still plenty of hard cases in dynamic Ruby, which is exactly what makes the problem interesting. If you work on large Rails apps, I’d be curious: How do you currently answer “what else could this change affect?” before a refactor? 我已经使用第一个版本对真实的 Rails 代码库进行了测试,包括 Lobsters、RubyGems.org、Solidus 和 Mastodon。在动态的 Ruby 语言中,仍然存在许多棘手的情况,而这正是该问题有趣之处。如果你正在从事大型 Rails 应用的开发,我很想知道:在重构之前,你目前是如何回答“这次修改还会影响什么?”这个问题的?
GitHub: https://github.com/iamzayn19/ripple-effect RubyGems: https://rubygems.org/gems/ripple_effect