I don’t understand. Wouldn’t an override of #'doesNotUnderstand:’ solve this 
problem? The proxies I’ve seen subclass from nil or ProtoObject and forward 
almost everything to the target. It’s really very easy.

> On Mar 19, 2022, at 3:14 AM, Richard O'Keefe <rao...@gmail.com> wrote:
> 
> An object should be a Proxy or Stub only with reference to a specific 
> protocol, which should be kept narrow.
> 
> Being a Proxy is a form of coupling.  Proxying a wide
> interface creates maintenance problems:
> Squeak 5.3 : Object selectors size => 485
> Pharo 9.0  : Object selectors size => 435
> astc       : Object selectors size => 325
> VW 8.3PUL  : Object selectors size => 304
> 
> The interface of Object is HUGE.  You want to bet that
> your Proxy got *all* of the methods right?  This
> interface didn't get that way all at once; it grew.
> The number was 78 in Smalltalk-80.  At a minimum, then,
> Smalltalk systems have accreted one extra Object method
> every two months.
> 
> So you set up your proxy to *flawlesly* mirror Object,
> and then, WHOOPS, upgrade Smalltalk and now there is a
> method that Object has and your Proxy either lacks (if
> it descends from ProtoObject but not Object) or inherits
> an inappropriate version of (if it descends from Object).
> 
> What this means is that nobody ever *does* flawlessly
> mock everything in the public interface of an object
> they are Proxying.  They proxy a *limited* protocol.
> Because that is all they *can* do.
> 
> Look, I know that people who have been trained to work
> with the stuff can use C4 as cooking fuel.  But I haven't
> had that training, so I won't touch the stuff.  In the
> same way, I dare say there are things *you* can safely
> do in Smalltalk that fumblefingers here would be burnt
> badly by.  There are many things that *can* be done that
> I *won't* do.  In a chemistry lab, I would not work with
> ClF3 let alone O2F2.  In Smalltalk, I don't monkey with
> #isNil.
> 
> On Fri, 18 Mar 2022 at 03:52, James Foster <smallt...@jgfoster.net 
> <mailto:smallt...@jgfoster.net>> wrote:
> Richard,
> 
> I very much admire Dijkstra’s admonition regarding “The Humble Programmer” 
> and was pointing a student to that article just this week. 
> 
> In any case, I think you’ve demonstrated that you now comprehend the argument 
> against inlining—you just don’t agree. That’s fair and I think the discussion 
> has been clarified. Would it be fair to say that you have an “ideological 
> objection” to allowing a Proxy or Stub to transparently stand in for another 
> object (say, in a two-object-space environment such as Pharo and GemStone)? 
> That is, a domain object can’t be replaced by a Proxy or Stub without a 
> wholesale rewrite of the rest of the application? I respect that as a 
> reasonable position (demanding perfect clarity), but I see a cost to that 
> position as well.
> 
> Of course, if you really want to avoid allowing the receiver to chose its 
> response to a message, you can use other messages. So if you want to find out 
> if an object is identical to nil you should use `nil == myObject` to ensure 
> that there was not an override of #’isNil’ or #’==‘ by the object’s class. 
> 
> James
> 
>> On Mar 17, 2022, at 2:27 AM, Richard O'Keefe <rao...@gmail.com 
>> <mailto:rao...@gmail.com>> wrote:
>> 
>> My chief concern is that I am a bear of very little brain,
>> and if you change the meaning of #isNil to anything at all
>> other than "is the receiver identical to nil" you *WILL*
>> (not may) confuse me.  This extends to things that happen
>> not to be inlined: if even a god-like Smalltalker like
>> Andres Valloud overloads #, to something other than "combine
>> the collection that is the receiver with the collection that
>> is the argument to yield a new collection" than I *WILL*
>> most certainly be confused and find the code unmaintainable.
>> Smalltalk being Smalltalk, if you admit an inconsistent
>> overload anywhere, I can no longer understand sends of that
>> selector anywhere.  One of the things to like about Traits
>> is that you can say "this class doesn't just *happen* to
>> have selectors x and y, it has them *because* it has this
>> whole consistent bundle of selectors."
>> 
>> There are more annotations documented for my Smalltalk
>> compiler than are actually implemented.  One that *is*
>> implemented is <doNotOverride>, and it has caught more
>> mistakes than I care to admit to.  It's particularly
>> important for a bundle of methods with varying arguments
>> that are meant to be routed through a single method,
>> which *is* meant to be overridden.  It makes sure that
>> I override the *right* method.  (Take #= and #~= as an
>> obvious example.)
>> 
>> Once you start down the path of lying about things like #isNil
>> you find that EITHER you have to go very far down that path
>> and override #== and #instVarAt: and a whole lot of other
>> things OR you are working with a semantically incoherent system.
>> 
>> "How should a proxy (https://en.wikipedia.org/wiki/Proxy_pattern 
>> <https://en.wikipedia.org/wiki/Proxy_pattern>) to nil respond to the 
>> #’isNil’ message?"
>> 
>> It SHOULD NOT LIE.  A proxy *isn't* nil, and it doesn't *behave* like nil,
>> even if it is a proxy for nil.  A proxy, qua proxy, can do things that nil
>> cannot.  Use another selector, #isEffectivelyNil, or whatever reveals your
>> intentions, and give it what semantics you find useful.
>> 
>> "How should the Null Object Pattern 
>> (https://en.wikipedia.org/wiki/Null_object_pattern 
>> <https://en.wikipedia.org/wiki/Null_object_pattern>) respond to #’isNil’?"
>> 
>> It should answer false.  Period.  No ifs, buts, quibbles, or maybes.
>> The whole *point* of the Null Object Pattern is to return something
>> that *isn't* nil, that has quite a different protocol.  If you call
>> something that is supposed to return either a Foo or a NullFoo, and
>> it gives you nil instead, there is a BUG in what you just called so
>> the sooner you find out the better.  What you want is
>> 
>>    Foo >> isNullFoo ^false
>>    NullFoo >> isNullFoo ^true
>> and no other class defines #isNullFoo.
>> 
>> That way, when you ask "tripeWorks grobblingMill lastPallet isNullPallet"
>> (a) you make it clear to someone reading your code what you are expecting
>> (b) if you DON'T get what you are expecting, Smalltalk will tell you.
>> 
>> I must admit that on the few occasions when I've used Null Object
>> I've used an all-purpose #isMissing instead of a task-appropriate
>> #isNullFoo, but then I figured out what I was doing wrong.  You
>> look at the code, you say "there's *something* off here, but I don't
>> know what."  But when you ask "what, exactly, does this method MEAN?"
>> you realise "oh, THAT'S what I was doing wrong."  #isMissing told me
>> it was a NullPerson or a NullAddress or a NullPartsList or ... but
>> in this case I needed to know whether it was a NullSummary.
>> 
>> And of course you run into E.F.Codd's lesson: "one NULL is never
>> enough, information can be missing for more than one reason".
>> Take the familiar example of a phone number:
>>  - I know that Fred's phone number is X
>>  - I know that Fred has a phone but I don't know what the number is
>>  - I don't know whether Fred has a phone or not
>>  - I know that Fred has no phone
>> There's room for three *different* null objects there.
>> Should we have UnknownNumberOfActualPhone to answer false to #isnil
>> and NonNumberOfNonexistentPhone to answer true?  Or what?
>> 
>> By the way, you may have misunderstood my benchmark.
>> It wasn't that #isNil or even _ ifNotNil: speeded up by
>> 10%, it was the *whole* matrix-munching benchmark that
>> speeded up.  Certainly not a big deal, but it's not
>> something I'd be happy to give up in order to get less
>> maintainable code.
>> 
>> 
>> 
>> 
>> 
>> 
>> 
>> 
>> On Thu, 17 Mar 2022 at 18:21, James Foster <smallt...@jgfoster.net 
>> <mailto:smallt...@jgfoster.net>> wrote:
>> Richard,
>> 
>> My _concern_ with inlining is that since it is designed to short-circuit 
>> dynamic method lookup, it is impossible to call a _different_ 
>> implementation. That is, you lose the opportunity to have the _receiver_ 
>> decide how to respond to the message. You may think of it as a message, but 
>> the caller is deciding how the receiver will respond—which largely defeats 
>> the purpose and role of it being a message. Yes, at the machine code level 
>> you are performing a branch instruction, but when comparing OOP to 
>> Procedural Programming we typically make a distinction between “messages” 
>> and "procedure calls." The distinction is that the receiver gets to decide 
>> how to respond to a message. In C++ this is the distinction between a 
>> “virtual" and "non-virtual" function. By inlining, you are converting the 
>> function from a virtual function to a non-virtual function, and this can 
>> make a difference (which is why virtual functions exist).
>> 
>> How should a proxy (https://en.wikipedia.org/wiki/Proxy_pattern 
>> <https://en.wikipedia.org/wiki/Proxy_pattern>) to nil respond to the 
>> #’isNil’ message? How should the Null Object Pattern 
>> (https://en.wikipedia.org/wiki/Null_object_pattern 
>> <https://en.wikipedia.org/wiki/Null_object_pattern>) respond to #’isNil’? 
>> 
>> And, yes, I’m sure you can come up with benchmarks that show a measurable 
>> difference, but what is the impact in realistic code? When someone asked 
>> about inlining #’yourself’ in GemStone I believe I measured the performance 
>> as taking 2 nanoseconds per call (on a 2012 machine). A 10% speedup would 
>> make it 1.8 nanoseconds. Is that worth it? Maybe, maybe not.
>> 
>> Note that I described my position as a “concern,” not an ideological 
>> objection. Mostly I’m giving a rationale for something that doesn’t seem to 
>> be explained very well for you. I accept that there may be a time for 
>> inlining, but I can “comprehend" another side to the issue.
>> 
>> James
>> 
>>> On Mar 16, 2022, at 9:42 PM, Richard O'Keefe <rao...@gmail.com 
>>> <mailto:rao...@gmail.com>> wrote:
>>> 
>>> We're still not on the same page.
>>> You seem to have some ideological objection to inlining that
>>> I am completely failing to comprehend.
>>> Just because a procedure call (message send) is inlined doesn't
>>> in the least mean it *isn't* a procedure call (message send),
>>> just as compiling a procedure call (message send) as a jump
>>> (last-call optimisation) doesn't mean it *isn't* a procedure
>>> call (message send).
>>> By the way, forget about "40 years ago".
>>> I just did an experiment in Pharo 9, and found that
>>> using "_ ifNotNil: " instead of "_ izNil ifFalse: "
>>> -- where izNil is a non-inlined self == nil --
>>> gave a 10% speedup, in a test code where real work was going
>>> on as well.
>>> As for turning off all inlining, what do you think that would
>>> do to #ifFalse:ifTrue: and its relatives?  
>>> 
>>> 
>>> On Thu, 17 Mar 2022 at 08:34, <s...@clipperadams.com 
>>> <mailto:s...@clipperadams.com>> wrote:
>>> 
>>> 
>>> To start with, why do you CARE whether a particular method is inlined or 
>>> not?
>>> 
>>> I care because it makes “everything is a message” a lie! And I suspect (no 
>>> proof and could be wrong) it’s an optimization that only made sense with 
>>> the hardware constraints of 40+ years ago. Arguing against premature 
>>> optimization is hardly something I just made up ;-)
>>> 
>>> This makes absolutely no sense to me. What makes you think that the 
>>> combination "_ isNil ifFalse: [_]" will NOT be inlined?
>>> 
>>> I may have been unclear. My intent was to communicate: “I’d like to stop 
>>> ALL* inlining of messages by default if possible”
>>> 
>>> *or as many as practical
>>> 
>>> The thing that rings loud alarm bells for me is there being "long chains" 
>>> in the first place.
>>> 
>>> I agree that it is in general a smell, but long chains was tangential to 
>>> the intention above
>>> 
>>> Can you give an example?
>>> 
>>> I don’t know if I can think of one that’s not contrived… Wrapping something 
>>> external? Squeak’s AppleScript support used to mirror the underlying AS, 
>>> which is pretty much exactly that.
>>> 
>>> In my own programming, I've generally found that nils turning up in the 
>>> middle of a chain indicates a serious design error somewhere.
>>> 
>>> Agreed. See smell comment above.
>>> 
>> 
> 

Reply via email to