Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

So basically I can't commit anything containing the slightest form of metaprogramming? Seems a bit extreme to me. A solution is to go for the more concise and robust metaprogrammed piece of code (the example of the form with the User object is a good one) and add a comment mentioning the methods called in there.

The "smartass" way of programming is sometimes overused but it does have its benefits. When you're metaprogramatically setting the attributes on the User, you're also avoiding needless and error-prone repetition and making sure that this central piece of code will either crash all the time or work all the time for all attributes. This has tremendous value.

So while I understand the point about this article, I might want to add a pinch of salt to the dogma underlying it.



Your example of adding a comment mentioning the methods called in there would indeed pass the Grep Test, and is a reasonable compromise when there is a real call for dynamic declaration.

I think there are definite ways of adding metaprogramming functionality without breaking this test. For instance, in the first JavaScript counterexample, if the iteration was over [{attr: "position", fn: "getPosition"}, {attr: "direction", fn: "getDirection"}] instead, the Grep Test passes, and you get much of the same benefits, with a very minor duplication that I'd argue is worth the cost.


I work in Perl for the most part, and the alternative I've been using lately for functions is to assert that for a given generated sub, the text 'sub routine_name' exists literally in the code somewhere. This takes two forms in my case:

    my %to_generate = (
        'sub first' => { ... },
        'sub second' => { ... }
    );
    generate_from_spec(%to_generate);
generate_from_spec then strips off the 'sub ', and errors out if it is not found.

The second case I have is a function that itself then generates a function, but is trying to look like a sort of normal function itself, in which case I end up with:

    generate_sub routine_name =>
        ... whatever arguments ...
"abusing" Perl's => operator, which functions like a comma except that it forces stringification of the left argument, to once again make the literal, greppable "sub routine_name" appear in the codebase. Here "routine_name" is then just a standard string argument, the alterative being

    generate_sub "routine_name",
which is then harder to grep for. (Still possible, obviously, with a different grep query, but only if you already know up front you need to add the other possibilities.)

Note this actually goes a step beyond what you are proposing in that it makes the declaration site clear; my counterproposal for your JS case would be

    ["function getPosition", "function getDirection"].each(...)
and using string manipulation to do whatever you need to do to get the right info out of the function name.


So update your blog post to say that. I had the same reaction as GP.


Done.


I'm not sure I totally disagree with you, but I have to at least disagree with part of your argument.

> Seems a bit extreme to me.

That reasoning has absolutely zero argumentative value behind it, in any context that it's used. It ought to be treated like a logical fallacy.

> add a comment mentioning the methods called in there.

The problem of comments getting out of sync with code is omnipresent. "Never fail the grep test" seems like a much more easily-enforced and -maintained practice (both for yourself, and for teams) than what you're suggesting.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: