Use the Mikado Method to do safe changes in a complex codebase

(understandlegacycode.com)

109 points | by foenix 4 days ago

18 comments

  • bob1029 47 minutes ago
    My favorite tool for trying scary complicated things in an unknown space is the feature flag. This works even if you have zero tests and no documentation. The only thing you need is the live production system and a way to toggle the flag at runtime.

    If you can ship your hypothesis along with an effectively unaltered version of prod, the ability to test things without breaking other things becomes much more feasible. I've never been in a real business scenario where I wasn't able to negotiate a brief experimental window during live business hours for at least one client.

  • charles_f 4 hours ago
    Write tests. Most likely those 300k lines of code contain a TESST folder with 4 unit tests written by an intern who retired to become a bonsai farmer in the 1990s, and none of them pass anymore. Things become much less stressful if you have something basic telling you you're still good.
    • layer8 2 hours ago
      The problem with complex legacy codebases is that you don’t know about the myriads of edge cases the existing code is covering, and that will only be discovered in production on customer premises wreaking havoc two months after you shipped the seemingly regression-free refactor.
      • ljm 16 minutes ago
        It helps if tests are well written such that they help you with refactoring, rather than just being the implementation (or a tightly coupled equivalent) but with assertions in it.

        Rare to see though. I don't think being able to write code automatically means you can write decent tests. Skill needs to be developed.

      • mehagar 1 hour ago
        I agree. This is one area I'm hoping that AI tools can help with. Given a complex codebase that no one understands, the ability to have an agent review the code change is at least better than nothing at all.
      • UltraSane 1 hour ago
        If you save a log of input on the production system you can feed it to old and new versions to find any changed in behavior.
    • ipsento606 7 minutes ago
      I've been working on react and react native applications professionally for over ten years, and I have never worked on a project with any kind of meaningful test coverage
    • karmakurtisaani 2 hours ago
      The best time to write tests was 20 years ago. The second best is now, provided you've applied to all the companies with better culture.
  • Illniyar 2 hours ago
    This is a good method if you are stuck and you don't know what you need to do. It also helps explore a project with a specific task in mind.

    It is not very useful in giving you confidence your changes would not cause unexpected side effects, which is usually the main problem working with legacy code.

    If you want confidence when working with legacy code, your best bet is to do a strangler fig pattern - find a boundaries for the module you want to work on, rewrite the module (or clone and make your changes), run both at the same time in shadow mode, monitor and verify your new module is working the same as the old one, then switch and eventually delete the old module.

    • LoganDark 2 hours ago
      Boundaries? Module? I laugh.
      • hamandcheese 2 hours ago
        Replace "module" with "system" - every system has boundaries.
        • thfuran 1 hour ago
          Some of them are notoriously spaghetti-shaped, and that’s hard to isolate and replace.
      • nailer 2 hours ago
        Then your first step is found! Make those boundaries. Isolate dcomponents so you can test them.
  • w10-1 7 minutes ago
    Ah, no: incremental approaches only work in already well-formed code.

    Poor code requires not coding but analysis and decisions, partitioning code and clients. So:

    1. Stop writing code

    2. Buy or write tools to analyze the code (modularity) and use-case (clients)

    3. Make 3+ rough plans:

    (a) leave it alone and manage quality;

    (b) identify severable parts to fix and how (same clients);

    (3) incrementally migrate (important) clients to something new

    The key lesson is that incremental improvements are sinking money (and worse, time) into something that might need to go, without any real context for whether it's worth it.

  • jeremyscanvic 1 hour ago
    Is it possible in practice to control the side effects of making changes in a huge legacy code base?

    Maybe the software crashes when you write 42 in some field and you're able to tell it's due to a missing division-by-zero check deep down in the code base. Your gut tells you you should add the check but who knows if something relies on this bug somehow, plus you've never heard of anyone having issues with values other than 42.

    At this point you decide to hard code the behavior you want for the value 42 specifically. It's nasty and it only makes the code base more complex, but at least you're not breaking anything.

    Anyone has experience of this mindset of embracing the mess?

    • 0xbadcafebee 47 minutes ago
      I believe this is called Microsoft Driven Development

      (seriously though, this book has answers for you: Working Effectively with Legacy Code, by Michael Feathers)

  • yomismoaqui 3 hours ago
    I recommend reading a classic, "Working Effectively With Legacy Code" from Michael Feathers.
  • brutuscat 1 hour ago
    For me now days is like this: - try to locate the relevant files - now build a prompt, explain the use case or the refactor purpose. Explain the relevant files and mention them and describe the interaction and how you understand that work together. Also explain how you think it needs to be refactored. Give the model the instruction to analyze the code and propose different solution for a complete refactor. Tell it to not implement it, just plan.

    Then you’ll get several paths of action.

    Chose one and tell the model to write into a file you’ll keep around while the implantation is on going so you won’t pollute the context and can start over each chunk of work in a clean prompt. Name the file refactor-<name >-plan.md tell it to write the plan step by step and dump a todo list having into account dependencies for tracking progress.

    Review the plans, make fixes if needed. You need to have some sort of table reassembling a todo so it can track and make progress along.

    Open a new prompt tell it analyze the plan file, to go to the todo list section and proceed with the next task. Verify it done, and update the plan.

    Repeat until done.

  • mittermayr 3 hours ago
    While great in theory, I think it almost always fails on "non-existent" testing structures that reliably cover the areas you're modifying. I change something, and if there's no immediate build or compile error, this (depending on the system) usually does not mean you're safe. A lot of issues happen on the interfaces (data in/out of the system) and certain advanced states and context. I wouldn't know how Mikado helps here.

    In other words, I'd reword this to using the Mikado method to understand large codebases, or get a first glimpse of how things are connected and wired up. But to say it allows for _safe_ changes is stretching it a bit much.

    • SoftTalker 3 hours ago
      Yes, most of the time such spaghetti code projects don't have any tests either. You may have to take the time to develop them, working at a high level first and then developing more specific tests. Hopefully you can use some coverage tools to determine how much of the code you are exercising. Again this isn't always feasible. Once you have a decent set of tests that pass on the original code base, you can start making changes.

      Working with old code is tough, no real magic to work around that.

    • agge 3 hours ago
      If you create a graph of what changes are needed to allow for other changes, eventually leading to your goal.

      Then by definition you have the smallest safest step you can take. It would be the leaf nodes on your graph?

  • agge 3 hours ago
    Using a Mikado style graph for planning any large work in general has been really useful to me. Used it a lot at both Telia back in 2019 and Mentimeter at 2022.

    It gives a great way to visualise the work needed to achieve a goal, without ever mentioning time.

  • dirkc 1 hour ago
    The things that always get me with tasks like this is that there are *always* clear, existing errors in the legacy code. And you know if you fix those, all hell will break loose!
  • eblume 4 hours ago
    I’ve been using a form of the Mikado Method based on a specific ordering of git commits (by message prefix) along with some pre commit hook scripts, governed by a document: https://docs.eblu.me/how-to/agent-change-process

    I have this configured to feed in to an agent for large changes. It’s been working pretty well, still not perfect though… the tricky part is that it is very tempting (and maybe even sometimes correct) to not fully reset between mikado “iterations”, but then you wind up with a messy state transfer. The advantage so far has been that it’s easy to make progress while ditching a session context “poisoned” by some failure.

  • Mikhail_K 2 hours ago
    I usually use the method "shout Banzai! and charge straight like a kamikaze"

    Is that the Mikado method?

  • agge 3 hours ago
    There is a great interview that talks about the process and what it is about more generally: https://youtu.be/HbjWOvxJjms?si=5ta-JOyfFLub2yX_

    I think there are similar methods, such as nested todo-lists. But DAGs are exceptionally good for this use case of visualising work (Mikado graphs are DAGs).

  • theo1996 4 hours ago
    1. take a well known method for problem solving basically any programmer/human knows 2. slap a cool word from the land of the rising sun 3.??? 4. profit! This article is painfully pretentious and stealth marketing for a book
    • agge 3 hours ago
      Stealth marketing by someone completely unrelated to the book, 11 years after the book is released. Seems unlikely.
  • hidelooktropic 4 hours ago
    So you do things one step at a time and timebox as you go? This method probably doesn't need its own name. In fact I think that's just what timeboxing is.
    • bee_rider 2 hours ago
      FWIW Mikado seems to be the name of that game where you pick up one stick at a time from a pile, while trying to not disturb the pile. (I forget the exact rules). So it isn’t as if somebody is trying to name this method after themselves or something, it is just an attempt at an evocative made up term. Timeboxing is also, right? I mean, timeboxing is not recognized by my spell checker (I’d agree that it is more intuitive though).
      • bregma 1 hour ago
        Mikado is the name of an opera (by Gilbert and Sullivan) in which someone is deemed to have been executed without actually having been executed. Sounds like an ideal test strategy to me: yes, all the tests were executed, just not actually run.
        • zem 18 minutes ago
          when I saw the title I was expecting a reference to the opera. was wondering if they were somehow going to work in the exchange "Besides, I don't see how a man can cut off his own head." "A man might try." in reference to gradually removing bits of the old code.
      • kaffekaka 1 hour ago
        Plockepinn in Swedish, approximately "pickastick".

        Edit: thought I read it was of Scandinavian origin, hence my comment. But Wikipedia said european origin. Well well.

    • topaz0 1 hour ago
      There are important additions beyond timeboxing, at least according to the post. Notably, reverting your changes if you weren't able to complete the chosen task in the time box and starting over on a chosen subset of that task. I can imagine that part has benefits, though I haven't tried it myself.
  • dvh 4 hours ago
    Inherited? I wrote the thing! Customer have no money for large refactoring.
    • agge 3 hours ago
      So we make it many small commitable refactorings instead :)
  • janpot 4 hours ago
    In 2026, we call this "plan mode"
    • eblume 4 hours ago
      It goes a lot further than plan mode though, in fact I would say the key difference of mikado refactors from waterfall refactors is that you don’t do all the planning up front with mikado. If anything you try to do as little planning as possible.
  • koakuma-chan 4 hours ago
    > The project doesn’t compile anymore.

    Using a programming language that has a compiler, lucky.