使用Mikado方法在复杂的代码库中进行安全更改。
Use the Mikado Method to do safe changes in a complex codebase

原始链接: https://understandlegacycode.com/blog/a-process-to-do-safe-changes-in-a-complex-codebase/

## 使用Mikado方法处理遗留代码 继承一个庞大、复杂且文档匮乏的代码库,感觉就像陷入流沙。尝试进行重大更改——修复错误、添加新功能或重构——常常会导致连锁问题和进度停滞。Mikado方法提供了一种结构化的方法来避免这种情况。 其核心思想是将雄心勃勃的目标分解为小的、有时限的任务(5-15分钟)。如果任务在时限内失败,**回滚更改**并确定需要首先解决的更小的“子目标”。然后,在新的时限内处理这个子目标。成功的任务会**立即提交**,创建频繁的检查点。 这个迭代过程,可视化为分支的“Mikado”棍图,逐步解开依赖关系。例如,升级ORM依赖项可能首先涉及提取公共函数调用,然后调整单个实例,最后完成升级。 Mikado方法强调短时限以避免“沉没成本谬误”,并频繁提交以保持可发布的代码库。它关注于在尝试更大的目标之前,使每一步都*更容易*,最终实现对具有挑战性的遗留系统的有效且成功的更改。

## Mikado 方法用于安全的代码修改 一篇 Hacker News 讨论强调了“Mikado 方法”——一种用于对复杂代码库进行安全修改的技术,详情请见 understandlegacycode.com。该方法侧重于迭代的小幅修改,而非大规模重构。 一位用户成功地使用 Git 提交信息前缀和预提交钩子实现了该方法的变体,并记录在 [https://docs.eblu.me/how-to/agent-change-process](https://docs.eblu.me/how-to/agent-change-process),甚至将其与代理集成以处理更大的任务。 一个关键的挑战是抵制在迭代之间跳过完全重置的冲动,这可能导致混乱的代码库。与传统的“瀑布式”重构不同,Mikado 强调*最小化*的预先规划,允许灵活的进展并轻松放弃未成功的尝试,而不会丢失整体工作。它被描述为超越简单的“计划模式”,优先行动而非大量的预先规划。
相关文章

原文

You’ve inherited a 300k lines of spaghetti code. What do you do now?

Large, untested, poorly documented codebases are tricky to work with. They’re very hard to reason about.

You can’t move fast in a complex codebase.

Stuck in the quicksand of Legacy Code

The thing is, they called you to change that codebase! You need to meet new functional requirements. Or fix some bugs.

Maybe you decided that you’ll address the technical debt and refactor that legacy code. Maybe you want to improve the architecture of this system while it’s serving customers in prod.

But any valuable change takes you down to a path of failures 😩

Say you want to upgrade your ORM dependency. You start doing so, but you quickly realize that there are some breaking changes. So you need to change some function calls across the codebase. To make it easier, you decide to refactor and extract them somewhere, so you only have one place to change. But to do so, you need to adapt each call first…

Quickly you find yourself sinking into quicksand: whenever you fix 1 problem, 2 more arise.

The project doesn’t compile anymore. It has been a few hours since you committed the code. “I’m still working on it, I just need to fix a few things” is what your standup sounds like for a few days now…

If you’re here, you’re not alone!

And there’s a way to avoid the quicksand. I’m about to teach you: The Mikado Method.

A structured way to make valuable changes

The gist of it will sound like common sense:

There is only one way to eat an elephant: a bite at a time.

In a complex codebase, small changes quickly become an elephant.

If you address them upfront, chances are you’ll hit a wall. It will be painful. You will be late. Clients and management will be upset. Trust will erode and without trust, there are few chances you can get management support for necessary refactorings.

Instead, chop down the elephant into small pieces 🐘

The process

Concretely, here’s the Mikado Method process you can follow:

  1. Grab a piece of paper. Sometimes low-tech is better. This is such a time.

  2. Set a goal. Write it down on paper. Put it at the top or at the center, it doesn’t really matter. Just keep space for other items.

  3. Try to achieve the goal within a timebox. 5min, 10min, 15min, as you wish. Keep it relatively short.

    • If you failed:

      • Revert your changes. Undo what you did during the timebox. This is important to start fresh.
      • Think about what’s missing. What do you need to change to make the goal easier? That’s your subgoal.
      • Write it down on your paper and attach it to the goal you tried to achieve.
      • Start over from 3) with your subgoal.
    • If you succeeded:

      • Commit. You’ll certainly finish before the end of the timebox, that’s fine, stop the timer.
      • Check the goal you achieved on paper. Celebrate internally.
      • Start over from 3) with the next unchecked subgoal available. Start from the leaves of your Mikado graph. Iterate until you’ve checked your main goal.

What it looks like for real

Let’s go back to our ORM dependency upgrade.

First, write down the goal on a piece of paper. Draw 2 circles around. That’s your main goal!

Main goal: "Upgrade ORM"

You try to do so. You upgrade the dependency and realize the project doesn’t compile anymore. Damn, you should have read the changelog before!

Ok, so you read the changelog and understand you have to change some calls. Frankly, that’s a lot of changes for a single timebox!

Revert your changes. Really. Undo it. It matters. 🔥

Then, write down what needs to be done before.

How to change a few calls within a little timebox? Easy: extract the calls, so you don’t have many places to change. Make it so the upgrade in itself would be quick!

2 new goals: "Extract .query()" and "Extract .dump()"

Start over. Try to extract the first method within the timebox.

Hopefully, there are just a few calls and they all look alike. You can complete that task within a few minutes. Congrats!

Commit your work, check that subgoal and pat yourself on the back. You got closer to your main goal.

Goal "Extract .dump()" checked

Now try to address the other call. You start doing so, but it doesn’t go as smooth as the previous one 😩

After a couple of minutes, just stop and think. What’s missing? What would make it easier to do that change, like the previous one?

Maybe you first need to make each call look alike.

Revert your changes. Again. I’m serious.

Then write down the new subgoals.

2 new subgoals: "Adapt calls in booking" and "Adapt calls in cart"

Start over with one of the leaves. Iterate.

When each of its subgoals is checked, tackling a goal should be easy. In the end, you’ll make the main goal easy.

Then, just do it. Upgrade your ORM dependency.

Finally, everything is checked, including the main goal!

Congrats! You just implemented an ambitious change without getting stuck in the quicksand of the codebase.

3 advice to master the Mikado Method

  1. Make your timebox short. That way, it will be easier to revert your changes. It’s a critical step to avoid the sunk cost fallacy. I find 10min to be a pragmatic compromise.
  2. Commit when you check a goal. It’s a checkpoint that gets you closer to the main goal. It means you can stop anytime, open a PR and ship the improvements. You may not be done with the task, but you made it easier.
  3. Use this when you start an ambitious refactoring. Doing baby steps and keeping the code in a shippable state gives you incredible productivity.

Why is it called “Mikado”?

It’s a reference to the Mikado pick-up sticks game.

The Stick you want to remove is your ORM dependency upgrade.

It’s tangled with dozens of other sticks: annoying dependencies and tweaks you need to make, so the code still works.

The strategy is to remove the easy sticks first. The ones that are not tangled. Progressively, you untangle your Stick. Until you can reach it without breaking anything 🎉

There’s even a book that goes deep in detailing this process: The Mikado Method.

With a bit of practice, you’ll become good at it.

And you’ll become a much more efficient developer!

联系我们 contact @ memedata.com