├── .gitignore ├── README.md ├── pom.xml └── src ├── main └── java │ └── algorithm │ ├── F.java │ ├── FT.java │ ├── Finder.java │ └── Thing.java └── test └── java └── test └── FinderTests.java /.gitignore: -------------------------------------------------------------------------------- 1 | .classpath 2 | .project 3 | .settings/ 4 | bin/ 5 | target 6 | 7 | .idea 8 | *.iml 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | Here is the bad news: the new developer you hired has written some terrible, atrocious code. 4 | No one can understand what it does. 5 | 6 | The good news: at least there are unit tests to prove the code is working. 7 | 8 | You job is to refactor the code and make it readable, while keeping the code in working order (pass all tests). 9 | 10 | # How To Start 11 | 12 | 1. Clone this repository `git clone https://github.com/DoDevJutsu/incomprehensible-finder-refactoring-java.git` 13 | 2. Install all the dependencies using Maven. 14 | 3. Run the tests. 15 | 4. Start refactoring! 16 | 17 | The primary goal is to refactor the code in `Finder.java` - as it stands the code is incomprehensible. 18 | 19 | # Tips 20 | 21 | * Start with simple rename refactors so you can better understand the abstractions you are working with. Rename any class or any variable. 22 | * Move on to extract methods and making the code more modular. 23 | * See if you can also eliminate switch statements and multiple exit points from methods. 24 | 25 | Anything is fair game, create new classes, new methods, and rename tests. 26 | The only restriction is that the existing tests have to keep working. 27 | Lean on the tests and run them after every small change to make sure you are on the right path. 28 | 29 | # How to End 30 | 31 | You can stop when you feel the code is good enough, something you can come back to in 6 months and understand. 32 | 33 | # Helpful resources 34 | 35 | ## Refactoring 36 | 37 | * [Martin Fowler Refactorings catalog](http://refactoring.com/catalog/) 38 | * [Refactoring.guru Code Smells catalog](https://refactoring.guru/smells/smells) 39 | * [Refactoring.guru Refactorings catalog](https://refactoring.guru/catalog) 40 | * [CodelyTV Refactoring videos (Spanish)](http://codely.tv/tag/refactoring/) 41 | 42 | # Credits and other programming languages 43 | 44 | This kata is a Java port of the original Incomprehensible Finder Refactoring Kata created by [K. Scott Allen](https://github.com/OdeToCode) and ported by [Tom Cammann](https://github.com/takac). 45 | You can also find [the kata in C#](https://github.com/DoDevJutsu/incomprehensible-finder-refactoring-c-sharp) and [in Php](https://github.com/CodelyTV/incomprehensible-finder-refactoring-kata). 46 | 47 | We put the original Java version in an independent repository in order to make it more easily available for the [Software Craftsmanship Barcelona Coding Dojo session](http://www.meetup.com/Barcelona-Software-Craftsmanship/events/233107734/). 48 | Come with us and have some fun if you're near Barcelona the next Monday, August 22nd! 49 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | algorithm 6 | refactoring 7 | 0.4 8 | jar 9 | 10 | Refactoring Java 11 | 12 | UTF-8 13 | 14 | 15 | 16 | 17 | junit 18 | junit 19 | 4.8.1 20 | test 21 | 22 | 23 | 24 | 25 | 26 | org.apache.maven.plugins 27 | maven-compiler-plugin 28 | 29 | 1.6 30 | 1.6 31 | true 32 | true 33 | true 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /src/main/java/algorithm/F.java: -------------------------------------------------------------------------------- 1 | package algorithm; 2 | public class F { 3 | public Thing P1; 4 | public Thing P2; 5 | public long D; 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/algorithm/FT.java: -------------------------------------------------------------------------------- 1 | package algorithm; 2 | public enum FT { 3 | One, Two 4 | } 5 | -------------------------------------------------------------------------------- /src/main/java/algorithm/Finder.java: -------------------------------------------------------------------------------- 1 | package algorithm; 2 | import java.util.ArrayList; 3 | import java.util.List; 4 | 5 | public class Finder { 6 | private final List _p; 7 | 8 | public Finder(List p) { 9 | _p = p; 10 | } 11 | 12 | public F Find(FT ft) { 13 | List tr = new ArrayList(); 14 | 15 | for (int i = 0; i < _p.size() - 1; i++) { 16 | for (int j = i + 1; j < _p.size(); j++) { 17 | F r = new F(); 18 | if (_p.get(i).birthDate.getTime() < _p.get(j).birthDate.getTime()) { 19 | r.P1 = _p.get(i); 20 | r.P2 = _p.get(j); 21 | } else { 22 | r.P1 = _p.get(j); 23 | r.P2 = _p.get(i); 24 | } 25 | r.D = r.P2.birthDate.getTime() - r.P1.birthDate.getTime(); 26 | tr.add(r); 27 | } 28 | } 29 | 30 | if (tr.size() < 1) { 31 | return new F(); 32 | } 33 | 34 | F answer = tr.get(0); 35 | for (F result : tr) { 36 | switch (ft) { 37 | case One : 38 | if (result.D < answer.D) { 39 | answer = result; 40 | } 41 | break; 42 | 43 | case Two : 44 | if (result.D > answer.D) { 45 | answer = result; 46 | } 47 | break; 48 | } 49 | } 50 | 51 | return answer; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/algorithm/Thing.java: -------------------------------------------------------------------------------- 1 | package algorithm; 2 | 3 | import java.util.Date; 4 | 5 | public class Thing { 6 | public String name; 7 | public Date birthDate; 8 | 9 | public String getName() { 10 | return name; 11 | } 12 | public void setName(String name) { 13 | this.name = name; 14 | } 15 | public Date getBirthDate() { 16 | return birthDate; 17 | } 18 | public void setBirthDate(Date birthDate) { 19 | this.birthDate = birthDate; 20 | } 21 | } 22 | 23 | -------------------------------------------------------------------------------- /src/test/java/test/FinderTests.java: -------------------------------------------------------------------------------- 1 | package test; 2 | import static org.junit.Assert.assertEquals; 3 | 4 | import java.util.ArrayList; 5 | import java.util.Date; 6 | import java.util.List; 7 | 8 | import org.junit.Before; 9 | import org.junit.Test; 10 | 11 | import algorithm.F; 12 | import algorithm.FT; 13 | import algorithm.Finder; 14 | import algorithm.Thing; 15 | 16 | public class FinderTests { 17 | 18 | Thing sue = new Thing(); 19 | Thing greg = new Thing(); 20 | Thing sarah = new Thing(); 21 | Thing mike = new Thing(); 22 | 23 | @Before 24 | public void setup() { 25 | sue.name = "Sue"; 26 | sue.birthDate = new Date(50, 0, 1); 27 | greg.name = "Greg"; 28 | greg.birthDate = new Date(52, 5, 1); 29 | sarah.name = "Sarah"; 30 | sarah.birthDate = new Date(82, 0, 1); 31 | mike.name = "Mike"; 32 | mike.birthDate = new Date(79, 0, 1); 33 | } 34 | 35 | @Test 36 | public void Returns_Empty_Results_When_Given_Empty_List() { 37 | List list = new ArrayList(); 38 | Finder finder = new Finder(list); 39 | 40 | F result = finder.Find(FT.One); 41 | assertEquals(null, result.P1); 42 | 43 | assertEquals(null, result.P2); 44 | } 45 | 46 | @Test 47 | public void Returns_Empty_Results_When_Given_One_Person() { 48 | List list = new ArrayList(); 49 | list.add(sue); 50 | 51 | Finder finder = new Finder(list); 52 | 53 | F result = finder.Find(FT.One); 54 | 55 | assertEquals(null, result.P1); 56 | assertEquals(null, result.P2); 57 | } 58 | 59 | @Test 60 | public void Returns_Closest_Two_For_Two_People() { 61 | List list = new ArrayList(); 62 | list.add(sue); 63 | list.add(greg); 64 | Finder finder = new Finder(list); 65 | 66 | F result = finder.Find(FT.One); 67 | 68 | assertEquals(sue, result.P1); 69 | assertEquals(greg, result.P2); 70 | } 71 | 72 | @Test 73 | public void Returns_Furthest_Two_For_Two_People() { 74 | List list = new ArrayList(); 75 | list.add(mike); 76 | list.add(greg); 77 | 78 | Finder finder = new Finder(list); 79 | 80 | F result = finder.Find(FT.Two); 81 | 82 | assertEquals(greg, result.P1); 83 | assertEquals(mike, result.P2); 84 | } 85 | 86 | @Test 87 | public void Returns_Furthest_Two_For_Four_People() { 88 | List list = new ArrayList(); 89 | list.add(sue); 90 | list.add(sarah); 91 | list.add(mike); 92 | list.add(greg); 93 | Finder finder = new Finder(list); 94 | 95 | F result = finder.Find(FT.Two); 96 | 97 | assertEquals(sue, result.P1); 98 | assertEquals(sarah, result.P2); 99 | } 100 | 101 | @Test 102 | public void Returns_Closest_Two_For_Four_People() { 103 | List list = new ArrayList(); 104 | list.add(sue); 105 | list.add(sarah); 106 | list.add(mike); 107 | list.add(greg); 108 | 109 | Finder finder = new Finder(list); 110 | 111 | F result = finder.Find(FT.One); 112 | 113 | assertEquals(sue, result.P1); 114 | assertEquals(greg, result.P2); 115 | } 116 | 117 | } 118 | --------------------------------------------------------------------------------