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