Hacker News new | ask | show | jobs
by jbreiding 2496 days ago
Sorry, I've heard this statement a few times, code generation in dynamic languages is an anti pattern. Do you happen to have any more reading on this?

Sure the generated code is usually not readable which is against the zen of python. But writing code to generate code, especially if it's contract driven, is the correct approach no matter the language.

So really what I'm looking for is more substance of why generating code is an anti pattern in python but not in C.

2 comments

My personal feeling is that it just doesn't fit into the workflow. With C you always have a compilation step and thus a build process, so a code generation step fits quite naturally into your makefile (or other build script).

With Python there's normally no build step – you just run the program. Adding code generation means adding another step, which you might forget to run, leading to confusion. If you make the build step mandatory you lose some of the upside of dynamic languages.

I've always solved this with unit/functional tests. The test runner effectively acts as a compiler, for the purposes of checking the contact. in this process.

This is something that's baked into a gate check on merge to the source repo. Or rather it should be.

You can generate Python classes on the fly during the initial import stage - because Python does it anyway itself, that’s why it’s an anti-pattern.
So code generation isn't an anti pattern, persisting the artifacts generated is? To me that is still code generation, one is more durable and able to be tested, the other is a runtime exception.

I've not seen any long lived python projects that don't end up implementing runtime checks to validate the shape of these generated objects.

No, it is still an anti pattern.

Autogenerated code falls into two categories:

1. Code templates, which prepare some stubs but you need to complete it manually. This is what openapi-generator does, and this is anti-pattern because very rarely this approach can't be avoided in favour of simply using code constructs like inheritance or composition.

2. Intermediary code, which is not to be updated manually and is fed directly into interpreter or compiler. In compiled languages it is fine, as this intermediary code is not executed directly; what matters is whether it compiles. In interpreted languages, however, that code gets executed directly, and it can be really difficult to debug (as there is an additional level of abstraction, introduced by the macro). But ultimately there is no need for this type of code, as most interpreted languages (Python and JavaScript definitely) allow dynamic construction of various programming constructs (like classes and functions) on the fly.

>> So code generation isn't an anti pattern, persisting the artifacts generated is?

Yes. If you look at the most popular code-gen for Python, which is protobuf - it does the generation very badly.

That generated code is not only unreadable by humans - it’s not readable by IDEs. Protobuf author later on made a point that was a mistake.

And that’s from one of the most popular projects.