I take Sean's point. However, while I agree that practising using polymorphism instead of 'if' is a good idea, I don't think that *this* exercise is a good one for getting such practice. Roelof is going through the Pharo track of Exercism. This particular one is called 'flatten-array'. The one concession to "hey, this is Pharo!" in the description of the exercise is a veiled warning against using Pharo's #flattened/#flattenOn:, which (a) does not add anything to Object or UndefinedObject (just Collection>>flattened and Collection>>flattenOn:) (b) does not make a special case of nil (c) DOES make a special case of strings, treating them as atomic. Possibly the most challenging part for me in this exercise was trying to figure out "what does <list> mean for Smalltalk here?" In Pharo's existing #flattened, why does a String count as atomic but a Semphore is just another collection? This is a Lisp programming exercise from the early 1960s. It had unpleasant ambiguities back then and it has not got better since. If this were rewritten as "Make a Composite implementation of binary search trees with a class for empty trees, a class for non-empty ones, and perhaps a class for singleton ones. Implement #do:, traversing the elements in increasing order. Use this to implement #asOrderedCollection." then that *would* be a good exercise for using polymorphism instead of conditionals. BST () asOrderedCollection ^OrderedCollection new in: [:coll | self do: [:each | coll addLast: each]. coll] EmptyBST () do: aBlock "Nothing to do." NonemptyBST (less key greater) do: aBlock less do: aBlock. aBlock value: key. greater do: aBlock. On Tue, 15 Sep 2020 at 18:33, Sean P. DeNigris <sean@clipperadams.com> wrote:
Richard O'Keefe wrote
Whatever else it is, OOP is a means to an end, not an end in itself. It's not a religion.
Richard makes an important point here.
As I mentioned on Discord (slightly edited to fit this thread), itâs a judgment call with trade-offs, but for the purposes of an OOP exercise, I would say absolutely put the methods in object and wherever else you may need them - if only to get practice with that particular idiom. I needed to do a lot of that sort of thing - probably way *too* much, just to break my procedural thinking habits. Once I got it "in my bones" I became more pragmatic. While in theory, this may always be the âmostâ OOP way, in practice it can be confusing due to the limitations of our system organization and the fact that people will have to scroll through more methods on kernel objects (not to mention the extra dependencies Richard noted). That is the dogma, and I think is a fine answer for an OOP exercise, but IMHO in practice there are justifiable exceptions. The two major axes are understandability and adaptability. If in your domain there are only two choices and there can not logically be more, it may be easier to understand one method with a conditional that documents that domain fact, than it would be to dive down a polymorphism rabbit hole spread across the system. Of course, tooling is a big factor in understandability. In GT it may be trivial because you can open implementors in a plane right next to the code browser. Different toolsets themselves mean different trade offs. There are no one size fits all answers for all time. There are principles that have to be negotiated with your current environment, use case, experience level, team size...
----- Cheers, Sean -- Sent from: http://forum.world.st/Pharo-Smalltalk-Users-f1310670.html