Now would be the ideal time for everybody to give it negative feedback when bad code is returned but I'm afraid not enough people care and we'll just settle with what works just like we always have.
The design machines aren't good enough yet; and their progress has little relationship to LLMs at all. Designing computer programs and the proper level of abstraction for the easiest maintenance, flexibility and debugging is simply an open problem. There's nothing to train LLMs on that is smaller than the size of an entire program, and its history of code changes.
Get a few of those, figure out a way to analyze and reduce the patterns and lessons in them, and train on that maybe. Until then, there's no way for an LLM to figure out what lacking a particular abstraction is going to end up costing.
You can choose to ignore the fine details and just tell it what to build, or you can spend more time and effort and tell it how to do things, you can ask it to create a plan, review the plan and ask for changes etc, you can review the implementation and ask for changes there. You can simply tell it you don't like how a feature is implemented and ask it for suggestions on how to improve it, include what you don't like about it so it has direction.
It's all about the effort you put in. LLMs are able to write clean beautiful and efficient code, they just can't necessarily do exactly what you want on the first try without any direction. That's why you should figure out what you want, ask for what you want and make sure it's actually building what you want.