Re: Static vs Dynamic

From: Darren (pyedarren_at_hotmail.com)
Date: 10/30/04


Date: 30 Oct 2004 14:25:01 -0700

Matthew Danish <mrd+nospam@cmu.edu> wrote in message news:<87mzy5rozs.fsf@mapcar.org>...
> pyedarren@hotmail.com (Darren) writes:
> > That is where in a statically typed OO language you would have the
> > widget and grommet implement an inteface. Calling "instanceof" for a
> > specialization check like that is not bad OO and still doesn't mean
> > you need casting (though it would be justified if you did).
>
> No, it is bad OO, because it is "outside" of the OO system. This
> reminds me of a presentation on Slate that demonstrated what this means:
> http://tunes.org/~eihrul/talk.pdf (see also http://slate.tunes.org/).

Interesting PDF but far from convincing. The Mainstreem OO example
can't even be qualified as OO in Java. It doesn't leverage the fact
that sharks inherit from fish, nor does it acknowledge/use its own
encapsulation. It then goes on to claim "Mainstream OO is not
expressive enough" and says it has "A Brittle Program Structure".
Those would be interesting claims if the example even approached a
good design. I agree that *that* example is brittle and unexpressive
but *that* example is garbage.

Example:
Shark encounter pseudo code method from the PDF presentation (really
ugly):

method: encounter object
if self has state Healthy
  if object is in class Shark
    then fight object
    otherwise
      if object is in class Fish
        then eat object
  otherwise
    if self has state Injured
      and object is in class Shark
      and object has state Healthy
      then swim away

My Shark's encounter method:

  public void encounter(Fish fish) {
    if (fish instanceof Shark && isHealthy)
      fight((Shark)fish);
    else if (isHealthy)
        eat(fish);
      else
        super.encounter(fish);
  }

Plenty expressive, not brittle, less code and resloves 6 encounter
scenarios for sharks.

"Resolving Ambiguities: Ordering On The Fly"

Hmm...they reinvented what happens naturally in good OO. Notice in my
shark's encounter method, I don't test to see if it is a fish
encounter. Shark's don't worry about fish, they only worry about
other sharks. Sharks also only attack other sharks if they themselves
are healthy. The pseudo code is wasteful and perfoming checks which
should be resolved naturally (on the fly) by it's inheritance from
fish and it's health sate.

Through the same mechanism, my example covers two scenarios more then
the original without any more code:

Other circumstances:
Unhealthy Shark ignores any fish it meets
Unhealthy Shark ignores any unhealthy shark it meets

-------

Implementation notes:

The presentation didn't handle all cases (for any of the examples):
  Undefined if fish encounters fish
  Undefined if unhealthy shark encounters unhealthy shark

Possible logic problem
  If healthy shark fights healthy or unhealthy shark it is
  injured in either case.

Implemented fixes:
defined fish encounters fish
defined fish encounters unhealthy shark

Healthy shark only gets injured if it fights another healthy shark. To
restore original examples logic, remove the following line in void
fight(Shark shark)

    if (shark.isHealthy())

Output from Encounters.java :
-----------------------------------------------
a Fish ignores a Fish.... 1 = 1
a Fish ignores an Unhealthy Shark.... 1 = 1
a Fish swims away from a Healthy Shark.... 1 < 0
an Unhealthy Shark ignores a Fish.... 1 = 1
an Unhealthy Shark ignores an Unhealthy Shark.... 1 = 1
an Unhealthy Shark swims away from a Healthy Shark.... 1 < 0
a Healthy Shark eats a Fish.... 0 < 1
a Healthy Shark fights an Unhealthy Shark.... 0 = 0
a Healthy Shark fights a Healthy Shark.... 0 = 0
------------------------------------------------

------- Encounters.java
public class Encounters {
  public static void main(String[] args) {
    Fish fish = new Fish();
    Fish healthyShark = new Shark(true);
    Fish unhealthyShark = new Shark(false);

    // Fish encounters...
    fish.encounter(new Fish()); // Another fish
    fish.encounter(unhealthyShark);
    fish.encounter(healthyShark);

    // Unhealthy shark encounters...
    unhealthyShark.encounter(fish);
    unhealthyShark.encounter(new Shark(false)); // Another unhealthy
shark
    unhealthyShark.encounter(healthyShark);
    
    // Healthy shark encounters...
    healthyShark.encounter(fish) ;
    healthyShark.encounter(unhealthyShark);
    healthyShark.encounter(new Shark(true)) ;// Another healthy shark
  }
  
  static void explain(String p) { System.out.println(p); }
}

class Fish {
  public void encounter(Fish fish) {
    if (fish instanceof Shark && ((Shark)fish).isHealthy())
      swimaway(fish);
    else
      Encounters.explain(this +" ignores " + fish + ".... 1 = 1");
  }
  
  void swimaway(Fish fish) {
    Encounters.explain(this + " swims away from "+fish +".... 1 < 0");
  }
  
  public String toString() { return "a Fish"; }
}

class Shark extends Fish {
  private boolean isHealthy = true ;
  
  public Shark(boolean healthy) {
    isHealthy = healthy;
  }
  public boolean isHealthy() { return isHealthy; }
  
  public String toString() {
    return (isHealthy ? "a Healthy" : "an Unhealthy")+" Shark";
  }
  
  public void encounter(Fish fish) {
    if (fish instanceof Shark && isHealthy)
          fight((Shark)fish);
    else if (isHealthy)
        eat(fish);
      else
        super.encounter(fish);
  }
  
  void fight(Shark shark) {
    Encounters.explain(this +" fights "+shark + ".... 0 = 0");

    if (shark.isHealthy())
      isHealthy = false;
  }
  
  void eat(Fish fish) {
    Encounters.explain(this +" eats " + fish + ".... 0 < 1");
  }
}
------- End ----
> > I totally agree. That supports the belief that good design transcends
> > language. Good design in Lisp, Java or C++, or any OO language should
> > all be structurally similar, though the details of their
> > implementation might be quite different. That's why design patterns
> > work.
>
> Hah, you just opened up another can of worms! =) Design patterns as
> realized in software architecture today are bull; they are just
> published and accepted ways of working around the limitations of C++
> and Java. There is nothing fundamental about most of them that makes
> them transcend language. Especially since the paradigms of different
> languages really do encourage different solutions to the same problem.

Well, that's a whole other religious debate... Let's not go there ;)



Relevant Pages

  • >>>> SHARK FISH <<<<
    ... Mini Shark Fish ... Diamond Shark Aquarium Fish ... Tropical Fish Tank Sharks ...
    (sci.chem.electrochem)
  • Re: Skate Wings
    ... > Whoever wrote that about shark being served as scallops has never handled ... There's not the remotest possibility of confusing the ... Shark eats like fish. ...
    (rec.food.cooking)
  • Re: Skate Wings
    ... > Whoever wrote that about shark being served as scallops has never handled ... There's not the remotest possibility of confusing the ... Shark eats like fish. ...
    (rec.food.cooking)
  • Re: Skate Wings
    ... >> Whoever wrote that about shark being served as scallops has never handled ... There's not the remotest possibility of confusing the ... Shark eats like fish. ...
    (rec.food.cooking)
  • Re: Wimping out already?!?
    ... >biten by a shark or that other chick was attacked by a jellyfish or that ... >other chick was attacked by a shark..... ... Sorry, Boo, but when I speak of an encounter that could end the show ... The Shark attack could have easily killed him, it wasn't a guppy, it was a shark that latched onto his arm, could have easily burst an artery. ...
    (alt.tv.survivor)