4: Design Principles

In lecture, we discussed a number of software principles, including Encapsulate what varies, the God Class anti-pattern, DRY, LSP, OCP, and SRP. Identify in each of the following cases which if any of these principles are violated (or in the case of God Class, matches) and if so, (a) justify your reasoning as to why that principle applies in a sentence or two, and (b) outline how the code can be corrected. Note: in some cases, there may be more than one principle violated. In that case, explain each one; but, don't identify a design principle without good cause. (For more on the design principles refer to the lecture notes and Chapter 8 of HFOOA&D).
  1. (10 points)

    Code from part of a hypothetical collection library:

    /* A generic interface for collections */
    interface Collection<T>
    {
        public void add(T v);
        public void remove(T v);
        public int count(T v);
    }
    
    /* Multisets can hold more than one instance of a value */
    class MyMultiSet<T> implements Collection<T>
    {
       private List<T> data;
       public MyMultiSet() {
           data = new LinkedList<T>();
       }
       public void add(T v) {
           data.add(v);
       }
       public void remove(T v) {
           data.remove(v); //Removes the first element equal to v
       }
       public int count(T v) {
           int c = 0;
           for(T i : data) {
               if (v.equals(i)) c++ ;
           }
           return c;
       }
    }
    
    /* Sets on the other hand only a single instance of a value */
    class Set<T> extends MyMultiSet<T>
    {
       public void add(T v) {
           if (count(v) == 0) {
               super.add(v);    
           }
       }
    }
    
  2. (10 points)

    A snippet from a terminal version of Hare and Hounds

    class Game {
        private Piece[][] board;
        public void move() {
            /* Read user input */
            Point source = readCoordinateFromInput();
            Point dest = readCoordinateFromInput();
            /* Does the source square have a piece? Is the desination empty? */
            if (board[source.x][source.y] == null || board[dest.x][dest.y] != null)
                throw new IllegalMoveException();
            /* ... More rules here .. */
            /* Print out the current state of the board */
            printBoard();
        }
    
        private Point readCoordinateFromInput() {
            /* Read input from the terminal and convert to a point */
        }
        private void printBoard() {
            /* Printing code here */
        }
    }
    
  3. (10 points)

    Some code for a standalone weather station

    class WeatherStation {
        /* ... */
        void updateDisplay () {
    	int tenTemps = 0;
    	float tenDirections = 0.0;
    	/* implemented temp and wind direction so far, 
               still have windspeed, barometer, rainfall to go */	
          for(int i=0; i<10; i++){
             tenTemps = tenTemps + sensor.getCurrentTemp();
    	 tenDirections = tenDirections + sensor.getCurrentWindSpeed();
    	 TimeUnit.SECONDS.sleep(1); // ten readings to average
          }
          int aveTemp = tenTemps / 10;
          float aveDirection = tenDirections / 10;
          display.setTemp(aveTemp);
          display.setDirection(aveDirection);
        }
    
  4. (10 points)

    A snippet of code from a hypothetical hack-and-slash game:

    public class Player 
    {
        private int weaponType;
        public void attack(Monster target) {
            switch(weaponType) {
                case SWORD:
                    slashWithSword(target);
                    break;
                case SPEAR:
                    pokeWithSpear(target);
                    break;
                /* Cases for other weapons here */
            }
        }
        public void slashWithSword(Monster target) {
            int swordDamage;
            /* Do some work here to compute the damage */
            target.addDamage(swordDamage);
        }
        public void pokeWithSpear(Monster target) {
            int spearDamage;
            /* Do some work here to compute the damage */
            target.addDamage(spearDamage);
        }
        /* Other code and definitions here */
    }
    
  5. (10 points)

    A snippet from a HareAndHounds game

    class Game {
        /* Other code and definitions here */
        private void canMoveBetween(Point src, Point dest) {
            Piece piece = getPieceAt(src);
            /* Check if we are moving along a valid edge. Also ensure that hounds cannot move backwards */
            if (src.x == 0 && src.y == 1 && dest.x == 1 && dest.y == 0 && getPieceAt(dest) == null) {
                /* Code to move the piece to the new position */
            } else if (src.x == 1 && src.y == 0 && dest.x == 0 && dest.y == 1
                       && piece != null && piece.getPieceType() != PieceType.HOUND) {
                /* Code to move the piece to the new position */
            } else if (src.x == 0 && src.y == 1 && dest.x == 1 && dest.y == 2 && getPieceAt(dest) == null) {
                /* Code to move the piece to the new position */
            }
            /* More else-if conditions here */
        }
        private Piece getPieceAt(Point pt) {
            /* Code here to return the piece at the given position. Returns null
               if none exist */
        }
    }