Login  Register

Re: How can I make this more OOP

Posted by Richard O'Keefe on Sep 15, 2020; 12:58pm
URL: https://forum.world.st/How-can-I-make-this-more-OOP-tp5121729p5121888.html

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 <[hidden email]> 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