Post AP7LmgBw4EyVJ606oC by SSumma@social.anthro.cc
(DIR) More posts by SSumma@social.anthro.cc
(DIR) Post #AP6Pzc0r7WTAloHSO8 by RustyCrab@sleepy.cafe
2022-10-30T19:24:49.029141Z
1 likes, 0 repeats
Programmers against OOP: what is your answer to RAII?I'm really and truly not in love with OOP but RAII is something nobody sane should give up.
(DIR) Post #AP6QJo0oDWLfmDt68W by RustyCrab@sleepy.cafe
2022-10-30T19:28:27.145620Z
1 likes, 0 repeats
For those who don't know: RAII is basically constrictors and destructors. Memory management and invariants are more or less impossible to maintain without them. The C solution is factory functions but that's really just a shitty version of constructors
(DIR) Post #AP6TGTDpMCsYI84uES by deprecated_ii@poa.st
2022-10-30T20:01:29.009784Z
1 likes, 0 repeats
@RustyCrab the problem with answering the question is I don't structure my data in an OOPy way to begin withthe whole notion of factories and constructors/destructors assumes an OOP data model
(DIR) Post #AP6W6XoRjaGbUnAHpY by RustyCrab@sleepy.cafe
2022-10-30T20:33:17.749414Z
1 likes, 0 repeats
@deprecated_ii that's kind of my question though. The alternative is manually initializing every time you allocate. Projects at scale simply can't survive that. I think even C has a limited form of RAII with their auto init to 0 structs.
(DIR) Post #AP6WCAmkGLH9oa3M8G by RustyCrab@sleepy.cafe
2022-10-30T20:34:18.851683Z
1 likes, 0 repeats
@deprecated_ii for clarity, what I mean by factories is a standard function that both allocates a struct and sets some variables in it.
(DIR) Post #AP6WKTeO0Raqdn6S6S by RustyCrab@sleepy.cafe
2022-10-30T20:35:48.753159Z
1 likes, 0 repeats
@deprecated_ii generally in the C libraries I've used, structs will have a creation function and instances are never allocated outside of that. That's a de-facto constructor.
(DIR) Post #AP6XJ6tFF80jiPxtdw by Binkle@sleepy.cafe
2022-10-30T20:46:45.093488Z
3 likes, 0 repeats
@RustyCrab depends on the context. My audio engine is "allocate data upfront and then never deallocate" which requires a certain kind of design for a certain kind of problem. My game engine is "allocation and initialization happen at the system level in batches not at the single object level" - so the tree system keeps track of the allocation and initialization of trees and so on.More and more I find myself steering away from OOP, RAII and ECS because I find in the wild they're more like ideologies than they are tools to solve a problem. People have these ideas swimming around in their heads and, instead of looking at the problem they're encountering and building something organically to match it, they jump to the nearest thing they've heard about and implement that, even if it doesn't actually match the problem. Sometimes they even implement these things before they SEE any problems, which is especially bad.
(DIR) Post #AP6XfZ7YxgZ9dvMzDc by RustyCrab@sleepy.cafe
2022-10-30T20:50:48.824628Z
2 likes, 0 repeats
@Binkle I'm generally steering away from OOP as well, and that's partially why I'm asking this question. RAII just seems like basic common sense though. Something about babies and bathwater. I sometimes hear RAII criticized but am never given a viable alternative, or one that just sounds hyper situation specific or flat out insane.
(DIR) Post #AP6XtN7qMDPWUg5IUy by RustyCrab@sleepy.cafe
2022-10-30T20:53:19.079559Z
1 likes, 0 repeats
@Binkle I will say that encapsulation for the sake of maintaining class invariants does work. Encapsulation as a general principle though does not. It always falls the fuck apart in the real world.
(DIR) Post #AP6YAfRPVu1gDnU3pQ by deprecated_ii@poa.st
2022-10-30T20:56:27.736408Z
3 likes, 0 repeats
@RustyCrab RAII to me means a lot more about ownership and object life cycle and so on, not so much about just initializing to non-garbage. the *deallocation* seems more important than the allocation, once you're past the "yep we got the memory" stepbut sure, I automate the hell out of my allocation and initialization. it would be silly not toHOWEVERI also think dynamic allocation is a bad idea and everyone would be better off ditching the idea entirely
(DIR) Post #AP6YQN4jZ4cXtWMhhw by Binkle@sleepy.cafe
2022-10-30T20:59:17.266935Z
2 likes, 0 repeats
@RustyCrab yeah I mean sometimes it's appropriate. If you're allocating and deallocating things constantly and it's always a single object at a time, and the data must be packaged together in memory, it makes sense (I can think of several situations where that's the case). More than anything I advocate for building your solutions organically, based on how you're thinking about the problem and how your thinking evolves over time, rather than bringing in these sorts of notions to limit how much you have to consider the problem at hand. It's very possible that RAII, OOP, and ECS can be the final result of this process and I wouldn't steer away from them intentionally just for the sake of it. It's not really a great answer that makes one feel great hearing it, but I genuinely do believe "it depends on the context" is the right way to think about it
(DIR) Post #AP6ZEAfJyj81swE0oq by RustyCrab@sleepy.cafe
2022-10-30T21:08:17.404967Z
2 likes, 0 repeats
@deprecated_ii dynamic allocation is best avoided where possible, but it's largely unavoidable nowadays. Languages like java are just a shit show though. C# does a significantly better job but I wish we could get away from garbage collection in general. It causes a lot of problems that you can't fix.
(DIR) Post #AP6aRyo0yAjx6wRJtQ by deprecated_ii@poa.st
2022-10-30T21:21:59.938659Z
0 likes, 0 repeats
@RustyCrab I don't think dynamic allocation is unavoidable, it's just that *as a consequence of modern practices* people don't know how to approach itif you allocate a big chunk of memory up front, and then manage internal allocation directly as necessary instead of relying on the OS, you remove an entire class of dangerous memory problems. and working within known constraints makes the system much more provable, there's no "oh we'll keep allocating until the machine runs out", you just know you have N bytes for X purpose and you have to stay inside it, periodin a sense you're still doing dynamic allocation (reassignment of memory you already have, really), but within a bounded space, without making millions of maybe-it-works-maybe-it-doesn't calls through the platform layer into the mythical infinite virtual memory spaceit requires more planning, a better understanding of the system, and frankly more skill, but the result is a much more robust and provably-correct model of the system you're makingif all an OS did today was assign a program its own core(s) and its own block of directly addressable physical memory, with *no ability at all* to stray outside those resources, I'd be happy as a pig in shit. because that's a much more sensible way of doing things than what we do now, with all this pointless resource sharing on systems that have way more than enough resources to *not* be shared for the things people actually want to do 99.9% of the time
(DIR) Post #AP6dZ7NTnTqlaP7ia0 by RustyCrab@sleepy.cafe
2022-10-30T21:56:53.489884Z
1 likes, 0 repeats
@deprecated_ii @Binkle I really don't think pooling helps tbh. It's just moving the problem from once place to another. You're just less likely to get an access violation now but in a way that makes correctness bugs actually harder to catch since you don't get "warnings" about it. What you can do however is try to isolate allocations into controlled blocks of time and try to avoid allocations outside of that. For instance when a job starts you can try to allocate what you need up front in one go. It will likely use more resources than necessary but you're not mixing allocation logic with businesses logic and that can help.Also watched this video https://www.youtube.com/watch?v=QM1iUe6IofMIt turns out that most of what he recommended are things I'm really already doing. I typically keep encapsulation strictly for holding invariants like tree or queue structure. Whenever possible I write stateless static functions in "utility libraries" that only compute stuff or mutate the state of an object. I use "utility classes" simply because resharper is much better at working with classes than namespaces. A class with no data is the same as a namespace however.
(DIR) Post #AP6lhDngbJOPSJkxZQ by icscarythings@sleepy.cafe
2022-10-30T23:27:59.623195Z
1 likes, 0 repeats
@RustyCrab On the de-alloc side, a non-OOP language could solve this other ways like using a feature like Go's defer or supporting some kind of reference counting that calls a registered function when none are left.For the initialization side, the main issue is that you can (or the language makes it too easy to) declare data members without giving them an initial value. This doesn't really have to be a problem with procedural languages as a whole, but would rather be a design flaw with C itself (along with other languages of its era). A non-OOP procedural language could fix this by requiring an initial value assignment for all data at initialization. Decoupling of initialization and declaration is the real problem here because it makes it impossible for the compiler to enforce against easy mistakes (e.g. no initialization, partial initialization (which can sometimes happen due to a new member being added to the data structure without updating every place it was used)). You would need to have an exception for this in cases where initialization would be outside the project code (e.g. the sort of cases where you would need to use the volatile keyword, for accessing hardware level stuff).
(DIR) Post #AP6wrqDJjbHQz60mMi by SSumma@social.anthro.cc
2022-10-30T23:06:27.461847Z
1 likes, 0 repeats
Yeah it's a real pain that .Net doesn't have any kind of RAII mechanism, makes it difficult to implement hard guarantees about resource lifetime. Wish I could just add a finalizer to value types that I can rely on to be called, the dispose pattern is no replacement, it's opt in.I implemented a generic ref count mechanism for a project recently, and it's not —and nor can it be— as robust as I'd like, if you're not thinking you can easily drop a handle as an r-value, so you have to be very formal and make sure all appropriate handles you create are given an explicit variable declared with `using`, or otherwise somehow disposed in a `finally` block.Kinda wish C# had a little more C++ hybrid vigor tbh (variadic generics and type classes would be great too plsnthx)
(DIR) Post #AP6wrqeG7QpaKecIMK by RustyCrab@sleepy.cafe
2022-10-31T01:33:09.141468Z
0 likes, 0 repeats
@SSumma @Binkle destructors are really not compatible with garbage collection unfortunately. Reliable invocation with a random timer in front of it is asking for trouble. That's one of the many downsides to garbage collection.
(DIR) Post #AP6x6Oj4DSd64lns5A by RustyCrab@sleepy.cafe
2022-10-31T01:35:47.837913Z
1 likes, 0 repeats
@icscarythings you can get close to solving this with linters, at least. But yeah, uninit values is absolutely insane in current year. They should really be building that into compilers and make it opt out rather than opt in.
(DIR) Post #AP7LmgBw4EyVJ606oC by SSumma@social.anthro.cc
2022-10-31T06:10:34.069042Z
1 likes, 0 repeats
Naw, I just want opt in destructors and copy/move semantics specifically for value types. Finalizers are fine for object types.I'd never really thought about how interleaving destructed types with finalized types could cause issues, I suppose I can see it at least causing a GC performance issue by transparently adding finalizers (and thus extra GC passes) to objects, and maybe a little confusion in regards to order of finalization. I dunno though, I'd rather have the option than not.
(DIR) Post #AP7MXpPTbxbNVXohEG by RustyCrab@sleepy.cafe
2022-10-31T06:20:53.219273Z
0 likes, 0 repeats
@SSumma @Binkle I've tried to use finalizers before and found myself getting in trouble with them due to the unpredictable release times. They're pretty much only good for freeing resource handles and even that can be a problem because you're at the whims of GC.The only way to have reliable destructors is reference counting and it has its own problems. Along with being somewhat expensive, it isn't actually leak proof.