4 ms·
I think OOP is fine as long as it's the only thing you are doing and as long as it is single-threaded. Problems will occur if you need to convert the innards o
by beders 8y ago
I think OOP is fine as long as it's the only thing you are doing and as long as it is single-threaded.
Problems will occur if you need to convert the innards of your objects to data (i.e. JSON etc.), if you need to materialize objects from data (i.e. ORM) or if you need to write multi-threading safe code.
If you expose things as data, just be honest about it and treat it as such. It's already out in the open, why hide it in objects again?
- kazinator 8y ago> if you need to convert the innards of your objects to data Not to mention: when you need to make objects correspond to a database.
- seanmcdirmid 8y agoOOP with threads is fine. Mutability is orthogonal to OOP anyways.
- the_af 8y ago> If you expose things as data, just be honest about it and treat it as such. It's already out in the open, why hide it in objects again? What if this exposure occurs at the boundaries of your system, or when interacting with certain libraries? Surely there's value as "mostly" handling some things as objects within your system, even if you expose their innards and maybe break their invariants at the boundaries.
- jschwartzi 8y ago> I think OOP is fine as long as you are doing it and as long as it is single-threaded. I don't really see how threading has anything to do with it. What OOP allows you to do is choose what terms you want to express your solution in. You can choose language that exposes thread-safe aspects of your problem domain without requiring the user to be aware that they are expressing things in thread-safe terms. In my last project one of the early elements of our architecture was a thread-safe message queue for each thread to receive messages from across the thread boundary. Discussions on our team involved talk of messaging and threading because those were the abstractions we chose to use to express our solution. We knew that order of access was important and so we chose to make it explicit in the language we used to express the problem. And the abstraction we chose allowed us to hide the details of the problem in such a way that we did not have to worry about memory protection as long as we were consistently using the architecture we built. That was a concern of the messaging system's maintainer. We could just as easily have chosen rows and columns and operators on such and expressed the same solution in those terms. What mattered to us was making sense of the problem, domain and solution. It really doesn't matter which paradigm you use. What matters more is that you express your solution in terms that are consistent with the problem domain, and that you actually make an effort to understand the problem you're trying to solve well enough to express the solution. Anything beyond that is just sugar.
- humanrebar 8y ago> You can choose language that exposes thread-safe aspects of your problem domain without requiring the user to be aware that they are expressing things in thread-safe terms. What's a couple orders of magnitude of performance and some heavyweight link time dependencies between objects?
- legulere 8y agoOOP is linked strongly to mutable objects, which is inherently thread-unsafe. Sure you can get thread-safety in OOP, but it’s hard. It’s the same reason why global variables are bad but worse. Mutability is rarely needed and often makes things more complicated than needed.
- jschwartzi 8y agoWell, my original point is that thread-safety is easy with the right abstractions, and that choosing your abstractions is a conscious thing. So I don't see how mutability is "inherently thread-unsafe." Rather, programmers are "inherently thread-unsafe" and we have a responsibility to understand the problem domain and choose abstractions that make sense to us and that actually solve the problems we're encountering. Now if you want to talk about specific languages, then I would generally agree with you about C++ and C, but then there are ways you can design a program in those languages to be thread-safe. With FP you're just choosing a different solution to the problem which comes with its own drawbacks in some cases.
- legulere 8y agoI just doubt that those abstractions are easy and would say that they often break. Blaming the programmer for thread-unsafety in e.g. Java is like blaming programmers for memory unsafety in C. I agree if you stay in purely functional programming languages you run into points that are solved better with mutability. However those parts of a program are small and most parts are expressed better by pure functions.
- 8y ago
- Koshkin 8y ago> as long as it is single-threaded Yet, there is a well-known pattern, which is to have objects each running on its own thread. (Incidentally, this gives a new - I'd say, true - meaning to the notion of 'message passing' as the idea of how objects are to communicate.)
- beders 8y agoHow many projects do you know that do that? Yes, the original intent of OOP is message passing between objects. But no on thought about massive parallel computing back then. And how many objects do you want to run in its own thread? 10k? 100k?
- Jtsummers 8y agoI'd be comfortable with hundreds of thousands or millions of concurrently executing objects. If your system was actually operating in the "message passing" concept of OO, this wouldn't be impossible to support. Now, you'd need something lighterweight than many threading libraries (such as C++ and Java programmers usually use), you'd want something closer to Erlang's process model.
- Hodgman 8y agoThis is called the actor model, and we actually implemented it in a prototype game engine once. We made one thread per CPU core and collected messages in "cycles" - where you'd process a batch of messages in parallel, which could produce the next batch. Messages would be sorted/grouped by target object address and then partitioned among the thread pool for execution. Most of the architecture was wait-free (no locks/atomics) so it really was quite fast. This resulted in a C++ framework where you could write 'typical' OOP code and it would automatically be deconstructed into call-graphs and safely scheduled for execution across any number of threads in a completely deterministic way, without locks. We abandoned the prototype because the "typical" OO behaviour of having deep call graphs is not actually something we want to keep, making the purpose of the framework kind of shaky. Also, while performance was good, the characteristics weren't quite suitable for games -- it worked best if you had large objects, receiving multiple messages each, doing computationally complex work. In our games though, we typically have huge numbers of very simple objects, so batching messages by class instead of by object typically gives the best performance.
- Hodgman 8y agoFollow up articles in that series are going to show how to make it multi-threading and OO-compliant. "Typical" bad OOP code is a threading nightmare because the flow of control and flow of data becomes impossible to follow - it's all just random objects calling random objects calling random objects. Not spaghetti code, but spaghetti flow. To write threadable OOP, you need to avoid fine grained polymorphism and deep call graphs. Instead of doing work immediately by calling out to the next object, return some results to your caller and allow them to make the call. This also allows your caller to collect large batches of work a'la DOD... which often actually increases performance (much better I$ and D$ usage) AND it's also much closer to old school OO message passing theory, and assist in writing simple, decoupled components. I'd go as far to say that even if you're not targeting multiple threads, accounting for them in this way (NOT the stupid "just put a lock on each object" way) results in much better/simpler code.