Writing code that writes code – Hack Codegen
code.facebook.com
code.facebook.com
I used at least one PHP to JavaScript code-gen in the past and it was rather bad.
I also dislike this Rails/Ember-CLI scaffolding stuff. It simply feels like too much magic for me.
Good thing nobody forces you to use scaffolding in Rails. Code generation should always be a one shot , to get started on something.
On the other hand the situation in Go land with "go generate" is much much worse, as code generators become dependencies , right in the code with pragmas ...
The worst offender is PHP of course, with frameworks like Symfony or Doctrine (and its famous proxies because yes, Doctrine doesn't actually use the code you write but the one it generates and put in a proxy folder ) that use code compilers and generators for everything from routing to dependency injection to every configuration step . Although PHP frameworks usually do it on the fly so no manual step.
When it works, you forget that the only thing that computers understand is their native instruction set, and everything on top of that is built on some form of codegen. When it doesn't, you curse out the programmer who left you a pile of buggy scripts to maintain.
A solution that does not need lots of boilerplate code would be even better, but codegen is still better than the makeshift code that it originally replaced.
This is totally a 'C' hacker's approach but it's not bad for some things - especially serialization and the like. But it will need some generic reference mechanism - as void * is used in 'C' - to work.
* It was not typed, and with the advent of Hack, we wanted to have types.
* The actual setter method was not defined. If you searched the codebase,
you wouldn't find it. If you looked at the class, you couldn't see which
methods you could call, which made it harder to discover other calls,
such as ifNotNullSetName.
* IDEs can't autocomplete the code.
What this boils down to is metaprogramming. If you want to create an array that contains twenty items, you aren't going to do: array.add(1);
array.add(2);
array.add(3);
...
You'll use a loop, some imperative code. That's because data structures like arrays are within the domain of things you can touch with code.But what about class definitions? What if you want to add twenty methods to a class? Fans of dynamic languages will rightly say that class definitions, functions, etc. should also be in the domain of what your code can affect. Smalltalkers and Rubyists will happily write imperative code to build and modify classes.
This is really powerful. It's exciting stuff.
At the same time, for better or worse, most programmers are not spending their day in a live editing environment. They aren't in a Smalltalk browser all day. They're in an IDE or text editor.
That means the window into the program that we have while editing doesn't see any of the results of that metaprogramming. All of the static analysis tools, auto-completers, go-to-definition-ers, etc. can't handle dynamic metaprogramming because they run before any of that metaprogramming is invoked.
Code generation is a way out of that problem. It lets you do imperative dynamic metaprogramming, but then bakes the result back out to the file system where the rest of your tool ecosystem can see it.
It's not the most elegant solution in the world, but I think it beats trying to reinvent the entire world of tooling that programmers use all day: grep, text editors, IDEs, etc.
Exactly, but only because we don't have a any really good solutions to building tooling that supports meta-programming for typed languages.
> the window into the program that we have while editing doesn't see any of the results of that metaprogramming
I wonder if there's a way to build IDEs that provide support for metaprogramming.
(Also, this was a really excellent comment.)
You can find some crufty Lisp macros from 1983 (code that writes code, par excellence) and they still work today.
There is an interesting presentation by ThoughtWorks – Neil Ford: Building DSLs in Static and Dynamic Languages [1]
However I thought you might find this the EPFL / ETH Summer School on DSL Design and Implementation very useful. They not only come with presentations, but also code in Scala, Racket, Haskell et. al. I am currently working in a huge project with about >30 people working on building an MDD (Model Driven Development) platform for visually/declaratively writing things for the systems we use internally. These will be able to create models out of code and even fix API incompatibilities automatically. [2]
Excuse the Unicode, I got bored
⬬══════━━━━━━──⋯𝅖܅܅܅܅﴿⌁⏧⌁﴾܅܅܅܅𝅖⋯──━━━━━━═══════⬬
[0] https://github.com/facebook/pfff
[1] http://www.intertech.com/resource/usergroup/Neal_Ford-Buildi...
[2] http://vjovanov.github.io/dsldi-summer-school/program.html
I'm having trouble seeing any real-world scenarios for this kind of codegen but since it seems to be in wide use at Facebook, I must just be missing something...
public function getName(): string {
/* BEGIN MANUAL SECTION User::geName */
Wonder how well that works if there's a typo in the section comment?