Hi richard

Thanks for the mail. 
I would go for the solution 2. 

1) Put the test code *inside* the class under test as an extension.
Have the test code in the image only when testing.
(2) Add the access-to-private-details methods in an extension,
included in the image only when testing.
(3) What the authors did: reveal all the implementation details to all the world
all the time.

> On 30 Jun 2025, at 06:22, Richard O'Keefe <rao...@gmail.com> wrote:
> 
> Ah, the astc copy you found is years out of date.
> And the deque.st you found has had several mistakes fixed since.
> 
> Here's why it mattered to me that these data structures weren't Collections.
> 
> I was writing my own testing and benchmarking code to explore these ones.
> They have #isEmpty, so naturally I used both #isEmpty and #notEmpty in my 
> tests.
> Not collections, so #notEmpty isn't there.
> They have #do:.  They don't have #print:, so I threw together some printing 
> code
> using the conventional #do:separatedBy:.
> Not collections, so #do:separatedBy: isn't there.
> Throw in a few non-nil elements, check [b noneSatisfy: [:each | each
> isNil]] assert.
> Not collections, so #noneSatisfy: isn't there.
> Tried to preload a buffer with specified contents using #withAll:.
> Not a collection, so #withAll: isn't there.
> Tried to compare the result of a series of operations with the expected one.
> Not a collection, so #asArray isn't there.
> 
> Now Collection is big.
> Collection selectors size ==> 201
> Collection allSelectors size ==> 692
> in Pharo 12.
> Collection selectors size ==> 403
> Collection allSelectors size ==> 1091
> in astc with everything included, including compatibility packages,
> and a lot of the methods in Collection don't make sense for all descendants.
> I've tried very very hard to reduce this in astc, so my Collection
> doesn't include #+ .
> 
> Basically, in order to be a "good faith" Collection in astc, you have
> to be able to
> to #do: multiple times without changing the multiset of items reported and you
> have to report #size consistent with this.
> 
> I finally understood why these buffers expose all their implementation 
> details,
> and there is arguably an excellent reason for it.  There is a question
> I would like
> advice about, and that's the best way (in Pharo) to accomplish the same 
> purpose
> without exposing the implementation.
> 
> Here's the reason.  I think of unit tests as testing the externally
> visible behaviour
> of an object, so that unit tests should only use the public interface
> of the objects
> they're working with.  One reason for this is that I want to be able
> to change the
> internal details completely without changing the tests.  For example,
> another way
> to implement a deque is using a doubly linked list, and there's no
> reason that it
> couldn't be bounded, so a *FIFOBuffer might not *have* an elements array or
> a readIndex integer, and making such a change leaves the unit tests
> still useful.
> Well and good: there is *A* category of tests that can and should be 
> restricted
> to the public interface.
> 
> But the authors of these buffers went further.  They decided to test that the
> operations do the right thing the right *way* and created further
> tests that check
> the internal state of a buffer after an operation.  To do this, they
> need *access*
> to the internal state.
> 
> It seems to me that there are three ways to do this.
> (1) Put the test code *inside* the class under test as an extension.
> Have the test code in the image only when testing.
> (2) Add the access-to-private-details methods in an extension,
> included in the image only when testing.
> (3) What the authors did: reveal all the implementation details to all the 
> world
> all the time.
> A fourth theoretical possibility, providing the
> access-to-private-details methods
> to the test class(es) only, is easy in Eiffel but appears to be
> impossible in Smalltalk.
> 
> At this point a confession is appropriate.  While testing and benchmarking 
> their
> code, I found a discrepancy between their results and mine, and it was MY code
> that was broken.  (I had tested Deque, but didn't really care about 
> BoundedDeque
> very much, so hadn't tested it very thoroughly.)  My bug *was* revealed by a
> conventional public-interface-only test, but it would have been revealed 
> quicker
> by a test-the-implementation test like theirs.  So I doff my hat to
> the authors for
> their thoroughness.
> 
> GIVEN then that testing the implementation as well as the interface is
> a good idea,
> which of the 3 approaches above is recommended?  Is there a still better way?
> 
> 
> On Sun, 29 Jun 2025 at 16:18, stephane ducasse
> <stephane.duca...@inria.fr> wrote:
>> 
>> Hi richard
>> 
>> BTW guille found your prolog bookon second hand :)
>> 
>> My own Smalltalk library (and yes, I've tried to put it on github, I
>> don't know what I'm doing wrong)
>> 
>> 
>> If you want we can get with it. Just ask and we can do a videos sessions 
>> with zoom,m webex, team or whatever software.
>> 
>> includes Deque and BoundedDeque, both descendants of Collection.
>> Using addLast/removeLast gives you a stack (use #last for peeking)
>> Using addLast/removeFirst gives you a queue. (use #first for peeking)
>> 
>> 
>> I have found on my disc astc-1711 but I could not find them.
>> Can you send us the files?
>> 
>> 
>> (1) I am puzzled why there are separate FIFO and LIFO classes rather
>> than a single BoundedDeque.
>>    -- This has implications for performance.
>> (2) I am puzzled why #withCapacity: is used rather than #new:,
>> familiar from OrderedCollection.
>> 
>> 
>> Good point
>> 
>>   -- These two points together make it hard to just swap
>> OrderedCollection and ?IFOBuffer.
>> 
>> 
>> (3) I am puzzled why #clear is used instead of the familiar #removeAll.
>>   -- See note on question 2.
>> 
>> 
>> Good point this is nice for API with Collection.
>> 
>> (4) I am extremely puzzled why ALL, like ALL, of the internals of the
>> data structure are exposed.
>>   Did encapsulation fall out of favour and I didn't get the memo?
>> (5) It looks as though calling #capacity: at the wrong time can
>> destroy the integrity of one of
>>    these containers, but there is nothing sayiing "don't do that".
>> (6) I am puzzled that they are not Collections.
>> 
>> 
>> What do you mean.
>> If this is that they do not inherit from Collection I can understand because 
>> the API of collection is large.
>> Now Alok it would be good to look at ANSI and see a bit the protocol
>> I attach ANSI
>> 
>> (7) I am puzzled why trying to access an element in an empty buffer
>> does not signal
>>   a CollectionIsEmpty exception
>>   -- Is this related to (6)?
>> 
>> The structure, with two separate classes and key performance-essential
>> methods being
>> template methods, hurts performance by about a factor of two in my tests.
>> 
>> Now Pharo has a design MOOC and if Stephane Ducasse says "this is
>> great", these things
>> that puzzle me must be good design.  I would like to improve my
>> skills, so *why* is this good design?
>> (As it happens, I *have* had occasion to 'push' from both ends of a
>> single Deque.)
>> 
>> 
>> I say great because any effort is good, Then we can discuss.
>> I’m currently running a summerschool in parallel to prepare several talks to 
>> ESUG and
>> finishing the organisation and reviewing other code and more. :)
>> 
>> 
>> None of this is meant as criticism of the generosity or competence of
>> the authors.  It expresses
>> genuine puzzlement.  Like when I implemented deques I could not
>> imagine not making them
>> Collections.  Principle of Least Surprise and all that.  Maybe I
>> should be thinking differently.
>> 
>> 
>> On Fri, 27 Jun 2025 at 20:10, stephane ducasse via Pharo-users
>> <pharo-users@lists.pharo.org> wrote:
>> 
>> 
>> Thanks this is great!
>> 
>> On 18 Jun 2025, at 12:13, Alok via Pharo-users <pharo-users@lists.pharo.org> 
>> wrote:
>> 
>> Hello Everyone,
>> We're excited to share a new addition to the pharo-containers. An efficient 
>> Circular Buffer implementation, developed as part of Google Summer of Code 
>> 2025 project under the mentorship of Gordana Rakic and Sebastian Jordan 
>> Montaño.
>> 
>> This package provides fixed-size buffers supporting both FIFO (queue-style) 
>> and LIFO (stack-style) behavior. It’s designed for use cases such as 
>> streaming data, undo/redo functionality, chat or browser history & more.
>> 
>> You can find the repo here: Containers-Buffer
>> The README includes usage examples, installation steps etc.
>> 
>> Feedback, suggestions, and contributions are very welcome !
>> ThankYou !
>> Alok Pathak
>> GSoC'25 Contributor
>> 
>> 
>> Stéphane Ducasse
>> http://stephane.ducasse.free.fr
>> 06 30 93 66 73
>> 
>> "If you knew today was your last day on earth, what would you do 
>> differently? ....ESPECIALLY if, by doing something different, today might 
>> not be your last day on earth.” Calvin & Hobbes
>> 
>> 
>> 
>> 
>> 
>> 
>> Stéphane Ducasse
>> http://stephane.ducasse.free.fr
>> 06 30 93 66 73
>> 
>> "If you knew today was your last day on earth, what would you do 
>> differently? ....ESPECIALLY if, by doing something different, today might 
>> not be your last day on earth.” Calvin & Hobbes
>> 
>> 
>> 
>> 
>> 

Stéphane Ducasse
http://stephane.ducasse.free.fr
06 30 93 66 73

"If you knew today was your last day on earth, what would you do differently? 
....ESPECIALLY if, by doing something different, today might not be your last 
day on earth.” Calvin & Hobbes





Reply via email to