4 ms·
I don't think I'd use this in production. Testing/development--sure. A class added a method with a require or dynamic definition and that was cause to crash a
by ericb 2y ago
I don't think I'd use this in production. Testing/development--sure.
A class added a method with a require or dynamic definition and that was cause to crash a production activity of some kind? You'd discover the attempted modification via a new FrozenError being raised unexpectedly and crashing what you were doing.
Ruby is made to let you extend core classes--Rails does it all over the place. If I put a require behind a feature flag, this is probably going to surprise me when it fails. It might also make junior devs think gems "don't work" or are buggy if you use it in development, when they work fine? How well does this play with dynamic class loading in dev work in Rails? I would think it would be problematic as you can't draw a line in the sand about when everything is loaded, so it is a safe time to "freeze."
- jaynetics 2y agoIts a safety thing, and it's probably difficult to use it effectively with rails. E.g. in a project with lots of dependencies, things can break if two libs patch the same class after an update. A worse scenario: malicious code could be smuggled into core classes by any library that is compromised, e.g. to exfiltrate information at runtime. This would grant access even to information that is so sensitive that the system does not store it.
- LegionMammal978 2y agoExcept for carefully sandboxed languages, malicious code can generally exfiltrate process memory regardless of what the language constructs are. In the case of Ruby code, this could be with Fiddle or with more esoteric means like /proc/self/mem. At worst, patching classes can make it a bit easier.
- rubyfan 2y agoJeremy Evans is not in the wrong part of town.
- Rapzid 2y agoIt's like a professional wandered into amateur hour.
- ericb 2y agoThat's fair, and I removed that comment for seeming snarky or directed at the author--it wasn't. My meaning was, like strong typing, it is an idea from a different context that works well there, but may not translate well to the Ruby world given expectations and usage patterns.
- vidarh 2y agoEfforts to freeze more and more objects and classes after initial setup have been a long-standing trend in the Ruby world.
- kyledrake 2y agoJeremy Evans is definitely not in the wrong part of town. I use his Sequel gem in production and it is perhaps the best piece of software ever written for ruby. Studying how it is implemented is a textbook example of how to develop complex ruby DSLs really well without getting too deep in the metaprogramming muck.
- echelon 2y ago> Ruby is made to let you extend core classes This is not the way to build long-lived software that outlives your team. This is how you create upgrade and migration headaches and make it difficult for new people to join and be productive. Chasing down obscure behaviors and actions at a distance is not fun. Being blocked from upgrades is not fun. Having to patch a thousand failing tests is not fun. I have serious battle scars from these bad practices.
- ericb 2y agoI like to hear these stories--feel free to share. I guess, usually, I feel like the battle scars are from Rails users, though, which is made up of hundreds of core extensions which make it nicer to use, so reducing the practice is a good recommendation, but removing the practice seems like a nonstarter?
- samtheprogram 2y agoThere’s some nuance here. Application and nearly all library code should not do this. (There can be exceptions for libraries, but they should be used sparingly.) A framework like Rails? A reasonable place to do this sort of stuff, because a framework implies your entire application depends on the framework, and the framework is well managed (otherwise you wouldn’t be using it). Like you said: “you” shouldn’t do this. I feel like your pain from this comes from someone being too clever, outside of a framework, hijacking core methods and classes.
- magic_smoke_ee 2y agoExactly. Dynamic languages that allow self-modification create tech debt and bugs implicitly, which is why I prefer statically-compiled languages that have stable ABI/API guarantees. When there are too many "freedoms", there are no promises and zero stability. Static compilation (because all of code paths must be exercised and translated to machine code) or at least gradual-typing of dynamic languages are essential. rbs and sorbet are non-starters, mostly because it's fragmented, optional, not widely-deployed, and lots of extra work. Python demonstrated wiser leadership in this specific area by modifying the language.
- Andys 2y agoLesson learned for me though, if you "put a require behind a feature flag", you'll get surprise failures when your staging and test environments are no longer able to properly test what might happen in production. Put the require outside the flag and make the flag wrap the smallest possible part of the feature.