6 ms·
I don't think most people would describe almost anything you wrote as clever. I hope that's not insulting... Metaprogramming tho... You want to make a magic bl
by cookieperson 3y ago
I don't think most people would describe almost anything you wrote as clever. I hope that's not insulting...
Metaprogramming tho... You want to make a magic black box that takes hours to debug and conceals real bugs, invest heavily in metaprogramming to save a hundred lines of code that can be maintained with three find and replaces/SED calls and a recompile a year... Most metaprogramming shouldn't exist in production code.
Programming is social. You have to weigh your decisions heavily by who you work with now and who you might work with in the future. If you work in a niche language or toolset you might think "this is my chance to do whatever I want!" But the reality is, it should be the complete opposite.
Most compilers make clever code silly. You can write a 15 line hard to read pipe or method chain, or a 25 line double for loop with the same runtime characteristics. The latter is always better to maintain, while the former is always more clever. One is good for the team the other for someone's self esteem.
- nisegami 3y ago>I don't think most people would describe almost anything you wrote as clever. I hope that's not insulting... I desperately wish I could say this, but I have seen it happen
- cookieperson 3y agoSorry to hear that. I'd pitch to invest in the teams education a bit. A little time spent establishing some ground rules goes a long way. If it's your boss biting down on you for it, don't waste your time, seek a new environment if it bothers you or stunts your growth. Most code review cultures degrade into absurd rules over time because of human power structures and crappy feedback loops. I'd imagine if some of those things became rules either there's an obscure reason for it, or the environment has rotten out. I've seen both cases for some of these types of things. The rotten culture being the most common
- josephg 3y ago> Most compilers make clever code silly. You can write a 15 line hard to read pipe or method chain, or a 25 line double for loop with the same runtime characteristics. The latter is always better to maintain, while the former is always more clever. Weirdly, in rust there's lots of cases where the compiler will generate better assembly if you give it map/filter/fold than it will if you give it a for loop. The reasons are weird - like, its easier for the compiler to know it doesn't need bounds checks for list.iter(), and to work around some integer overflow errors while iterating through ranges and things like that. The difference usually doesn't matter in practice, but I still find myself thinking about it in performance critical sections.
- cookieperson 3y agoIgnoring rust or any language specific thoughts... Sure, but there are many cases where it's still better to have slightly slower code at the expense of readability/extendability/maintenance. Even in HPC applications. I know I know some very smart people are about to throw their sharpened axe at me. But in my experience very rarely does someone truly need to sacrifice a bounds check to deliver their product or save meaningful amounts of $ in prod. Not saying all loops must be bound checked, that's a dumb hill to die on. But I've seen devs hyperfocus on hypothetical minimal gains that get blown away two days after the code lands, or a minor requirement changes. The challenge with DO NOT TOUCH this code comments that intense performance tuning leads too(figuratively and literally) is it makes people who don't understand the code build bizarre(and often slow) monuments all around it that don't usually need to exist and deter from the minor gains won over a cute optimization. I've seen this happen ALOT. Of course there are times where you should opinionate your code to better serve the machine. But my big thing is, it's rarer then the overly complex design decisions favoring it are and compilers are getting better every day.
- atoav 3y ago> Most metaprogramming shouldn't exist in production code. Go ahead and try. Many of the libraries you will use use metaprogramming of one flavour or another for ergonomic reasons. Python decorators are metaprogramming. For example putting @cached above a function declaration esentially wraps your function into another that caches it's values without you ever having to see all of these details. I am not sure if your production code would really gain from writing out that caching logic over and over again for each of your functions that need caching. I am sure however that it would become less readable and harder to reason about. In Rust #[derive(Serialize, Deserialize)] can be used to automagically give your data-types serialization and deserialization. This is also metaprogramming. It also reduces the code you have to read and write and the mistakes you will make if you roll this on your own. It also makes your code easier to read to all people who understand what it does (so nearly everyone who programs Rust). Metaprogramming is okay, if it is done in the right places for the right reasons and doesn't obscure the logic of the program. I often use it for custom decorators in flask e.g. @admin_user or @authenticated_user to quickly wrap the functions for some http routes with the ever-same logic for authentification. Sure you could also do this with a function, but the ergonomics could be worse and you could accidentally place the function call in the wrong place and thus exposing some parts of a route to unauthenticated users. I don't think this makes it harder to reason about my code. Like all "don't do X" idioms in programming the one about metaprogramming should be taken with a grain of salt. There are cases where metaprogramming is the best (most reliable, futureproof, usable, etc) way of solving a given problem. The warning is true in that you should avoid using it everywhere without reason. But there are places where it makes sense and there it would be a waste not to use it
- cookieperson 3y agoIt's a good thing I didn't say "don't do X"
- antonvs 3y ago> You can write a 15 line hard to read pipe or method chain, or a 25 line double for loop with the same runtime characteristics. The latter is always better to maintain, while the former is always more clever. You’ve just told us which one you’re more familiar with, that’s all, which is exactly what the other commenter was pointing out. This one also belongs on the list in that comment. Beyond familiarity and subjective preference, there are benefits to the pipe approach that come from its functional nature. Determining that a for loop is a pure pipeline can be tricky in general, which contradicts your idea about which one is harder to read. And the ability to get reliable parallelism for free - e.g. Java’s parallelStream - is not a feature of for loops.
- 908B64B197 3y ago> And the ability to get reliable parallelism for free - e.g. Java’s parallelStream - is not a feature of for loops. This is the big one. For large datasets or computationally intensive processing the speed difference will be noticeable. One of the issues with "cleverness" is also that code that's trivial for John Carmack to understand might not be for $BODY_SHOP_RESSOURCE_200353. I recall a self taught dev (or maybe from a bootcamp) coming up with a cascade of nested if-else, nested 8 deep. Someone with a background in CS asked him what he was trying to do and basically concluded that what he was trying to do could be expressed as a state machine. To which the initial dev replied that it was "way too fancy" and that he didn't need the code to be fancy, just work.
- cookieperson 3y agoI think if you took a survey about which code is easier to read a pile of expressions acting as closures inside of nested method calls or a loop, you would likely find most programmers have comfort with one over another. That's objective because it's how pseudocode, the most widely used language agnostic abstraction used in computer science beyond plain text, is written. But that's really not the point and it never was, right? You can grill me if you want and say I am the problem! Zing ouch got me so good! Those HN points will get racked up, so much winning... Or you can read between the lines. I drew an unspecific example with microseconds of thought behind it. People who know what I am saying know what I conveyed is fine. People who know me, know I regularly use pipes and chained method calls all day. The point is, the paradigm could go either way, it depends on culture(reading the room), and design decisions. Had I of flipped my example and said "method calls can make code way cleaner than for loops" which in some contexts is equally valid your antiparticle HN contributor would make the same argument you made calling me the problem. Get it? I would say people trying to shit on everyone around them for being casual are more of a problem then anything else. Especially in collaborative development environments. That supercedes any code anyone could contribute. But that's my take and I'm not going to suggest it belongs on some arbitrary list of ad hoc HN rules (of which none hold water)... I won't be writing a five pager with examples where what I said was sound valid and best praxis, I have nothing to prove, and that was never the point. Everyone who knows what I'm talking about gets it. Happy flag planting with imaginary enemies.
- 2devnull 3y agoMetaprogramming can do the opposite: make obscure, complicated and lengthy code much more readable and easier to maintain. It’s clear when it does this. Agree that “clever code” is silly but also important to remember that people need to entertain themselves and “grow professionally.” People get paid more if they write the 15 line pipe and it’s job security. Maybe gpt will help since it’s a lot better to have gpt write easy to debug for loops, but then programming will be less fun. People need to entertain themselves.
- cookieperson 3y agoI hear you, that's why I said "most". But there's also a flipside where someone tries to tweak a language feature or implement a missing language feature with an inhouse macro. That macro goes on to be defunct but a major chunk of mission critical code is now glued too it. After all we can't expect languages to not fill in missing gaps in an opinionated way. The only way out is to wall off a code base for a month for a treacherous refactor. I am pro have fun screw up and grow. But macros present a certain kind of danger a lot of other tools don't. If you are playing with them be careful of their scope is my only real warning.