8 ms·
A couple of related practices I've picked up over the years: (1) using long names when implementing things that are necessary but discouraged (2) putting dange_
by KMag 4y ago
A couple of related practices I've picked up over the years: (1) using long names when implementing things that are necessary but discouraged (2) putting dange_danger in names of things that should never be used in production.
The former introduces just a tiny bit of friction, but it's often enough to encourage developers to use the preferred API calls.
The latter I learned almost 20 years ago from Google's "Mustang" search back-end. If running a test instance of Mustang without bringing up a ton of dependency processes, there was a --danger_danger_must_not_fail true commandline flag (or something very similar) to turn a bunch start-up sanity check aborts into warning log messages. If any code reviewer sees "danger_danger" being added to production command line flags, they'll almost certainly ask the right questions.
- AnotherGoodName 4y agoif_you_use_this_you_will_be_fired is my favourite suffix seen in production.
- asddubs 4y agoin react, I assume https://github.com/facebook/react/blob/80bff5397bf854750dbe7c286f61654ea58938c5/src/umd/ReactUMDEntry.js https://github.com/facebook/react/blob/80bff5397bf854750dbe7...
- CGamesPlay 4y agoIt's used in many of Facebook/Meta's internal code bases, in fact.
- fotios 4y agoAnd it has been for a long, long time https://twitter.com/thefotios/status/689130197891829760 https://twitter.com/thefotios/status/689130197891829760
- bradrn 4y agoThe Haskell ecosystem uses a very similar convention: unsafe functions have names starting with ‘unsafe’ (or, in one particularly horrible case, ‘accursedUnutterable’ [0]). These are generally functions which subvert the type system, so the name acts as an alternate warning. [0] Documented at https://hackage.haskell.org/package/bytestring-0.11.4.0/docs/Data-ByteString-Internal.html#v:accursedUnutterablePerformIO https://hackage.haskell.org/package/bytestring-0.11.4.0/docs... — incidentally one of the funniest pieces of documentation I’ve ever seen!
- jiggawatts 4y agoRust and C# both use 'unsafe { }' blocks, which can only be enabled by a module-level compiler flag.
- tialaramex 4y agoThere is no such "compiler flag" in Rust, that's only a C# thing. But also more relevantly here, stuff you'd be calling in those Rust blocks tends to have longer names and often calls out the fact it's specifically not checked, e.g. a = b.unchecked_add(c); // Like a C or C++ arithmetic operation if you overflow it's UB. This might be faster. It might not. But if you must have this anyway, that's how n = NonZeroU32::new_unchecked(0); // Unlike new() which returns None because duh, zero isn't non-zero, this results in UB. Not all of them though, for example: v = Vec::from_raw_parts(ptr, len, cap); // Make a Vec, the pointer ptr had better actually be pointing at contiguous memory for exactly cap item-sized slots, the first len of which are in fact legitimately values of the appropriate type, if any of this is wrong that's immediately UB.
- CamJN 4y agoWhile sadly it does not require a flag to enable, at least you can turn it off with: `#![forbid(unsafe_code)]`.
- rezaprima 4y agoAnother correct way to use Hungarian Notation, according to (iirc) Joel Spolsky
- calvinmorrison 4y agoAt my old job we had some unsafe-ish operations, mostly you needed to do --force or --really. Typically you would invoke without it, then it would say "heres what I am gonna do, do this again with --really and I will do it for sure" There was one tool that had '--yolo', because if you're at that point of an operational crises - you might as well give it a shot.
- mbo 4y agoWas this old job Canva by any chance?
- tialaramex 4y agoI too have written force features. You've likely never seen this, but in tool design, prefer git push's --force-with-lease design. Force With Lease says "I believe X is true, and because of that, force". The tool can check that X is indeed true, and if so force, but if it's not true the human was wrong and they ought to re-consider and obtain a new "lease" before we make the change. In Git this "lease" is the current ref of a remote, if we specify this, but actually it's wrong, that means the state of the remote system has changed, and we need to re-consider whether our forced change is still appropriate. e.g. While you and Bill were quickly changing colors.js to hackily disable dark mode, turns out Sarah guessed the actual bug, and replaced main.css with a patched version that works fine even in dark mode, if you force-push your change, instead of zapping the broken change it zaps Sarah's fix! This approach works best where you can actually take some sort of "lock" and avoid clashes at the tool level, but there's some benefit even without that at the human level.
- plorkyeran 4y ago--force-with-lease is great, but I really wish it was --force and the current force was --force-without-checking-if-its-safe or something. The more dangerous one being the shorter one is unfortunate, and I think it's worth the breaking change to swap them (with some sort of config option to gradually do the switch).
- IgorPartola 4y ago
- suzzer99 4y agoThis is the flag required by our script to create and merge pull requests from one environment to another: MERGE_APP_REPOS_YES_I_ALREADY_MERGED_LIB_REPOS_AND_WAITED_FOR_THEM_TO_FINISH_BUILDING
- craigmcnamara 4y agoThis seems like a broken process to me.
- lamontcg 4y agoSeems like that is intended to never be used by humans and is used by a process that has always done the other thing first (unless you're manually debugging the process itself in which case you'll copypasta the silly long thing).
- suzzer99 4y agoIt's a script run by a human when they want to push the changes in one environment to another. Our various apps consist of 3-10 repos. All the apps are backed by two shared lib repos (one for node lambdas, and one for C# lambdas). Merging each repo manually to do an environment push is cumbersome. The script creates and merges pull requests on github for the lib repos and app repos - from one environment (branch) to another. First you have to do the lib repos, and if there are any changes wait for the CICD jobs to finish. If there are no changes to the libs, the script indicates that no pull requests were needed. I have no idea how to get a local bash script to poll for when AWS CICD jobs are done, nor do I really want to spend days on that. So I just added that parameter to make sure I (and anyone following me) runs the lib merges first and waits for them to finish building before merging the app repos. The job without any flag just merges the lib repos.
- notpushkin 4y agoWhy not create a draft PR on the app repos and tell user to merge it when lib builds are done?
- deleted 4y ago[deleted]
- lamontcg 4y agomy contribution: public_method_that_only_deep_merge_should_use https://github.com/chef/chef/blob/68dd5f42273f19bc5975c0dc8ed46ee592764eec/lib/chef/node/immutable_collections.rb#L158 https://github.com/chef/chef/blob/68dd5f42273f19bc5975c0dc8e... that was 9 years ago and it was code smell that things were broken apart incorrectly and at some point i rewrote it so that wasn't necessary -- but sometimes you just gotta move the ball down the field, even if you don't get a first down.
- GuB-42 4y agoFor 1, I have seen somewhere that it a reason why C++ casts are so verbose compared to C casts: like "reinterpret_cast<A>(b)" vs "(A)b". Type casting in C++ may be the result of bad design. And while casts definitely have a place, they are ugly, and therefore, they should look ugly.
- xigoi 4y agoBut C++ still lets you use C-style casts, which kind of defeats the point.
- munch117 4y agoNot so much, you could phase out C-style casts over time. C++ compilers could grow options to warn about C-style casts (if they haven't already), shops could outlaw them in coding style guides, and slowly it would go away. What does kinda defeat the point is that C++ adds a new form of cast that is even less conspicuous than a C-style cast: typedef int* int_p; int f(char* p) { int* ip = int_p(p); // basically a reinterpret_cast return *ip; } int main(int argc, char** argv) { return f(argv[0]); } gcc -Wall compiles this with no warnings.
- scatters 4y agoUgh, I really need to clean up and submit my patch that adds those warnings. Hopefully I'll have some time this year.
- planede 4y agoYou can blanket ban C-style casts with appropriate warnings and static analysis.
- chrismorgan 4y agoMy own example from a decade ago: https://sourceforge.net/p/portableapps/launcher/ci/default/tree/Other/Source/Segments/PathChecks.nsh#l21 https://sourceforge.net/p/portableapps/launcher/ci/default/t...: you can’t run PortableApps.com apps from the Program Files directory for a few reasons, but for some reason we decided to allow overriding the guard anyway, but in a clear and verbose way: you have to set an environment variable named IPromiseNotToComplainWhenPortableAppsDontWorkRightInProgramFiles to “I understand that this may not work and that I can not ask for help with any of my apps when operating in this fashion.” (case-sensitive).
- zensavona 4y agoYep - we do the same thing: functions which don't (for example) check if a given user should be able to do the given thing use then naming pattern dangerously_verb()
- layer8 4y agoFor languages that support Unicode identifiers, you could zalgo-ify the name to increase the friction: | | d̜̣͎̱̟̥͓̥͍̙͖̫̓̀͗̌̚a͍̩̫̳͖̒̒́́͐̍́̍̏͋̿̈n̳̯̫̥̞͗̒̆͗̀͒͒͌̒̎g͉̝̠̝̠͉̰̘͉̩͖͙̾͐̽̂̈́͗ë̗̙̳̮̘̟͙͇̣͇́̐͑̈́͂̾́̇̇̀͒ŕ̗̱̜͚̌̔̓̄̄͒́̄͌̚_̱̭͍̣̳̝͓͔͖͓̀̃͒̑̊͛͛̽̑͋̿͒ͅd͉̰̖͎̰̙̘̰͈̫̃̍́̋̆̀̓͆̈́̓̇̾a̭̦̲̫͕̩͔͙͔͖̱̿̑͌̊͌̾̊͂́͂̉ň͖͔̩͓̮̦̭̜̩͉́̀̍́̑g̖̦͙̝̈͆͗̈̄́̉̽͗̄͆́ȅ̠͔͕̜͔̇͗̊̈́r͎̬̦͈͈͐͑̃̄̀͒̉̓̋_̪̝͔͖̠̘̰͛̂́̔̆́̓̅͒t̖̘̟̝͚̭̦̪͕̘͐̎̋̈̍̋̾̈́̇̈́̉̚ḣ̙͇̝̳͓͇̮̫͙͈͍͊̇͌e̳̖̯̥̭̜͓̜̒̉̎̒_̥̱̲̘̞͓̖̣̝̮̮̌͌̅̀͊̅̍̑̿̂̿ͅp̗͖̘̝͈͙̫͖͍̠͑̎̃̍͌̇͋̍͋͗͑͛o͉̬̗̠̝̗͈̟̘̱̬̫͗̽͆̊́̂̚n͚̪̰͉̪̟̈́͛̓͒͌̎̑́̒̃͌͆ͅy̞̗͖̗̾̂̿̿̀̊͋͐̓̓̚_̜̲͖̣͈̞͖͎͆͑͌̾̃͆ͅh̦̘͇͍͓͕͒̎̒̽͂̊̐̍e͎̰̲̥̱͍̗͉̞͔̦̬̊̌͆́_̲͚̮̮̙͇̠̮͖͐́̎͆̿̄̋c̙̩͈͇̩̯̠͇͙̄̄̒̄̓͑͂͗̈͂̊̚o̪̥̲̗͓̭͍̣̮͙͉͇̽͊̿̔m̫̖̘̰̆̊̒̃̔͛͛̚ẻ͓̭͓̗̙̳͖̭͚̐̀̃́̃s͖͈̬͚̜͊̐͗̓̂͑̀͑̔̿͌͒ | | (Yes this is actually a valid Unicode identifier.) https://en.wikipedia.org/wiki/Zalgo_text https://en.wikipedia.org/wiki/Zalgo_text
- layer8 4y agoNow that I think of it, a more toned-down version could be: d͓ͨa͓ͣn͓ͮg͓ͤe͓ͣr͓ͭ_d͓ͨa͓ͣn͓ͮg͓ͤe͓ͣr͓ͭ_f͓ͨo͓ͣo͓ͮb͓ͤa͓ͣr͓ͭ_o͓ͨp͓ͣt͓ͮi͓ͤo͓ͣn͓ͭ
- runlevel1 4y agoAnd it's a perfectly valid function name in Ruby: https://replit.com/@brandt1/WatchfulTemptingRecursion#main.rb https://replit.com/@brandt1/WatchfulTemptingRecursion#main.r...
- MrGilbert 4y agoAlso works in .NET, although Visual Studio really doesn't like the identifiers.
- deleted 4y ago[deleted]
- 8n4vidtmkvmk 4y agoi wrote "this is dangerous" in a comment the other day and then it failed on me the next day. whoops. i guess i was right
- l0b0 4y agoThis comes with a huge caveat: You must explain it in enough detail for anyone encountering it to understand why it's dangerous and what they should be doing instead, if at all possible. The documentation must at the very least be where the name is defined. "But why?!" is exactly the wrong thing for a developer in a hurry to be thinking.
- tpoacher 4y agoI have a similar insight regarding long names. If you strive to make your function names as self-documenting as possible, you then end up with the following situation: either 1) Long-named functions become a signal that code structure is suboptimal and can be refactored to split functionality / responsibilities appropriately, until the function has a reasonable name, or 2) You are working with code that cannot be refactored, in which case the long, cumbersome, but otherwise highly informative name is doing you a favour, as well as possibly forcing you to wrap meaningful interfaces around it to make you less reliant on calling that monstrosity directly as much as possible. So yes, I always try to make my function names contain as much relevant information as possible.