SWEA 2025 Weekplan 6

The learning goals for Week 40 are:

Mon: Interface Segregation Principle. Private Interfaces. Test Spy revisited. Wed: Theory of roles, responsibility, and protocol. Principles of compositional design. Multi-dimensional variance.

Literature:

Slides:

Notes for this weekplan:

Monday lecture (at 9.15) will cover the ISP and revisit a nice way to use private interfaces to do Unit Testing even if our strategies needs to modify state in our Game object. The topics covered are thus essential for proper solving the mandatory.

Wednesday will be more theoretical discussing the Role concept in great depth and the compositional design principles.

Kata

Spend the first 15-20 minutes of the TØ/Lab class in plenum discussing...

... Test Stub for Random Minion

A SWEA group which did not follow the Test First principle came up with an implementation of the RedWine hero power (which lacks the ISO 9126 Testability capability (FRS §3)):

public class RedWinePowerStrategy implements HeroPowerStrategy {
  @Override
  public void executeEffect(StandardGame game) {
    // Get the size of the field of the opponent
    Player opponent = Player.computeOpponent(game.getPlayerInTurn());
    int opponentFieldSize = game.getFieldSize(opponent);
    // Compute a random index in range 0..opponentFieldSize-1
    int index = (int) (Math.random() * opponentFieldSize);
    // Tell game to reduce health of that minion by two
    game.changeCardHealth(opponent, index, -2);
  }
}
        

Of course, their TA was not happy (nor was the lecturere) as there is no automated testing possible: The random 'index' is indirect input from the Java random library, and writing a reproducible test case impossible (or at least cumbersome and not aligned with the Evident Test principle.) We need a test stub!

They came up with this bad design for a test stub: They copied the above code into a new "stub" class:

public class RedWinePowerSTUBStrategy implements HeroPowerStrategy {
  private final int whichIndexToApplyEffectOn;

  public RedWinePowerSTUBStrategy(int whichIndexToApplyEffectOn) {
    this.whichIndexToApplyEffectOn = whichIndexToApplyEffectOn;
  }

  @Override
  public void executeEffect(StandardGame game) {
    // Get the size of the field of the opponent
    Player opponent = Player.computeOpponent(game.getPlayerInTurn());
    int opponentFieldSize = game.getFieldSize(opponent);
    // STUB the random generation
    int index = whichIndexToApplyEffectOn;
    // Tell game to reduce health of that minion by two
    game.changeCardHealth(opponent, index, -2);
  }
}        
        
which was then used to write a reproducible/deterministic test case ala this one:
@Test
  public void shouldApplyRedWineToMinionAtIndex0() {
    // Given a game
    StandardGame game = new StandardGame();
    // Given the stub for the RedWinePowerStrategy which
    // always applies the effect to the minion at index 0
    HeroPowerStrategy redwine = new RedWinePowerSTUBStrategy(0);
    // When I apply the effect
    redwine.executeEffect(game);
    // Then the minion at index 0 has health reduced by 2
    [... the proper assertThat here]
  }          
        

Analyze and discuss the above design proposal

  1. Does it adhere to the (3) principle Encapsulate what varies?
  2. The 'generate a random index' variability point is handled by which of our four variability techniques (source-code-copy; parametric; polymorhpic; compositional)?
  3. At a later point in time, a maintainer accidentially changes the line in RedWinePowerStrategy (that is, not in the RedWinePowerSTUBStrategy) from the correct one:
      game.changeCardHealth(opponent, index, -2);
                
    to
      game.changeCardHealth(opponent, index, +2);
                
    Will our automated JUnit tests fail?
  4. I called it a bad design above, which is rather subjective. To rephrase it in more correct and objective turns, what ISO 9126 capability (FRS §3) is it lacking? Analyzability? Changeability? Stability? Testability?

Discuss (and implement in you HotStone system) a better design.

Optional Exercises:

These are optional exercises. Be sure to solve the mandatory project first, and only if you have a lot of spare time, try having a look at the exercises below.

16.5 17.5 18.4 19.6

Rehearse a test stub exam situation using an exercise in the example exam question set: demo-question-2025.pdf.

Next, do a 10 minute presentation at the whiteboard in front of your team.

The team provides constructive feedback on the presentation: Is your presentation clear and understandable, do you discuss the concepts and terms correctly, is you Java example code correct, etc. Swap and ensure all in the team gets a chance to rehearse the situation.