SWEA 2025 Weekplan 3

The learning goals for Week 37 are:

Mon: (at 8.15) The Strategy pattern derived. Wed: Refactoring and Integration Testing. Mandatory Reflections. Definitions of Design Patterns.

Literature:

Slides:

Notes for this weekplan:

The UML presentation (W3-3) is one of those boring 'then-there-is-X-and-Y-and-Z' lectures so it is replaced by a screencast. But do not skip it, because it is important and you will use UML a lot for documenting design in your mandatory project ! While rather boring to remember the difference between a dashed and a full line, or the shape of a diamond and which end it should be at, it is vital that you get it right. It makes a huge difference if you say "The ocean is in the fish" but wanted to say "The fish is in the ocean". I see students at the exam describing their designs using incorrect UML ("The PayStation inherits from Receipt" kind of stuff), and it is not good.

Several modern languages avoid implementation inheritance but keeps (aspects) of the essential 'interface' and 'object implements interface' constructs that are essential to the Strategy pattern. If you want to see one way of implementing PayStation's RateStrategy in Go and Rust, you may have a look at my own katas:

  1. paystation.go (GoLang).
  2. paystation.rs (Rust).

Kata

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

The Card and Hero interfaces only have methods to access/read data, not to mutate/write data. The argument is of course that of 'strong encapsulation'---we do not want anyone to cheat by modifying the health value of a card.

To see this, consider the Game method:

        public interface Game {
          Card getCardInField(Player who, int indexInField);
          ...
        }
      

When a client calls:

        Card c = game.getCardInField(Player.FINDUS, 0);
      

... then the returned object is of type Card, and only methods mentioned in the interface Card can be called. Beware you Python folks: Java is radically more insisting here than Python is. (Java is 'strongly typed').

There is, however, a problem, as a HotStone game is all about changing state as the game play progresses---getting that opponent hero's health to zero. That is, the object implementing Game must be able to mutate objects that represents cards and heroes. So - what to do?

We could consider:

  1. Adding mutator methods to the interfaces, ala: public interface Card { int getHealth(); void setHealth(int newValue); // ADDED }
  2. Not changing the interfaces at all, but adding mutator methods only to the implementing class, ala public interface Card { int getHealth(); } public class StandardCard implements Card { int getHealth() { return health; } void setHealth(int newValue) { health = newHealth; } }
    and then let Game declare the instances by the class type, ala
    public class StandardGame implements Game { private StandardCard[][] hand; // Just an example datastructure }
  3. Same as point 2 above, and then let Game declare the instances by the interface type, ala
    public class StandardGame implements Game { private Card[][] hand; // Just an example datastructure }
    and then do casts whenever it is necessary, ala
    StandardCard asStdCard = (StandardCard) card; asStdCard.setHealth(7);
  4. Same as point 3 above, but encapsulate the cast in a private methods, which is used instead of the cast, ala
    StandardCard asStdCard = asStandardCard(card); asStdCard.setHealth(7);

I strongly advice against option 1. Argue why option 1 is a problematic idea.

Next, discuss benefits and liabilities of the other options. (And we will later in the course discuss a fifth option, which solves many of the liabilities of all these options.)

Next, consider mutating the health of a card with either of these two methods:

  1. void setHealth(int newValue); // Set to specific health
  2. void changeHealthBy(int delta); // Add 'delta' to health

The first method will set health to the given value 'newValue'; whereas the second method will add the given delta to the current health value, so you will normally use negative delta values ala
card.changeHealthBy(-2);

Given the specifications and 'feel' of HearthStone which of the two types of methods would you prefer? Argue why.

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.

7.5 7.6 9.1 9.3

Rehearse a TDD exam situation. Spend 20-25 minutes to read and prepare a 10 minute oral presentation of one of the TDD exercises in the example exam question set: demo-question-final-2023.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.