refactoring : primitive obsession - replace conditional with polymorphism

This commit is contained in:
haerong22
2022-04-02 01:50:15 +09:00
parent 13fb80e26e
commit 7f55ac3858
15 changed files with 354 additions and 0 deletions

View File

@@ -0,0 +1,21 @@
package com.example.refactoring._11_primitive_obsession._32_replace_conditional_with_polymorphism.switches;
import java.util.List;
public abstract class Employee {
protected List<String> availableProjects;
public Employee() {
}
public Employee(List<String> availableProjects) {
this.availableProjects = availableProjects;
}
public abstract int vacationHours();
public boolean canAccessTo(String project) {
return this.availableProjects.contains(project);
}
}

View File

@@ -0,0 +1,14 @@
package com.example.refactoring._11_primitive_obsession._32_replace_conditional_with_polymorphism.switches;
public class FullTimeEmployee extends Employee {
@Override
public int vacationHours() {
return 120;
}
@Override
public boolean canAccessTo(String project) {
return true;
}
}

View File

@@ -0,0 +1,16 @@
package com.example.refactoring._11_primitive_obsession._32_replace_conditional_with_polymorphism.switches;
import java.util.List;
public class PartTimeEmployee extends Employee {
public PartTimeEmployee(List<String> availableProjects) {
super(availableProjects);
}
@Override
public int vacationHours() {
return 80;
}
}

View File

@@ -0,0 +1,16 @@
package com.example.refactoring._11_primitive_obsession._32_replace_conditional_with_polymorphism.switches;
import java.util.List;
public class TemporalEmployee extends Employee {
public TemporalEmployee(List<String> availableProjects) {
super(availableProjects);
}
@Override
public int vacationHours() {
return 32;
}
}

View File

@@ -0,0 +1,32 @@
package com.example.refactoring._11_primitive_obsession._32_replace_conditional_with_polymorphism.switches._before;
import java.util.List;
public class Employee {
private String type;
private List<String> availableProjects;
public Employee(String type, List<String> availableProjects) {
this.type = type;
this.availableProjects = availableProjects;
}
public int vacationHours() {
return switch (type) {
case "full-time" -> 120;
case "part-time" -> 80;
case "temporal" -> 32;
default -> 0;
};
}
public boolean canAccessTo(String project) {
return switch (type) {
case "full-time" -> true;
case "part-time", "temporal" -> this.availableProjects.contains(project);
default -> false;
};
}
}

View File

@@ -0,0 +1,35 @@
package com.example.refactoring._11_primitive_obsession._32_replace_conditional_with_polymorphism.variation;
import java.util.List;
public class ChinaExperiencedVoyageRating extends VoyageRating {
public ChinaExperiencedVoyageRating(Voyage voyage, List<VoyageHistory> history) {
super(voyage, history);
}
@Override
protected int captainHistoryRisk() {
int result = super.captainHistoryRisk() - 2;
return Math.max(result, 0);
}
@Override
protected int voyageProfitFactor() {
return super.voyageProfitFactor() + 3;
}
@Override
protected int voyageLengthFactor() {
int result = 0;
result += 3;
if (this.voyage.length() > 12) result += 1;
if (this.voyage.length() > 18) result -= 1;
return result;
}
@Override
protected int historyLengthFactor() {
return this.history.size() > 10 ? 1 : 0;
}
}

View File

@@ -0,0 +1,18 @@
package com.example.refactoring._11_primitive_obsession._32_replace_conditional_with_polymorphism.variation;
import java.util.List;
public class RatingFactory {
public static VoyageRating createRating(Voyage voyage, List<VoyageHistory> history) {
if (voyage.zone().equals("china") && hasChinaHistory(history)) {
return new ChinaExperiencedVoyageRating(voyage, history);
} else {
return new VoyageRating(voyage, history);
}
}
private static boolean hasChinaHistory(List<VoyageHistory> history) {
return history.stream().anyMatch(v -> v.zone().equals("china"));
}
}

View File

@@ -0,0 +1,4 @@
package com.example.refactoring._11_primitive_obsession._32_replace_conditional_with_polymorphism.variation;
public record Voyage(String zone, int length) {
}

View File

@@ -0,0 +1,4 @@
package com.example.refactoring._11_primitive_obsession._32_replace_conditional_with_polymorphism.variation;
public record VoyageHistory(String zone, int profit) {
}

View File

@@ -0,0 +1,57 @@
package com.example.refactoring._11_primitive_obsession._32_replace_conditional_with_polymorphism.variation;
import java.util.List;
public class VoyageRating {
protected Voyage voyage;
protected List<VoyageHistory> history;
public VoyageRating(Voyage voyage, List<VoyageHistory> history) {
this.voyage = voyage;
this.history = history;
}
public char value() {
final int vpf = this.voyageProfitFactor();
final int vr = this.voyageRisk();
final int chr = this.captainHistoryRisk();
return (vpf * 3 > (vr + chr * 2)) ? 'A' : 'B';
}
protected int captainHistoryRisk() {
int result = 1;
if (this.history.size() < 5) result += 4;
result += this.history.stream().filter(v -> v.profit() < 0).count();
return Math.max(result, 0);
}
private int voyageRisk() {
int result = 1;
if (this.voyage.length() > 4) result += 2;
if (this.voyage.length() > 8) result += this.voyage.length() - 8;
if (List.of("china", "east-indies").contains(this.voyage.zone())) result += 4;
return Math.max(result, 0);
}
protected int voyageProfitFactor() {
int result = 2;
if (this.voyage.zone().equals("china")) result += 1;
if (this.voyage.zone().equals("east-indies")) result +=1 ;
result += voyageLengthFactor();
result += historyLengthFactor();
return result;
}
protected int voyageLengthFactor() {
return this.voyage.length() > 14 ? -1 : 0;
}
protected int historyLengthFactor() {
return this.history.size() > 8 ? 1 : 0;
}
}

View File

@@ -0,0 +1,4 @@
package com.example.refactoring._11_primitive_obsession._32_replace_conditional_with_polymorphism.variation._before;
public record Voyage(String zone, int length) {
}

View File

@@ -0,0 +1,4 @@
package com.example.refactoring._11_primitive_obsession._32_replace_conditional_with_polymorphism.variation._before;
public record VoyageHistory(String zone, int profit) {
}

View File

@@ -0,0 +1,62 @@
package com.example.refactoring._11_primitive_obsession._32_replace_conditional_with_polymorphism.variation._before;
import java.util.List;
public class VoyageRating {
private Voyage voyage;
private List<VoyageHistory> history;
public VoyageRating(Voyage voyage, List<VoyageHistory> history) {
this.voyage = voyage;
this.history = history;
}
public char value() {
final int vpf = this.voyageProfitFactor();
final int vr = this.voyageRisk();
final int chr = this.captainHistoryRisk();
return (vpf * 3 > (vr + chr * 2)) ? 'A' : 'B';
}
private int captainHistoryRisk() {
int result = 1;
if (this.history.size() < 5) result += 4;
result += this.history.stream().filter(v -> v.profit() < 0).count();
if (this.voyage.zone().equals("china") && this.hasChinaHistory()) result -= 2;
return Math.max(result, 0);
}
private int voyageRisk() {
int result = 1;
if (this.voyage.length() > 4) result += 2;
if (this.voyage.length() > 8) result += this.voyage.length() - 8;
if (List.of("china", "east-indies").contains(this.voyage.zone())) result += 4;
return Math.max(result, 0);
}
private int voyageProfitFactor() {
int result = 2;
if (this.voyage.zone().equals("china")) result += 1;
if (this.voyage.zone().equals("east-indies")) result +=1 ;
if (this.voyage.zone().equals("china") && this.hasChinaHistory()) {
result += 3;
if (this.history.size() > 10) result += 1;
if (this.voyage.length() > 12) result += 1;
if (this.voyage.length() > 18) result -= 1;
} else {
if (this.history.size() > 8) result +=1 ;
if (this.voyage.length() > 14) result -= 1;
}
return result;
}
private boolean hasChinaHistory() {
return this.history.stream().anyMatch(v -> v.zone().equals("china"));
}
}

View File

@@ -0,0 +1,36 @@
package com.example.refactoring._11_primitive_obsession._32_replace_conditional_with_polymorphism.switches;
import org.junit.jupiter.api.Test;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
class EmployeeTest {
@Test
void fulltime() {
Employee employee = new FullTimeEmployee();
assertEquals(120, employee.vacationHours());
assertTrue(employee.canAccessTo("new project"));
assertTrue(employee.canAccessTo("spring"));
}
@Test
void partime() {
Employee employee = new PartTimeEmployee(List.of("spring", "jpa"));
assertEquals(80, employee.vacationHours());
assertFalse(employee.canAccessTo("new project"));
assertTrue(employee.canAccessTo("spring"));
}
@Test
void temporal() {
Employee employee = new TemporalEmployee(List.of("jpa"));
assertEquals(32, employee.vacationHours());
assertFalse(employee.canAccessTo("new project"));
assertFalse(employee.canAccessTo("spring"));
assertTrue(employee.canAccessTo("jpa"));
}
}

View File

@@ -0,0 +1,31 @@
package com.example.refactoring._11_primitive_obsession._32_replace_conditional_with_polymorphism.variation;
import org.junit.jupiter.api.Test;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertEquals;
class VoyageRatingTest {
@Test
void westIndies() {
VoyageRating voyageRating = RatingFactory.createRating(new Voyage("west-inides", 10),
List.of(new VoyageHistory("east-indies", 5),
new VoyageHistory("west-indies", 15),
new VoyageHistory("china", -2),
new VoyageHistory("west-africa", 7)));
assertEquals('B', voyageRating.value());
}
@Test
void china() {
VoyageRating voyageRating = RatingFactory.createRating(new Voyage("china", 10),
List.of(new VoyageHistory("east-indies", 5),
new VoyageHistory("west-indies", 15),
new VoyageHistory("china", -2),
new VoyageHistory("west-africa", 7)));
assertEquals('A', voyageRating.value());
}
}