1

I have read that we can think of an OOP object as a "small program" that send messages to other "small programs" (objects), but I am not sure if this is a good analogy.

One reason that make me think that this is a flawed analogy is that with real programs, I can send a message to a program telling it to do a task, and then the program will start doing the task and then I (the message sender) can do other things while the program continue doing the task, and later I can send a message to the program asking it if it finished the task, so each program have at least one thread, while objects don't have threads (they all share the same thread, i.e. if one object is "running", then all other objects are "paused").

  • It looks like you've already answered your own question. Moreover,it's usually counter-productive to lean on analogies and metaphors for general programming concepts because they're usually based on a skewed way of looking at something. Focus instead on problem solving. For example, OOP is a mindset about organising your code by grouping things together based on how they logically relate to each other for whatever problem/s you need to solve. No useful analogies exist for that because it always depends upon the problem domain (i.e. functional requirements / what the code needs to achieve). – Ben Cottrell Jun 27 at 8:35
  • Two things. Asynchrony dramatically increases the complexity of reasoning about a program when designing or re-designing it. Secondly, objects are best thought of not as small programs, but as partial programs. Appropriate object granularity can simplify reasoning about the program whole, but it does not eliminate the need to reason globally shout the whole, and an excessive number of interacting parts may add more complexity than it eliminates. – Steve Jun 27 at 11:12
4

I have read that we can think of an OOP object as a "small program" that send messages to other "small programs" (objects), but I am not sure if this is a good analogy.

That is a good analogy.

Just like programs (or more precisely, processes), objects have their own internal memory (instance variables / fields) that is hidden from the outside world and cannot be accessed by anyone else. Just like processes, objects have their own internal code (private methods) that they use to implement their functionality but that is hidden from the outside world and cannot be called by anyone else. Just like programs, the only thing you can observe is how they react to the messages you send them. Just like programs, I can implement a replacement program that behaves identically, and you cannot tell the difference. (For example, unless you explicitly start looking for incompatible GNU-specific command line options, you will not be able to distinguish BSD mkdir from GNU mkdir simply by calling it and observing its response.)

In fact, processes are actually how objects are implemented in Erlang. In Erlang, processes and objects are the same thing.

Alan Kay minored in microbiology. He was also acquainted with, and followed the progress of, the people who were designing what would become the ARPANET, which evolved into the Internet.

So, when he created Smalltalk and shaped the way we think today about OO, he was influenced by the way that simple cells can form complex organisms by sending chemical / electrical messages to each other, and by the way that computers on the Internet communicate by sending messages. You cannot access another computer's RAM over the Internet, you cannot execute code on that computer. All you can do is send it a message, and observe the reply. He explicitly used the metaphor that every object is like its own little computer with its own RAM (instance variables) code (private methods), and only a well-defined external messaging interface (TCP/IP):

In computer terms, Smalltalk is a recursion on the notion of computer itself. Instead of dividing "computer stuff" into things each less strong than the whole—like data structures, procedures, and functions which are the usual paraphernalia of programming languages—each Smalltalk object is a recursion on the entire possibilities of the computer. Thus its semantics are a bit like having thousands and thousands of computers all hooked together by a very fast network. Questions of concrete representation can thus be postponed almost indefinitely because we are mainly concerned that the computers behave appropriately, and are interested in particular strategies only if the results are off or come back too slowly. —The Early History Of Smalltalk, Alan Kay

One reason that make me think that this is a flawed analogy is that with real programs, I can send a message to a program telling it to do a task, and then the program will start doing the task and then I (the message sender) can do other things while the program continue doing the task, and later I can send a message to the program asking it if it finished the task, so each program have at least one thread, while objects don't have threads (they all share the same thread, i.e. if one object is "running", then all other objects are "paused").

You are confusing the concept of object-orientation with one specific, narrow, implementation of object-orientation. For example, in Erlang, processes / objects most certainly do run concurrently. Actually, they not only run concurrently but even in parallel and actually even distributed.

In early versions of Smalltalk, objects were concurrent. In Active Oberon, Zonnon, and related languages, objects can be "active", meaning they run in a separate concurrent context. In the Eiffel programming language, objects can be concurrent.

Carl Hewitt's Actor Model is heavily influenced by OO, specifically Smalltalk-72. The people who invented the Actor Model and the people who invented OO really thought of Actors and Objects as more or less the same things. It is only in recent years that we have artificially segregated them.

Active Objects can also be implemented as a Design Pattern in languages that don't support them natively.

| improve this answer | |
  • It's a shame Kay didn't draw the other analogy from microbiology. That biological systems based on cells and message-passing required (depending on one's explanatory tastes) supernatural design by the Almighty, or evolved through trial and error over eons of time longer than the existence of the human species. – Steve Jun 27 at 11:17
1

Describing an object as a "program" is a correct, if limited and not particularly useful analogy. Given that the basic definition of a program is just a series of instructions that can be executed by a computer; a single object can meet this defininition.

Your objection assumes that a real program must be asynchronous and multi-threaded, which is not necessarily the case. A program may have a single thread of execution and may execute instructions in sequence and still be a program. It's just that many modern applications don't work that way.

| improve this answer | |
1

Is thinking of an OOP object as a “small program” a good analogy?

Yes and no. For a beginner, the analogy helps to highlight that applications break down tasks into smaller tasks. But for an OOP developer, the analogy can lead to misunderstanding of OOP principles.

Programs are a routine, which is developed by creating individual subroutines. In that sense, you are correct that a program is comprised of mini me versions of itself, regardless of whether OOP or FP was used.

However, a routine is conceptually different from an object, so you need to carefully beware to not overextend the analogy.

A routine is a function, whereas an object is a state. In that sense, they are antithetical to one another. If you equate one to the other, you're liable to end up writing bad OOP objects that are "function bags" instead of states. And while some function bags are allowed (e.g. helper methods), those are generally static and thus not instanced (= not an object).

I can send a message to a program telling it to do a task, and then the program will start doing the task and then I (the message sender) can do other things while the program continue doing the task

In a synchronous context, you are assumed to wait and do nothing until the program returns its result. What you're describing is an asynchronous context.

I'm note saying your real-life example is wrong, but I'm not sure if you want your analogy to rely on asynchronicity, as that opens up a whole other can of worms.

When your program is being called by another program instead of being called by you, that "parent" program is just going to halt and wait for a result - unless instructed otherwise, which is the asynchronicity can of worms I'm talking about.

It may be better just to phrase it as "when the program does something, that means the caller (you/another program) is not doing it themselves", without focusing whether you do/n't do other things while waiting for the program.

and later I can send a message to the program asking it if it finished the task,

That again is a very particular scenario and not the most common one. As a general outset, the program returns it's value to you, you don't go fetch it.

There are ways to poll for a result, but this is something you have to build when you need it. The default behavior is pushing (program returns output to you), not pulling (you fetch the output from the program).

This is the same argument as I made before about asynchronicity: it's better to avoid this additional complexity that is not essential to describing what "a program" is. You're opening up new cans of worms left, right, and center, and it's adding unnecessary caveats that make it dangerous to rely on your analogy.

so each program have at least one thread, while objects don't have threads (they all share the same thread, i.e. if one object is "running", then all other objects are "paused")

This is where your analogy is just wrong, or at least misunderstanding exactly what a thread is.

All other objects are not paused. You just relied on the implicit assumption your ability to asynchronously do something else while the program is running. The same principle applies here: in an asynchronous context, multiple objects can be executing their logic at the same time.
I'm not delving into the specific distinction/relation between asynchronicity and multithreading, as that is not the goal of the analogy.

Objects don't "have" threads. Objects live in the runtime, and threads are the workers of that runtime. Think of it like mechanics working in a garage. They are individual workers, but they share the same wall of wrenches. Those wrenches are your objects, and the mechanics are your threads.

A wrench does not own a mechanic. A mechanic does not own their own wrench (they are the garage's property), though they can temporarily use a wrench when they need to.

Similarly, an object does not have a thread. A thread does not own an object (they are the runtime's property), but it can use an object when it needs to.

| improve this answer | |
0

No, an object is not a little program. It is a thing containing state and typically passive behaviors. The latter being methods waiting to be called by a program.

To me the message analogy is not very helpful. Neither is bringing threads into the picture. An object may use threads of its own to perform tasks asynchronously but this is independent of its objectness.

If you must have an analogy, think of an object as a piece of software covering a distinct piece of functionality. Both its data (state) and methods (behavior) are directly related to that functionality.

It is possible to create a program from objects that meet your definition, with each major object running on its own thread, processing messages posted to it and sending messages to other objects. Those systems do exist. I can tell you from personal experience that this kind of application is a nightmare to debug, and is prone to hard to find threading issues if not implemented flawlessly.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.