Re: Test Driven Development Sample

From: Paul Sinnett (paul.sinnett_at_btinternet.com)
Date: 12/16/03


Date: Tue, 16 Dec 2003 14:42:49 +0000

Isaac Gouy:
> Paul Sinnett:
>
> There's a library call and we can use an anonymous function to define
> the test criteria.
>
> void addScore(int pinsKnockedDown){
> q.add(pinsKnockedDown);
>
> while (frameScorers[0].isScorable(q) && frames<=10){
> let s = frameScorers.search(Scorer each => each.canScore(q));
> if (s != null){
> total += s.score(q) + s.bonus(q);
> s.next(q);
> frames++;
> totalScore(total);
> }
> }
> }

That's cool. But why?:

   if (s != null){
      ...
   }

The condition frameScorers[0].isScorable(q) prevents s from being null. That
suggests that they are doing some of the same job to me. If
Scorer::canScore took on the additional checks in SK::isScorable we could
simplify the loop:

   while (frames<=10){
      let s = frameScorers.search(Scorer each => each.canScore(q));
      if (s != null){
         total += s.score(q) + s.bonus(q);
         s.next(q);
         frames++;
         totalScore(total);
      }
      else{
         break;
      }
   }

or:

   while (frames<=10){
      let s = frameScorers.search(Scorer each => each.canScore(q));
      if (s == null) break;
      total += s.score(q) + s.bonus(q);
      s.next(q);
      frames++;
      totalScore(total);
   }

Looking again at SK::isScorable what do the numbers 2 and 3 refer to?

> boolean isScorable(ArrayList<int> q) =
> q.size==3 || (q.size==2 && q[0] + q[1] < 10);

I recognise q[0]+q[1]<10, it's the old isOpen check. The q.size==3 side of
the conditional logic could include the opposite, then we'd have:

   boolean isScorable(ArrayList<int> q) =
      (q.size==3 && !this.isOpen) || (q.size==2 && this.isOpen);

and !isOpen could be written isMark where:

   boolean isMark() = this.isStrike || this.isSpare;

so we could expand it out to:

   boolean isScorable(ArrayList<int> q) =
      (q.size==3 && this.isStrike) ||
      (q.size==3 && this.isSpare) ||
      (q.size==2 && this.isOpen);

and since each Scorer subclass has it's own canScore function we could split
these checks out to those:

class Strike extends Scorer {
   canScore(ArrayList q) =
      q.size==3 && q[0] == 10;
   ...
}

class Spare extends Scorer {
   canScore(ArrayList q) =
      q.size==3 && q[0] != 10 && q[0] + q[1] == 10;
   ...
}

class Open extends Scorer {
   canScore(ArrayList q) =
      q.size==2 && q[0] + q[1] < 10;
   ...
}



Relevant Pages

  • Re: Test Driven Development Sample
    ... void addScore{ ... class Strike extends Scorer { ... class Spare extends Scorer { ... class Open extends Scorer { ...
    (comp.object)
  • Re: Test Driven Development Sample
    ... > Now we can clearly see the duplication that was hidden in the earlier ... void addScore{ ... class Strike extends Scorer { ... class Open extends Scorer { ...
    (comp.object)