Object-oriented – Does object-oriented programming allows side effects and state changes

object-orientedside-effectstate

I know that obviously every language has its own characteristics and implementations, but from a theoretical standing point, viewing OOP as an abstract programming paradigm, does it allows side effects? Does it change the program state?

Every object has its own state and an object can change its own state or another object's state. So, is this state the same with the program state? And thus, OOP is not stateless?

On the other hand, OOP allows for side effects (observable interactions between objects, modify global vars).

So OOP is stateful and allows side effects? Did I got it right?

Best Answer

There is no universal definition of OOP. It is therefore difficult to make a statement like “OOP is stateful”. There are both examples where OOP involves state and examples where OOP is used without any state. OOP tends to be paired with imperative programming, which certainly allows side effects and mutable state.

There is one line of thought that OOP is about encapsulation. OOP is not needed to organize the program state into smaller records/structs. But if we turn those records into objects and encapsulate this data behind a message-passing interface, we can disentangle the program state, leading to a more decoupled and modularized architecture.

That way the state is still there, but we can look at parts of the state (each object) in isolation. There won't be any outside interference. If outside users want to access or change the state, they will have to call a method that we control. It is now easier to reason about an object. Conversely, outside users only need to know about the public interface and not all internal details, which makes their life easier as well.

So one could say that OOP is a technique for managing program state more easily.

Using OOP for encapsulation like this lends itself well to larger software systems, at least in theory. This idea is not restricted to single object instances in a programming language. One could also view larger architectures as object-oriented, e.g. in a microservice architecture each individual microservice can be interpreted as an object.

In most OOP-ish programs this state management is not done cleanly. Any time you access a global variable or call a static function you are side-stepping the decoupling benefits of only communicating via method calls. This will come back to bite you if you write unit tests for an object – any data flow through static members is data flow you can't intercept, mock, and verify.

OOP is not the only way to manage state within a larger application. Most of these features like “encapsulation” are merely an example of the modular programming paradigm, but there's no clear line between modular and object-oriented programming. Instead of parcelling state into smaller chunks that send messages to each other, functional programming suggests making all state explicit and immutable. The program flow can then be interpreted as state transformations rather than state mutations.