One thing I notice with LLM-generated code is that they are paranoid. And that affects code quality. For me, I will do things the naive way, and only when I encounter errors during testing will I add safety nets for edge cases. But LLMs tend to want to catch all possible things that might go wrong from the get-go, even when we know that an error is not possible, or when we actually want the error to propagate and crash the program.
Maybe itβs because of how they are trained on coding benchmarks. They are optimised to not make the program crash no matter what. When we humans code, we want the program to crash so that we become aware of a problem fix it, not necessarily by adding error-catching logic but maybe by enforcing some kind of invariant into the system.
Another example of paranoia is how LLMs tend towards defensive code. For me, if I know that there is only one place that a function is being called, I will not add any checks on the arguments inside the function or try to coerce types - there is simply no need! On the other hand, LLMs default to trying to handle as many variations of malformed function arguments as possible, doing null checks, converting types, etc. It assumes that this function will eventually be called from 10 other places with messy arguments.
What is the common theme here? LLMs try to solve imaginary problems. In doing so, they silently swallow program behavior. I want exceptions to raise, so that I can prevent that exception from ever throwing in the first place. I do not want to catch it. I want malformed function arguments to cause a crash, so that I can reconsider the function scope and how it is being called in different places. I do not want to let the show run on with type coercions that I have never allowed.