> On 14 Sep 2020, at 16:02, Roelof Wobben via Pharo-users > <pharo-users@lists.pharo.org> wrote: > > > Thanks Richard for this explanation. > and I like also your idea of using #respondTo instead of asking a object if > its a collection or a item.
refrain from using respondTo: I make code difficult to evolve and can introduce vicious bugs. S. > Roelof > > > Op 14-9-2020 om 14:28 schreef Richard O'Keefe: >> "OOP is not asking an object what it is"? You've lost me. >> I'm reminded of a joke exam question that goes something >> like this: >> Some things have ping nature and other things have pong nature. >> Discuss, with examples. >> >> Whatever else it is, OOP is a means to an end, not an end in itself. >> It's not a religion. Allah will not cast you into the Fire for using >> something which is not ritually pure. >> >> The whole point of the Design Patterns movement was not to present >> canned solutions but to describe common *situations* characterised >> by (metaphorical) *forces* pushing you in incompatible directions. >> >> Question 1: Why do you even have a stream there? >> flattenArray: aCollection >> |buffer| >> buffer := OrderedCollection new: aCollection size. >> self flattenArray: aCollection into: buffer. >> ^buffer asArray >> >> flattenArray: anObject into: buffer >> (anObject respondsTo: #do:) >> ifTrue: [anObject do: [:each | self flattenArray: each into: buffer] >> ifFalse: [anObject ifNotNil: [buffer addLast: anObject]. >> >> (CAUTION: untested code.) >> >> Question 2: is there any point in *trying* to make this more ping and less >> pong? >> I have to say that in 40 years of programming, I have *never* wanted to >> flatten >> a completely arbitrary structure. When I have wanted to flatten something, >> it >> has always been an instance of the Composite design pattern, so that a >> specific >> and quite small set of classes has been involved. >> >> I am well aware that some Smalltalk systems have some sort of 'flatten' >> lying around like a rake in the grass, but I have found no two which agree >> on the specification. >> >> Question 3: Let's consider an if-less alternative. >> >> Stream >> flattenInto: buffer >> self do: [:each| each flattenInto: buffer]. >> >> Collection >> flattenInto: buffer >> self do:[:each | each flattenInto: buffer]. >> >> Object >> flattenInto: buffer >> buffer addLast: self. >> >> UndefinedObject >> flattenInto: buffer >> "Do nothing." >> >> This is Smalltalk, where we *can* add methods to system classes like these. >> When the payoff is worth it, I have no qualms whatever in doing so. >> But putting methods of little or no utility into the interface of EVERY >> object just feels so wrong. >> >> Here we have opposing forces: >> - The first approach adds two methods to your worker class, >> and no methods to any system class. Instead, it uses >> "does this object know how to iterate over its elements?" >> and "is this object nil?". This does minimal damage to >> system structure at the price of a little ritual impurity. >> >> - The second approach adds a method to four system classes, >> enlarging the interface of every object in the system, >> creating a level of coupling we'd be better without, and >> making it harder for someone reading your code to figure >> out what's going on. >> >> In the context of a Composite, with a limited number of >> application classes involved, the second approach is better; >> the method is/methods are not defined anywhere they should >> not be. >> >> In the context of *this* problem, the first approach is >> better. MUCH better. Why? Because *encapsulation* is much >> more important to OOP than absence-of-IFs. >> >> On Sun, 13 Sep 2020 at 21:26, Roelof Wobben via Pharo-users >> <pharo-users@lists.pharo.org <mailto:pharo-users@lists.pharo.org>> wrote: >> Hello, >> >> I know that OOP is not asking a object what it is but I have to flatten a >> array so I did this : >> >> flattenArray: aCollection >> ^ (OrderedCollection >> streamContents: [ :stream | self flatten: aCollection into: stream ]) >> asArray >> >> flatten: anObject into: result >> ^ anObject isCollection >> ifTrue: [ anObject do: [ :item | self flatten: item into: result ] ] >> ifFalse: [ anObject ifNotNil: [ result nextPut: anObject ] ] >> >> The name flattenArray is given bij exercism. >> >> Now I wonder how I can make this more a OOP solution. >> >> Can someone give me some hints or some examples ? >> >> Roelof >> > -------------------------------------------- Stéphane Ducasse http://stephane.ducasse.free.fr / http://www.pharo.org 03 59 35 87 52 Assistant: Aurore Dalle FAX 03 59 57 78 50 TEL 03 59 35 86 16 S. Ducasse - Inria 40, avenue Halley, Parc Scientifique de la Haute Borne, Bât.A, Park Plaza Villeneuve d'Ascq 59650 France