5: Refactoring

For this homework consult the lecture notes; only the refactorings listed there are targets for the questions below.

  1. (24 points) Individual refactorings may not easily work due to problems introduced by the code motion implied in the refactoring. For the following refactorings give a concrete code example where the refactoring fails: the indicated refactoring is close to being applicable but some variable scoping or other constraint causes it to fail. You are welcome to take the code examples at refactoring.guru and break them, i.e. modify them to make the refactoring fail. Please give Java code for this question.
    1. Replace Temp With Query
    2. Extract Class
    3. Move Method
    4. Replace Inheritance With Delegation
    5. Replace Conditional With Polymorphism
    6. Replace Parameter With Method Call
    7. Collapse Hierarchy
    8. Introduce Parameter Object
  2. (15 points) For this question, imagine refactorings could talk, and list which refactoring(s) could be saying the indicated thing. Each question has one or more answers, you need to get all the applicable ones not just one.
    1. I help you get rid of switch statements.
    2. I will add more delegation to your code
    3. I aim to improve the clarity of the interfaces and encapsulation of your code
    4. I aim to make your code more directly readable (like English)
    5. I have an inverse refactoring which un-does me
    6. I have something to do with inheritance
  3. (30 Points) For each code snippet below, name the refactoring that will improve the code.
    1. public int getSpeedFor(Enemy enemy) {
          int speed;
          if (enemy.getType() == Enemy.TYPE_DRAUGR) {
              speed = 6;
          } else if (enemy.getType() == Enemy.TYPE_BANSHEE) {
              speed = 15;
          } else if (enemy.getType() == Enemy.TYPE_WENDIGO) {
              speed = 10;
          } else {
              throw new IllegalStateException("Bad enemy type code");
          }
          return speed;
      }
                          
    2. public int foo(boolean cond, int a, int b) {
      	boolean answer = not(cond);
      	if (answer) {
      		return a;
      	} else {
      		return b;
      	}
      }
      
      private boolean not(boolean b) {
      	if (b==true)
      		return false;
      	else
      		return true;
      }
      	
    3. class Cat {
      	private String name;
      	private Color furColor;
      	// assume appropriate getters and setters here
      	public void feed(CatFood food) { ... }; // assume some method body for ...
      	public void nap(double hours) { ... };
      ]			
      
      class CatOwner extends Cat {
      	private String ownerName;
      	// assume appropriate getters and setters here
      	public void petCat() { ... };
      	public void trainCat(Task task) throws TrainFailureException {
      		throw new TrainFailureException("It's a cat.");
      	}
      }
      
      // for example, we cause the owner to feed the cat by calling
      //     catOwner.feed(someCatFood);
      			
    4. public class ItemRepository {
          ...
          public List<Item> searchSaleItems(int minRating, int maxRating, double minPrice, double maxPrice,
                   int minBulkAmount, int maxBulkAmount, double minDiscountPercentage, double maxDiscountPercentage) { ... }
          public List<Item> searchItems(int minRating, int maxRating, double minPrice, double maxPrice) { ... }
          ...
      }
                          
    5. public class DataTool {
          private byte bits;
          private byte[] bytes;
          /* *** assume getters and setters for bits and bytes *** */
          public void rollBitsLeft(int n) {
              this.bits = (this.bits << n) | (this.bits >>> (8-n));
          }
          public void xorBytes(byte x) {
              for (int i=0;i<bytes.length;i++) {
                  bytes[i] ^= x;
              }
          }
          public int countBitsOn() {
              byte it = bits;
              int acc = 0;
              for (int i=0;i<8;i++) {
                  acc += (it & 0x01);
                  it >>>= 1;
              }
              return acc;
          }
      }
                          
    6. public class PriceCalculator {
          private List<Item> items;
          ...
          public double getTotalPrice() {
              double subtotal = 0;
              for (Item item : items) {
                  subtotal += item.getPrice();
              }
              final double total = (Math.max(5.00, subtotal)) * 1.06 + 2.95;
              final double discounted = total - total * (subtotal >= 50.00 ? 0.2 : 0.1);
              return discounted;
          }
      }