On Nov 29, 2023, at 15:49, Egon Elbre <egon...@gmail.com> wrote:For the code perspective, I would probably start from the humane side first; e.g. something along the lines of* principle of least astonishment
* reasonable working memory load
* principle of locality
* clarity of meaning
* semantic compression
On Nov 29, 2023, at 15:49, Egon Elbre wrote:For the code perspective, I would probably start from the humane side first; e.g. something along the lines of* principle of least astonishmentShow me some research that justifies this is so, or a formulation that it is even a distinct design goal of the paradigm.
* reasonable working memory loadDitto. This is the goal of any design paradigm.
* principle of localityWell, DCI kind of shows that it failed at that.
* clarity of meaningShallow— that is just semantics. Most software problems are hermeneutical.
Thanks for the responses!
@Cope
I remember many past comments on this group where you said that, and I actually already read "Abstraction Descant" to get a better understanding of abstraction vs. compression—although that seems not to be the main focus of that particular essay, which mostly talks about how abstraction becomes a problem when taken too far. (I should go back and read his earlier essay in the same book about compression.)Abstraction is evil
I liked the restaurant analogy of abstraction vs. compression in this short article, which I think echoes some of the concepts you've mentioned here before and also in the Lean Architecture book.
An interesting thing I noticed when looking at various OOP resources talking about "abstraction" is that different people seem to define it in different ways. A note before I continue: I'm not seeking to debate you on this (which I'm certainly not qualified to do), but simply to understand it better, and also to point out that there seem to be a variety of definitions even in the more academic literature. Some definitions even seem to use it to mean the same thing as how you and Gabriel define compression, i.e. a shorthand to compress shared understanding without actually throwing any information away. For example, Booch defines abstraction as being relative to the perspective of the viewer, which seems compatible with the idea of compression if I understand correctly (illustration below from his book):
There also seem to be some cases where throwing information away is actually desirable, e.g. when interacting with a relational database you can run SELECT and UPDATE queries without having to think about how those are implemented...but I suppose that's a different case because it's at the system level rather than objects within one system.
Setting aside possibly incorrect definitions of abstraction, if
compression is what we want, the more important question is: it is
an essential principle of object orientation (recognizing that it
also is a good practice for any paradigm), or more of a secondary
principle that would be better to introduce to new developers a
bit later?
The number one pillar of OO is messaging: anything else is beyond secondary
In practice, I rarely implement any objects where the message sent to an object doesn't exactly match the name of the method that's responsible for handling that message, but there have been some rare exceptions. For example, consider a UserRepository object that can handle various 'find' messages like 'findByName', 'findByEmail', 'findByZipCode', etc - rather than writing separate methods for each of those, there could be a single method that handles all of those (delegating to helper or utility functions as needed). In Smalltalk this would be handled by writing a 'doesNotUnderstand:' method to tell it what to do with the unrecognized message (not all so-called OO languages support such a feature, which Trygve criticized, I think rightly so if we want to be true to the original OO vision).
So the distinction between messages and methods is one thing, but I don't know how much that ties into your emphasis on messaging. While the distinction is nice to have, I think we can certainly still write OO code and think in OO without it, as long as we have objects that contain both state (or immutable data) and behavior that can communicate with each other. Am I on the mark here?
There's more to discuss, but this message is already getting too long so I'll stop here for now.
Thanks,
Matt
Could be relevant -- I remembered an article on examining the what people find essential in object orientation:(Also see the references)
Kind of funny that inheritance made the top of their list at the time ;)
Still an interesting article though, thanks for sharing.
On Nov 29, 2023, at 22:59, Matthew Browne <mbro...@gmail.com> wrote:There also seem to be some cases where throwing information away is actually desirable, e.g. when interacting with a relational database you can run SELECT and UPDATE queries without having to think about how those are implemented...but I suppose that's a different case because it's at the system level rather than objects within one system.
Setting aside possibly incorrect definitions of abstraction, if compression is what we want, the more important question is: it is an essential principle of object orientation (recognizing that it also is a good practice for any paradigm), or more of a secondary principle that would be better to introduce to new developers a bit later?
On Nov 30, 2023, at 01:46, Raoul Duke <rao...@gmail.com> wrote:we need to be able to see edit run manipulate investigate watch debug query poke the code from several different representations.
Hi Cope,
I'm curious, if we restrict the conversation to only "atomic event
architectures" where DCI roles/contexts would be less relevant,
would you say your views on OO have changed a lot since the late
90s?
I looked up one of the chapters of your book "Multi-Paradigm Design in C++" where you discussed object orientation to see if it would provide clarifications on some of the things you've been saying here, and it looks like you defined it quite differently at that time, although I'm sure at the core you had similar goals.
--
You received this message because you are subscribed to the Google Groups "object-composition" group.
To unsubscribe from this group and stop receiving emails from it, send an email to object-composit...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/object-composition/1BB7FB55-B260-4618-B048-BE10739A07A8%40yahoo.com.
On Nov 30, 2023, at 14:55, Matthew Browne <mbro...@gmail.com> wrote:Hi Cope,
I'm curious, if we restrict the conversation to only "atomic event architectures" where DCI roles/contexts would be less relevant, would you say your views on OO have changed a lot since the late 90s
I looked up one of the chapters of your book "Multi-Paradigm Design in C++" where you discussed object orientation to see if it would provide clarifications on some of the things you've been saying here, and it looks like you defined it quite differently at that time, although I'm sure at the core you had similar goals.
Hi Cope et al.,
I think I'm finally beginning to understand why so many of the
folks familiar with early OO history (including Kay himself)
emphasize messaging so much... (I also learned that Kay apparently
regretted naming it "object-oriented" because "objects", while
important, put too much emphasis on the objects rather than the
messages.)
Feel free to let me know if I'm off-base on any of this; below is
a description of what I'm gathering from my research.
It's much bigger than what I mentioned before about the technical
distinction between a method call and a message: it's about
designing good public interfaces and effective communication
between objects.
Consider this illustration, copied from the book Practical Object-Oriented Design: An Agile Primer Using Ruby by Sandi Metz:
The application on the left is basically meant to represent spaghetti code - objects calling methods on each other that probably shouldn't even be part of their public interface - overly coupled and a lack of encapsulation. And to quote from the book, "The second application is composed of pluggable, component-like objects. Each reveals as little about itself, and knows as little about others, as possible." (Of course some systems might be legitimately complex enough to look more like the one on the left even when well-designed, but these are just examples.)
So this is why the conceptual difference between a message and a
method call is so important: messages respect the boundaries of
objects and take an "ask for what, instead of telling how"
approach. Even if we mark internal helper methods as private, that
doesn't mean we've necessarily done a good job of designing a
public interface based on a mental model of how one object should
request something from another.
Another quote:
Instead of deciding on a class and then figuring out its responsibilities, you are now deciding on a message and figuring out where to send it.
This transition from class-based design to message-based design is a turning point in your design career. The message-based perspective yields more flexible applications than does the class-based perspective. Changing the fundamental design question from “I know I need this class, what should it do?” to “I need to send this message, who should respond to it?” is the first step in that direction.
On 12/1/23 11:20 AM, James Coplien wrote:
Many OO / Smalltalk advocates of the old days were trying to sell the idea that objects were independent fiefdoms, each with their own thread of control.
I assume those ideas shared a lot of similarities with the actor
model.
It was actually this
article, "Erlang is the Most Object Oriented Language" that
led me to the book I quoted above.
From the article:
If we take Alan Kay’s definition of object orientation as canonical, then Erlang fits almost perfectly. Instead of “objects” per say, Erlang uses “processes” that are fully isolated constructs that can only communicate with each through message passing.
Obviously we don't get that with Ruby, JavaScript, Java, C#, or even Smalltalk (at least in a non-distributed system), i.e. objects are not "processes" in their own right. (Note: I'm not literally talking about OS processes here, but I am talking about concurrency, among other things.) But that doesn't make the concept of message passing any less helpful in those languages. However, it does beg the question of whether we're really doing "message-oriented programming" (which seems like it would have been a better name for OOP) if we don't at least have either a message bus or an environment similar to Erlang.
As interesting as all of this is, getting back to my original
goal when I started this thread, I wonder how relevant teaching
fully "message-oriented programming" is for those working in
today's most popular programming languages, or even in a
non-distributed program written in trygve or other
similar DCI system (which we could perhaps call "DCI classic"—I
certainly think DCI could be extended, but I haven't seen many
real examples of that yet). Based on what I described above, I
think that messaging could still be a super important concept to
teach for effective programming of a frontend TypeScript web
application (which is my focus), but the kind of "messaging"
possible there probably falls well short of what early OO thinkers
were dreaming of.
--
You received this message because you are subscribed to the Google Groups "object-composition" group.
To unsubscribe from this group and stop receiving emails from it, send an email to object-composit...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/object-composition/D0C05EBB-6DFD-43DC-AAF6-4887DC2CD9E4%40yahoo.com.
so i fail to see how "ask don't tell" cannot be done with regular method invocations, all the java oop gurus recommended it too???
I agree. Basically what I was trying to say is that my earlier message missed the point: the important thing is the concept of messaging. Yes, one can make an argument that Smalltalk is more purely OO than Java because it has 'doesNotUnderstand' which decouples method calls from messages, but in practice in Smalltalk the messages almost always map directly to the methods anyway.
Whereas thinking in messages (at a basic level at least) can of
course be done in almost any language, and certainly quite nicely
in Java and other modern "OOP" languages.
--
You received this message because you are subscribed to the Google Groups "object-composition" group.
To unsubscribe from this group and stop receiving emails from it, send an email to object-composit...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/object-composition/CAJ7XQb5aRZsGDcuidr%2BVuSWd1LsfVHvDszL95FBce2_g9tzwZQ%40mail.gmail.com.
On Dec 2, 2023, at 00:18, Matthew Browne <mbro...@gmail.com> wrote:The application on the left is basically meant to represent spaghetti code - objects calling methods on each other that probably shouldn't even be part of their public interface - overly coupled and a lack of encapsulation. And to quote from the book, "The second application is composed of pluggable, component-like objects. Each reveals as little about itself, and knows as little about others, as possible." (Of course some systems might be legitimately complex enough to look more like the one on the left even when well-designed, but these are just examples.)
On Dec 2, 2023, at 00:18, Matthew Browne <mbro...@gmail.com> wrote:
Instead of deciding on a class and then figuring out its responsibilities, you are now deciding on a message and figuring out where to send it.
This transition from class-based design to message-based design is a turning point in your design career. The message-based perspective yields more flexible applications than does the class-based perspective. Changing the fundamental design question from “I know I need this class, what should it do?” to “I need to send this message, who should respond to it?” is the first step in that direction.
On Dec 2, 2023, at 01:25, Dom <dom.spi...@gmail.com> wrote:If we start with the perspective of objects having to send messages, the possibility of the message being sent to something that doesn’t understand it seems almost inevitable.
Hi Cope,
You're right of course that real object-oriented systems rarely
result in neat-looking interaction pathways, but I think I didn't
explain the illustration well enough...
Let's call these application 1 and application 2:
(figure A)
In Application 1, the public interfaces of the objects expose too
many implementation details (here "aTrip" knows lots of
implementation details of "aMechanic"):
(figure B)
Contrast with application 2:
(figure C)
The concept of designing good interfaces for a network of collaborating objects isn't new to me of course, I just hadn't thought of it in terms of "messaging" before (although "network of collaborating objects" always requires messaging of course).
Perhaps the main failure of the first illustration (figure A) is
that the author seems to be mainly thinking of interfaces and
classes rather than individual objects at run-time—as soon as we
shift our perspective from compile-time to run-time, I think
things will always start looking more like the diagram for
application 1.
Have a look at selfOrganization.k in trygve. It is both the most object-oriented program I have ever written, and illustrates an example of how object-oriented interactions work.
I will have to check that out in more detail; thank you!
--
You received this message because you are subscribed to the Google Groups "object-composition" group.
To unsubscribe from this group and stop receiving emails from it, send an email to object-composit...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/object-composition/E27BE9D5-2CF1-4545-8518-0EE3A9375D3D%40yahoo.com.
When a function returns a value, it doesn’t have to worry about where it is going. What if we think of messages being more like return values rather than like method calls.
To view this discussion on the web visit https://groups.google.com/d/msgid/object-composition/2efdb8fe-cd2f-437a-a503-197bb05272acn%40googlegroups.com.
On Fri, Dec 1, 2023, 8:02 PM Dom <dom.spi...@gmail.com> wrote:When a function returns a value, it doesn’t have to worry about where it is going. What if we think of messages being more like return values rather than like method calls.The idea of the sender not worrying where the message is going is interesting. But I suppose one difference with function return values is that you would never want the return value to go somewhere other than back to the requester (or at least, I can't think of a reason why you'd want that).
To view this discussion on the web visit https://groups.google.com/d/msgid/object-composition/CAJA9FQ-TW-_B-AnsN0-8gvgz2X0XgSKTgi4ZTY_4MY9joKnDJg%40mail.gmail.com.
On Dec 2, 2023, at 01:25, Dom <dom.spi...@gmail.com> wrote:If we start with the perspective of objects having to send messages, the possibility of the message being sent to something that doesn’t understand it seems almost inevitable.But this happens even in C++ and Java. It’s just that the compiler catches it at compile time.
One of the very clever things about trygve is that its type system catches such things while still giving all the flexibility you would expect.
Its duck typed roles?
On Dec 4, 2023, at 14:28, Dominic Robinson <d...@spikeisland.com> wrote:I don't think that "messages" are the method calls that we see in languages such as C++, java or even trygve.
On Dec 4, 2023, at 15:27, Dominic Robinson <d...@spikeisland.com> wrote:The compilers can ensure type safety, but unless you write programs in such a way that the type system guarantees that an inappropriate (out of contract) call can never happen, there are still the run-time cases where a call. or arguments passed to it, are contextually inappropriate and cannot be correctly understood.
On Dec 4, 2023, at 15:27, Dominic Robinson <d...@spikeisland.com> wrote:
So it depends on how you choose to define "not understood”
To pull this off requires a deep degree of reflection, though it’s not explicit at the source language level.
C++ has a tiny bit of it,
and if you use the right disciplines you can do real OO in C++.
(Again, nothing here that isn’t Turing complete, You can do it in FORTRAN too but the code becomes unreadable.)
You don’t have to be so disciplined — or thorough — in trygve or the other DCI languages. They support an abstraction boundary so I don’t have to worry about the dispatching semantics, at all. Most of the time I don’t have to worry about them in C++, but there are times when the static type system prevents the kind of flexibility that true OO messaging supports (e.g. things akin to duck typing).
The trygve language is really about ten times as complex as it seems at first glance, and I take a lot of satisfaction from having been able to hide that complexity from its users. If you can imagine it, it’s probably possible…
There are those who maintain that asynchrony (in one’s mental model) is essential to messaging and to OO. I tend to disagree, but given the Simula legacy of Smalltalk I’d sure like to hear Alan speak explicitly to this. He seems to never speak to the issue, almost as though he were avoiding it.
It is all those mechanisms that are necessary to support DCI's flexibility. I call that object-oriented programming, and the mechanisms that support the dispatching, I call messaging.
Hi Cope,
Based on the self-organization
example, I would have thought you were basically saying that
a system is only object-oriented if it has emergent
behavior—if it were not for your more recent messages.
I know that Kay had ambitious long-term goals that weren't fully
realized in Smalltalk, but I think that Smalltalk could still be a
useful starting point to consider how well a language supports the
messaging paradigm—even if the answer turns out to be "not very
well" (although that would sound odd given that Kay himself was
the lead creator of it).
I think this would be a good time to bring up your recent
discussion with Marius about DCI—I wish I had watched it
sooner (I was very busy at the time it was posted and forgot about
it). It really helped me understand your points about abstraction
and compression, and it seems that the contrast you made between
the Dynabook vision and fully emergent systems (perhaps
complimentary but different) is very relevant to what we're
talking about.
The other point in that video is that at the end of the day, the
most important goal of DCI is readable code. Is that also the most
important goal of OO even before we bring DCI into the picture?
I'm not so sure...with things like emergent systems or fully
asychronous messaging, some aspects might become simpler, but
others become much more complex. In some systems this is essential
complexity of course (rather than accidental complexity), or maybe
I'm misunderstanding and it's not necessarily any more complex,
but my real goal is to define some concepts that will help even
junior developers writing relatively simple programs to write
better and more readable code that expresses a shared mental model
of the system. I think that with the trygve language, you
have succeeded in creating a very approachable language, but if I
understand correctly then there are different levels of messaging
we are talking about here. What makes the self-organization
example special is that it's deliberately setting up objects in a
way that's similar to how cells work in a biological organism. And
of course not every trygve program will do that, or needs
to do that.
In addition to better defining "messaging", maybe we need to back up and ask why messaging is so important, and in what contexts.
And just to get back and answer an earlier question you asked:
You’re preoccupied with interfaces. Which interface?
I simply meant the public methods of an object—or something
roughly equivalent. These days I actually write React components
more often than I write classes (or Contexts, sadly). For better
or worse, modern-day React components are no longer defined using
classes: they are defined using functions but they can still have
internal state. In the case of React components, the public
"interface" would be the "props" that the component accepts, which
can optionally include callback functions to handle certain
events.
An interesting comment here about the Julia language:
Julia is fully object oriented. The core of OO is not to write a dot between an object and an associated function but that one has virtual functions. Multiple dispatch provides just that.
On Dec 4, 2023, at 23:49, Dominic Robinson <d...@spikeisland.com> wrote:On Mon, Dec 4, 2023, at 3:38 PM, James O Coplien wrote:To pull this off requires a deep degree of reflection, though it’s not explicit at the source language level.Is this what you were alluding to when you said that messaging requires a MOP?That is to say that the implementation layer, whether compiled, interpreted/run-time, or both requires reflective facilities?
C++ has a tiny bit of it,C++ has much stronger capabilities in this area than most people realise, but it isn’t at all obvious. You’d be surprised.
and if you use the right disciplines you can do real OO in C++.Certainly pretty much everything that trygve does and some things it doesn’t.
(Again, nothing here that isn’t Turing complete, You can do it in FORTRAN too but the code becomes unreadable.)You can always do pretty much anything if you are prepared to squint, but the challenge is to do things in such a way as to achieve compression from the abstractions you provide, ensure they sure they work predictably in combination, and feel natural to use both semantically and syntactically (not hideously ugly or requiring pages of typing) with the rest of the language.
You don’t have to be so disciplined — or thorough — in trygve or the other DCI languages. They support an abstraction boundary so I don’t have to worry about the dispatching semantics, at all. Most of the time I don’t have to worry about them in C++, but there are times when the static type system prevents the kind of flexibility that true OO messaging supports (e.g. things akin to duck typing).
Whilst C++ does require that the classes of objects that can play a role be subtypes of the declared role player type (not duck typed), I don’t think I’ve come across a situation where this causes a problem. There is an argument that the requirement to make this explicit through an abstract base type is a positive.'
The trygve language is really about ten times as complex as it seems at first glance, and I take a lot of satisfaction from having been able to hide that complexity from its users. If you can imagine it, it’s probably possible…Having built more than one C++ equivalent I think I can :).
There are those who maintain that asynchrony (in one’s mental model) is essential to messaging and to OO. I tend to disagree, but given the Simula legacy of Smalltalk I’d sure like to hear Alan speak explicitly to this. He seems to never speak to the issue, almost as though he were avoiding it.It would be interesting from a historical point of view. Some of the early OO talks describe biological inspirations which, to me, seem necessarily asynchronous.The asynchronous aspects become essential in some domains, at which point you have no option but to integrate them in some way.
Your description of C++/P and Tasks resonates here.
Our current approach is to integrate both synchronous and asynchronous aspects in such a way that the two can be combined smoothly. You need to be aware of what is going on because they have different underlying models, but the code looks and feels very similar. You aren’t locked into one or the other.'
Part of this is to make objects/contexts feel more autonomous. Even some of the synchronous code feels asynchronous (and can become so if necessary as the code evolves).
Both synchronised and asynchronous messaging bring their own, distinct, different problems and complexities. You need facilities to mitigate each so that you can use whichever best suits each part of the problem. I think you need both.
The event/continuation mechanism (another form of dispatch) I talked about back in January is a form of control abstraction that can provide very high levels of compression of control flow code.It is all those mechanisms that are necessary to support DCI's flexibility. I call that object-oriented programming, and the mechanisms that support the dispatching, I call messaging.O, I’ll buy that as a classification.
--
You received this message because you are subscribed to the Google Groups "object-composition" group.
To unsubscribe from this group and stop receiving emails from it, send an email to object-composit...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/object-composition/fa073e38-ea42-4987-a25d-245d08bcceb2%40app.fastmail.com.
On Dec 5, 2023, at 03:43, Matthew Browne <mbro...@gmail.com> wrote:I simply meant the public methods of an object
On Dec 5, 2023, at 03:43, Matthew Browne <mbro...@gmail.com> wrote:
would have thought you were basically saying that a system is only object-oriented if it has emergent behavior—if it were not for your more recent messages.
On Dec 5, 2023, at 03:43, Matthew Browne <mbro...@gmail.com> wrote:
if I understand correctly then there are different levels of messaging we are talking about here. What makes the self-organization example special is that it's deliberately setting up objects in a way that's similar to how cells work in a biological organism.
On Dec 5, 2023, at 05:38, Matthew Browne <mbro...@gmail.com> wrote:Julia is fully object oriented. The core of OO is not to write a dot between an object and an associated function but that one has virtual functions. Multiple dispatch provides just that.
Is this what you were alluding to when you said that messaging requires a MOP?
That is to say that the implementation layer, whether compiled, interpreted/run-time, or both requires reflective facilities?
Yup.
BTW for those following along... if you Google for "MOP", one of the things that comes up is "message oriented programming". Meta-Object Protocol also comes up of course. The above confirms that you were indeed referring to "Meta-Object Protocol". Might be obvious to most but I thought it would be good to point out (TBH I previously wasn't 100% sure if you were referring to Meta-Object Protocol or something else.)
On Dec 5, 2023, at 13:54, Matthew Browne <mbro...@gmail.com> wrote:if you Google for "MOP", one of the things that comes up is "message oriented programming
On Dec 5, 2023, at 18:20, Dominic Robinson <d...@spikeisland.com> wrote:I liked CLOS' multi-methods for this back in the day.
--
You received this message because you are subscribed to the Google Groups "object-composition" group.
To unsubscribe from this group and stop receiving emails from it, send an email to object-composit...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/object-composition/37e24ee8-4880-431d-8d72-50350f1c8e8a%40app.fastmail.com.
On Dec 5, 2023, at 18:42, Raoul Duke <rao...@gmail.com> wrote:* A pillar of anything should be developer experience DX like ux but for my day job coding. Double dispatch is not imhumbleo at all good dx.
C++ is pretty much never good dx;
* Everything should start off in async by default and you should have to use special keywords to force any synchronous behavior. heh.
* A single textual representation is a tyrannical dominant encoding/representation and our tools suck for not helping us be more freely powerfully flexible including scatter/gathering and diagramming (eg see Enso). shake fist at sky.
* The most important thing is paying the bills. Which unfortunately means everybody cuts corners. I wish we thought the most important thing was communicating to other humans, such as my future self, or future other new maintainers. Then we would focus on how best to support mental model building. (That's what i want from LLMs, is to have conversational programming documentation/development/refinement.)
* Oop in some views is better called the Actor/Erlang model, n'est pas?
* Everything should start off in async by default and you should have to use special keywords to force any synchronous behavior. heh.
Bullfeathers. I can think of nothing that is a worse fit for how the human mind works. Me, I use mainly my mind when I program. Maybe you’re one of those TDD guys who just do and do and do instead of think… :-)
I agree that "everything should start off in async by default" is
going too far, but consider how in node.js, all I/O operations are
async (I think the same might be true in Go). This led to some
unnecessary complexities (callback pyramids) when using earlier
versions of JS, but now that we have async/await, I don't find
that it generally makes the code much more difficult to write or
understand, and the async I/O certainly makes the system much more
efficient.
The task methods in C++/P you mentioned sound interesting. I
suppose there are multiple effective ways of reducing async
complexity from the programmer's point of view, although of course
when debugging etc. it's important to understand what's actually
going on.
--
You received this message because you are subscribed to the Google Groups "object-composition" group.
To unsubscribe from this group and stop receiving emails from it, send an email to object-composit...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/object-composition/1229ec4c-cec2-4fda-beef-b2104209dfb7%40gmail.com.
This trend to separate areas of accountabilty (often wrongly touted as a separation of concerns) curiously correlates with a broad cultural migration to rugged individualism as opposed to teamwork or social cooperation.
I recently stumbled across something stunning in systems thinking from Russ Ackhoff. He maintains — correctly, I think — that system adaptability is proportional to the cohesion of a system. Cohesion (as defined by Constantine) is inversely proportional to decoupling.
I think it could be helpful to be specific here about what type
of coupling this is. I'm guessing you're referring to coupling within
a module rather than between modules (unless you meant to say
"inversely proportional to coupling" instead of "decoupling"?). In
a cohesive module, the functionality is all closely related
responsibilities, so I suppose that in a typical case you could
end up with a lot of interdependencies between the internal
functions of your module. But by increasing cohesion, the coupling
between modules should go down because you're no longer
depending on so many other modules—the functions you need to
accomplish your goal are no longer scattered all over the codebase
in different modules.
This also reminds me of how in DCI, Contexts are highly
cohesive—you can read the whole use case in one place. This is one
of my favorite benefits of DCI. And it does it without abandoning
the idea of multiple objects working together, thanks to roles. So
you get the benefits of locality without creating a large,
unwieldy object.
Perhaps the hardest problem in programming is tracking (or even reproducing) bugs in a distributed system — and we celebrate distribution and asynchrony as though they were good things. We’re idiots in doing so.
A possible example of this: Netflix "boasts over a thousand microservices." "By decomposing its monolithic application into smaller, specialized services, Netflix achieved a level of flexibility, scalability, and continuous deployment that was not possible with a monolithic architecture. Today, Netflix’s microservices architecture empowers its engineering teams to work independently, iterating quickly, and innovating at a rapid pace." (source).
I happened to already know from blog posts, etc. that Netflix is
using Apollo Federation to give them a universal GraphQL API. So
basically, Netflix split up their system into thousands of
microservices that need to communicate over a network, only to be
stitched back together again via Apollo Federation, including what
I imagine must be rather complicated solutions for joining related
data back together.
I don't know the details of their system, but when I learned
about this my first impression was that there must be some middle
ground between one giant monolith and thousands of microservices
that would be a better solution.
On Dec 7, 2023, at 04:34, Matthew Browne <mbro...@gmail.com> wrote:But by increasing cohesion, the coupling between modules should go down because you're no longer depending on so many other modules—the functions you need to accomplish your goal are no longer scattered all over the codebase in different modules.
On Dec 7, 2023, at 04:56, Raoul Duke <rao...@gmail.com> wrote:In a cohesive module, the functionality is all closely related responsibilities
like an object :-)
On Dec 7, 2023, at 05:05, Matthew Browne <mbro...@gmail.com> wrote:A "module" could be an object, or something bigger like a package.
On Dec 7, 2023, at 05:22, Raoul Duke <rao...@gmail.com> wrote:and sort of make me wonder, beg the question why/what are we trying to
modularize in the first place.
On Dec 7, 2023, at 04:34, Matthew Browne <mbro...@gmail.com> wrote:
This also reminds me of how in DCI, Contexts are highly cohesive—you can read the whole use case in one place.
int g, h;Context C1 {Role R1 { g; }Role R2 { h; }}Context C2 {Role R3 { g; }Role R4 { h; }}
On Dec 7, 2023, at 04:34, Matthew Browne <mbro...@gmail.com> wrote:
But by increasing cohesion, the coupling between modules should go down because you're no longer depending on so many other modules—the functions you need to accomplish your goal are no longer scattered all over the codebase in different modules.
This is a widely held fallacy. Coupling and cohesion are independent metrics. For a module with a given cohesion (the degree to which there are references to symbols within that module from within that module) I can arrange for any range of coupling to other modules from zero to infinity.
So just to be clear, is the wikipedia page for cohesion incorrect when it states, "High cohesion often correlates with loose coupling, and vice versa"? They're only claiming a correlation, not a direct causal relationship that happens in all cases. In my original statement, "by increasing cohesion, the coupling between modules should go down," I should have said "tends to" instead of "should" go down. Or maybe I just misunderstood the whole relationship between cohesion and coupling? I thought I already understood the basics of coupling and cohesion, but lately I'm not so sure.
Sorry if I'm boring anyone with all this, but I think that this might still be on topic for this thread—an attempt to identify and understand some fundamental principles that could be considered part of an "OO & DCI 101" curriculum, even if some of them are more universal principles that aren't unique to OO & DCI. We've already identified messaging and of course mental models as critical concepts, and they're perhaps the most interesting and important. But I think coupling and cohesion should also be in the list. They seem much more useful for this purpose than the "four pillars" I referenced when starting this thread (some of which are outright misleading) or things like SOLID.
The original 1974 Structured Design paper [PDF available here]
defines coupling as follows:
The fewer and simpler the connections between modules, the easier it is to understand each module without reference to other modules. Minimizing connections between modules also minimizes the paths along which changes and errors can propagate into other parts of the system, thus eliminating disastrous "ripple" effects, where changes in one part cause errors in another, giving rise to new errors, etc. [...]
The complexity of a system is affected not only by the number of connections but by the degree to which each connection couples (associates) two modules, making them interdependent rather than independent. Coupling is the measure of the strength of association established by a connection from one module to another. Strong coupling complicates a system since a module is harder to understand, change, or correct by itself if it is highly interrelated with other modules. Complexity can be reduced by designing systems with the weakest possible coupling between modules.
(The phrase "weakest possible coupling" seems perhaps overly strong, since as the paper itself acknowledges, calling a public interface is a rather different variety of coupling than calling "something inside" the module.)
I know that classes and OOP didn't exist in Constantine's heyday, but let's say we have two modules, each containing a single class:
Module 1:
class A { ... }
Module 2:
class B { ... }
If they're coupled, that means that one or more functions in class A calls function(s) in class B, and possibly the other way around too. This is why I was confused by your statement that cohesion is "inversely proportional to decoupling". If we translate structured design to modern class-based programming languages, then could the term "module" also be used (speaking at a different level) to mean a single method within a class? Or did you literally mean that making classes A and B more cohesive would usually result in higher coupling between module 1 and module 2? Maybe reading the rest of the paper will answer my question, but this is why I now find myself more confused about the term "coupling" and how it relates to cohesion.
I don't want to make it sound like I'm asking for tutoring, but if anyone has any comments to point me in the right direction, I will certainly appreciate it. And maybe it will be interesting for the discussion too.
On Dec 8, 2023, at 03:51, Matthew Browne <mbro...@gmail.com> wrote:The fewer and simpler the connections between modules, the easier it is to understand each module without reference to other modules.
Thanks for the explanation, that makes sense.
the per-module understanding that owes to its high internal coupling (sic., cohesion)
software engineering dollars don’t go into local concerns like understanding modules, but rather in reasoning about the interaction between modules
The complexity of a system is affected not only by the number of connections but by the degree to which each connection couples (associates) two modules, making them interdependent rather than independent.
--
You received this message because you are subscribed to the Google Groups "object-composition" group.
To unsubscribe from this group and stop receiving emails from it, send an email to object-composit...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/object-composition/F389E089-2EBF-4E07-9D34-9BE61FE501FD%40gmail.com.
On Dec 9, 2023, at 05:03, Matthew Browne <mbro...@gmail.com> wrote:"Independent" might be too strong of a wrong word there, but this is how I understand it: lots of connections and lots of messaging might be exactly what we need for many kinds of problems we want to solve with our applications, but we don't want moreconnections than that or a major breakdown of encapsulation, leading to a tangled mess. This reminds me of Einstein's quote (or rather probably more of a paraphrasing), "Make things as simple as possible, but no simpler." A certain degree of coupling is needed to avoid ignoring essential complexity. And maybe some systems should follow in the footsteps of emergent behavior in nature for the same reason—honoring the essential complexity. But I think in other contexts that would simply be over-engineering, and only get in the way of understanding what's happening at run-time.
There is extremely tight coupling in DCI between a Role and its role-player, and therefore between a Role and the class of its Role-player. It is not lexical coupling — not at all, that's the whole point — but rather technological and semantic coupling.
What exactly do you mean by "lexical coupling"? Just literally
two pieces of code that exist in the same source file or module?
And if we have MyRole.someDataMethod()
in a Context, what kind of coupling is that (assuming that someDataMethod is
a method in a class defined in a different file)?
On Dec 9, 2023, at 14:20, Matthew Browne <mbro...@gmail.com> wrote:What exactly do you mean by "lexical coupling"? Just literally two pieces of code that exist in the same source file or module?
And if we have MyRole.someDataMethod() in a Context, what kind of coupling is that (assuming that someDataMethod is a method in a class defined in a different file)?
On Dec 11, 2023, at 05:18, Matthew Browne <mbro...@gmail.com> wrote:And it seems to me that there is also essential and accidental cohesion.
--
You received this message because you are subscribed to the Google Groups "object-composition" group.
To unsubscribe from this group and stop receiving emails from it, send an email to object-composit...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/object-composition/AF9C3F89-B675-4B2B-9ED0-9EFC5A1797F8%40gmail.com.
On Dec 11, 2023, at 18:50, Raoul Duke <rao...@gmail.com> wrote:so we need some day star trek tools & paradigms that let us view things from different arbitrary perspectives, anything less will always have a degree of "tyranny of the dominant paradigm" i feel.
We were taught that system behavior should "emerge" from the interaction of dozens, hundreds or thousands of local methods. The word of the day was: think locally, and global behavior would take care of itself. Anyone caught writing a method that looked like a procedure, or caught doing procedural decomposition, was shunned by the OO community as "not getting it."
--
You received this message because you are subscribed to the Google Groups "object-composition" group.
To unsubscribe from this group and stop receiving emails from it, send an email to object-composit...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/object-composition/4340B6BD-7755-449B-81DA-A547CE0A46D2%40gmail.com.
From reading and watching videos with Alan Kay (including the one he recorded this year I posted in a previous message in this thread), one thing that's clear is that he was interested in a lot of different things, and not only in computer science but in many disciplines including psychology, biology, theater and the arts in general. I think that's one of the reasons that he was so innovative. It also seems that he might have had multiple goals or visions that were somewhat separate or distinct, although perhaps they could still be complimentary in some sense (I'm not sure). In particular I'm thinking of (1) the Dynabook vision and using Smalltalk to help with childhood education, and (2) the biological vision / objects as cells or "mini computers," ultimately leading to emergent behavior. (Cope alluded to these two visions in his recent talk.)
So I think part of the challenge of understanding the early history of OO, its success or failure, and what it means for us today, is mistakenly believing that it was about only one thing, or that we have to either embrace everything Kay was working on or forget the whole thing. I think it would be more constructive to look at the various concepts one at a time and then try to construct a new vision that's informed by both the early history and what we know today, and updated to acknowledge the technological changes that have happened. And we also have to acknowledge that there are many different kinds of systems, and different paradigms work better in different contexts.
It's also good to remember that there was a whole community working on these ideas in the early days, not only Kay (I don't know a lot of the history, but Dan Ingalls is an example). Although he wasn't there from the very beginning, that also includes Trygve and others at the time who did a lot of research and thinking about the best ways to use these new concepts. So there's a lot to draw on from both early history and more recent experience.
Even for those who aren't in a position of teaching junior
developers or university students, asking what are the real
fundamental and most valuable concepts for someone learning
programming today is a very useful exercise. It has certainly
helped me realize some gaps in my own knowledge, and also reflect
on concepts that I understand intuitively from programming for a
long time but I don't think are necessarily captured well in the
way that programming is commonly taught today. I'm still
reflecting on everything we've discussed here. I think the goal
should be a conceptual framework that new programmers (and
open-minded programmers of all levels) will be able to connect
with and deeply understand and improve the quality and
maintainability of the systems we write. I think teaching the
importance of mental models is an essential part of this. As for
everything else we've discussed in this thread, including OO and
messaging, there's definitely something there but it still needs
to be better distilled and also contrasted with other paradigms
that might be more appropriate in different situations. That's
also true of DCI, which for all its value I don't see as
necessarily a "universal" paradigm, mainly because I don't think
there's any such thing.
To view this discussion on the web visit https://groups.google.com/d/msgid/object-composition/c61dfad9-0ebc-483e-8b1f-16f87cff2059n%40googlegroups.com.
On Dec 16, 2023, at 21:55, Matthew Browne <mbro...@gmail.com> wrote:I think it would be more constructive to look at the various concepts one at a time and then try to construct a new vision that's informed by both the early history and what we know today, and updated to acknowledge the technological changes that have happened.
On Dec 16, 2023, at 21:55, Matthew Browne <mbro...@gmail.com> wrote:
That's also true of DCI, which for all its value I don't see as necessarily a "universal" paradigm, mainly because I don't think there's any such thing.
Hi Quang,
That's a very interesting video, thanks for sharing. I could
definitely see some people misunderstanding and taking his advice
to the extreme, but Ousterhout has some excellent points and I
think the part about "deep classes" (not what it probably sounds
like to most folks, or at least not what I expected) speaks to the
same issues we were discussing here re: cohesion. I think many
developers definitely take decoupling too far, and he does a good
job of cautioning against that.
And his intro is spot on: as an industry, we are definitely
lacking a set of basic principles that more than a small subset of
people can agree on (based on proven success metrics) about how to
design maintainable software...and (my two cents) the few
principles we do seem to agree on often aren't well-understood.
Sort of echoing what he said, it's surprising that this isn't
viewed as a bigger issue by more industry and academic leaders. I
guess "back to basics" software design stuff isn't the most sexy
topic.
To view this discussion on the web visit https://groups.google.com/d/msgid/object-composition/ba8106a2-b332-4801-ba8a-8af4f9a40235n%40googlegroups.com.
P.S. I feel I should note that I just used the word "decoupling"
in a way that I myself was just recently confused by ;) By
"taking decoupling too far," I meant splitting a system up into
too many tiny modules/classes/etc. in a way that makes it
difficult to follow system behavior.