# Why you should fear your automatic refactoring tool

Okay the title is clickbait. I actually encourage people to not let themselves succumb to fear-driven development. Fear is the mind-killer, stop fearing!

No really. All too often I come across people or comments about being too fearful to change software until they had "some tool" or process. The tool and processes vary, but the fear doesn't. I argue that even with no tool but your brain, you can code fearlessly. This isn't to say that tools don't help, especially when it comes to boosting confidence in correct results. I am saying that the physical sensation of fear that plagues certain programmers is entirely to do with their psyche.

If you're possessed by fear unless you have some particular tool or process, ask yourself, what if I took that tool or process away? And said you can't have it back? What are you going to do? Will you be able to move forward? The art of fearless coding is to change your perspective from an emotional one to a logical one. Instead of being fearful about the effects of some possible change, ask yourself instead how confident you are that this specific change will produce good effects over bad effects. How can you improve your confidence? Maybe you think back to the tools I took away -- what if you don't have those particular tools, how can you improve your confidence?

Suppose I give you the task of renaming a method in Java. Your tools are Java's static type system and whatever IDE. You use the IDE's auto-refactor command. How confident are you that the IDE has done the right thing?

If you say 100%, you're wrong, for two reasons. The first is trivial, in that you can never hold 100% confidence while also being in compliance with a formalized way of changing your confidence based on new evidence (Bayesian updating). The second is that in Java, your static type guarantees aren't enough.

This is because Java supports introspection. I can ask the JVM: do you know about this class that I'm specifying by a string? If so, do you know about this method? Oh, it's private, well can you ignore that and let me call it anyway?

The answer to all of those can be yes. The point is that your IDE's refactor tool is going to miss these. Some tools will miss fewer than others, or can at least flag introspective accesses for you to look at that might end up being false positives, but it's not possible to automatically catch everything.

This isn't a theoretical concern, it happens in real code. Fortunately for myself the last time I did this and was bitten by it was due to inlining a private method, and then later getting a report from our test automation that some old test had started failing. It was calling the private method with introspection...

There are other possible places it can miss too. Namely, if you're renaming an API method, you might have clients (in the browser, or as other Java programs) that you can't see but are expecting that method to be there and it to be named a certain way. The consequence for them could be a compile-time error or a runtime error, depending on how they're invoking the method.

So, don't trust your auto refactor tool with complete certainty. If you were fearful of making such a change like renaming a method without a tool, and the tool took that fear away, maybe you should bring that fear back and then reexamine how to stop fearing regardless.

None of this means stop using the auto refactoring tool!

But it's curious to note that Java has static types, and yet it can still fall prey to this issue. What does this mean for dynamically typed languages?

Nothing! The type system is a red herring. Certain types of program analysis can be easier with a static type system, sure, but there are other types of analysis besides static analysis. Dynamic analysis for instance. That type of analysis is easier in a language that supports runtime introspection, like Java, or many dynamically typed languages.

I suspect but haven't investigated that introspection is the key mechanism to make the LSP projects for dynamic languages here function correctly and be able to support all the usual IDE features (jump to def, hover for doc, auto-complete, cross-reference callers, and certain kinds of auto refactoring). A notable exception (and maybe worth addressing) from that project's long list of supported languages seems to be Common Lisp. But this is a minor issue because Lispers have enjoyed all these things for a long time, using a similar client-server model. I like to Lisp in vim, and with one plugin I have access to tab-complete, documentation on demand, jumping to definitions, etc.

I'm missing auto refactoring tools (maybe emacs has them, or commercial lisps) -- but I don't find myself needing them as much. Better designs made possible with more dynamicism alleviate the need for massive refactors where the tools really save a lot of effort (dynamic languages encourage late decisions and late binding so there's less to change for the average refactor) so for the average refactor an auto tool might only save half a minute at most compared to the manual vim/sed incantations. Sometimes vim will be faster. Maybe my confidence in certain things is theoretically lower sometimes, because with vim I'm often relying on my brain and text manipulation vs. a tool relying on static analysis, but I have ways to increase my confidence so I'm never fearful of moving forward.

For example, let's go back to the rename method. A random 46 thousand line CL project I found has a doubly-linked queue structure with some exported generic functions. What if I wanted to rename, say 'remove-from-queue to just 'rm-from-queue? Or maybe it was vice versa. We'll pretend there are no downstream libraries we have to worry about.

Take away all my tools but a bash shell, and I am unphased. find ... | xargs grep... These days I use ag for that. But it lets me find all strings with the name "remove-from-queue", then I can go one-by-one and see if it's the real one or not and update it. This doesn't give me 100% confidence because someone might be creating the symbol from e.g. user input and evaling it, but not even a static typed language would help with that.