├── .gitignore ├── LICENSE ├── README.md ├── pom.xml └── src ├── main ├── java │ ├── refactown │ │ └── cleancode │ │ │ ├── c01cleancode │ │ │ ├── BadCode.java │ │ │ ├── Refactoring1.java │ │ │ └── Refactoring2.java │ │ │ ├── c02names │ │ │ ├── BadCode.java │ │ │ ├── Refactoring.java │ │ │ └── order │ │ │ │ ├── Item.java │ │ │ │ ├── ItemDTO.java │ │ │ │ ├── Order.java │ │ │ │ ├── OrderDTO.java │ │ │ │ ├── OrderMapper.java │ │ │ │ ├── OrderRepository.java │ │ │ │ ├── OrderService.java │ │ │ │ └── Repository.java │ │ │ ├── c03functions │ │ │ ├── CommandQuery.java │ │ │ ├── Fibonacci.java │ │ │ ├── FileReader.java │ │ │ ├── FileWriter.java │ │ │ ├── PedraPapelTesoura.java │ │ │ ├── RockPaperScissors.java │ │ │ └── employee │ │ │ │ ├── CommissionedEmployee.java │ │ │ │ ├── Employee.java │ │ │ │ ├── EmployeeLib.java │ │ │ │ ├── HourlyEmployee.java │ │ │ │ ├── SalariedEmployee.java │ │ │ │ ├── TryCatch.java │ │ │ │ └── Type.java │ │ │ ├── c04comments │ │ │ └── Comments.java │ │ │ ├── c05format │ │ │ └── JavaExampleClass.java │ │ │ ├── c06objects │ │ │ ├── Item.java │ │ │ ├── ItemDTO.java │ │ │ ├── Pedido.java │ │ │ ├── PedidoDTO.java │ │ │ ├── PersonJ.java │ │ │ ├── book │ │ │ │ ├── Circle.java │ │ │ │ ├── CircleOO.java │ │ │ │ ├── Geometry.java │ │ │ │ ├── Rectangle.java │ │ │ │ ├── RectangleOO.java │ │ │ │ ├── Shape.java │ │ │ │ ├── Square.java │ │ │ │ └── SquareOO.java │ │ │ └── envy │ │ │ │ ├── AnemicOrder.java │ │ │ │ ├── FeatureEnvy.java │ │ │ │ └── Order.java │ │ │ ├── c07exceptions │ │ │ └── java │ │ │ │ ├── JsonException.java │ │ │ │ └── JsonParsing.java │ │ │ ├── c08boundary │ │ │ └── java │ │ │ │ ├── GsonJsonParser.java │ │ │ │ ├── JsonParser.java │ │ │ │ ├── LogonController.java │ │ │ │ └── User.java │ │ │ ├── c09tests │ │ │ ├── ContadorConstantesInteiras.java │ │ │ ├── IntConstCounterV1.java │ │ │ ├── IntConstCounterV1AfterRefactoring.java │ │ │ ├── IntConstCounterV2.java │ │ │ └── IntConstCounterV3.java │ │ │ ├── c10classes │ │ │ ├── ClassesMain.java │ │ │ ├── ProceduralMain.java │ │ │ ├── enums │ │ │ │ ├── Mao.java │ │ │ │ ├── Resultado.java │ │ │ │ └── ResultadoJogada.java │ │ │ └── model │ │ │ │ ├── Jogada.java │ │ │ │ ├── JogadaLegada.java │ │ │ │ ├── JogadaSimples.java │ │ │ │ ├── Jogador.java │ │ │ │ └── MelhorDeTres.java │ │ │ ├── math │ │ │ └── Math.java │ │ │ └── megasena │ │ │ ├── Aposta.java │ │ │ ├── CalculadoraPremio.java │ │ │ ├── MegaSenaV0.java │ │ │ ├── MegaSenaV1.java │ │ │ ├── MegaSenaV2.java │ │ │ ├── MegaSenaV3.java │ │ │ ├── MegaSenaV4.java │ │ │ ├── MegaSenaV5.java │ │ │ ├── modelo │ │ │ ├── Apostador.java │ │ │ ├── Bilhete.java │ │ │ ├── Bolao.java │ │ │ ├── BolaoBuilder.java │ │ │ ├── Concurso.java │ │ │ ├── Cpf.java │ │ │ └── QuantidadeApostasException.java │ │ │ └── v6 │ │ │ ├── Aposta.java │ │ │ ├── GloboGiratorio.java │ │ │ ├── Premio.java │ │ │ ├── Resultado.java │ │ │ └── TipoPremio.java │ └── tdc2020poa │ │ ├── Disputa.java │ │ ├── DisputaLegada.java │ │ ├── DisputaNova.java │ │ ├── Jogador.java │ │ ├── Jogo.java │ │ ├── Mao.java │ │ ├── PTP.java │ │ ├── Resultado.java │ │ ├── Rodada.java │ │ ├── RodadaJava.java │ │ ├── Simulacao.java │ │ ├── SimulacaoProcedural.java │ │ ├── codigo-pronto.txt │ │ └── roteiro-palestra.txt ├── kotlin │ └── refactown │ │ └── cleancode │ │ ├── README.txt │ │ ├── c01cleancode │ │ ├── BadCode.kt │ │ ├── Refactoring1.kt │ │ └── Refactoring2.kt │ │ ├── c02names │ │ ├── BadCode.kt │ │ ├── Order.kt │ │ └── Refactoring1.kt │ │ ├── c03functions │ │ ├── CommandQuery.kt │ │ ├── Employee.kt │ │ ├── Fibonacci.kt │ │ ├── FileReader.kt │ │ ├── FileWriter.kt │ │ ├── RockPaperScissors.kt │ │ └── TryCatch.kt │ │ ├── c04comments │ │ └── Comments.kt │ │ ├── c05format │ │ ├── ExampleClass.kt │ │ └── README.txt │ │ ├── c06objects │ │ ├── BookExample.kt │ │ ├── DemeterLaw.kt │ │ ├── FeatureEnvy.kt │ │ ├── FeatureEnvySideEfects.kt │ │ └── Person.kt │ │ ├── c07exceptions │ │ ├── JsonException.kt │ │ └── JsonParsing.kt │ │ ├── c08boundary │ │ ├── GsonJsonParser.kt │ │ ├── JsonParser.kt │ │ └── LogonController.kt │ │ ├── c09tests │ │ ├── IntConstCounterV1.kt │ │ ├── IntConstCounterV2.kt │ │ ├── IntConstCounterV3.kt │ │ └── RefactoringV1.kt │ │ ├── c10classes │ │ ├── BestOfThree.kt │ │ ├── ClassesMain.kt │ │ ├── Match.kt │ │ ├── Player.kt │ │ ├── ProceduralMain.kt │ │ ├── RockPaperScissors.kt │ │ └── full-code-oo.txt │ │ ├── math │ │ └── Math.kt │ │ └── quiz │ │ ├── domain │ │ ├── Answer.kt │ │ ├── Game.kt │ │ ├── Guess.kt │ │ ├── Question.kt │ │ ├── Quiz.kt │ │ ├── Round.kt │ │ └── User.kt │ │ └── service │ │ ├── GameService.kt │ │ └── GuessEvent.kt └── resources │ ├── README.txt │ └── cpbsb6 │ ├── pratica-funcoes-chatgpt.txt │ ├── pratica-funcoes-gemini.txt │ └── pratica-funcoes.txt └── test ├── java ├── refactown │ └── cleancode │ │ ├── c01cleancode │ │ └── CountIntConstTest.java │ │ ├── c03functions │ │ ├── FibonacciTest.java │ │ ├── PedraPapelTesouraTest.java │ │ └── RockPaperScissorsTest.java │ │ ├── c06objects │ │ ├── book │ │ │ └── GeometryTest.java │ │ └── envy │ │ │ └── FeatureEnvyTest.java │ │ ├── c07exceptions │ │ └── JsonParsingTest.java │ │ ├── c08boundary │ │ └── java │ │ │ ├── GsonJsonParserTest.java │ │ │ ├── GsonTest.java │ │ │ └── LogonControllerTest.java │ │ ├── c09tests │ │ ├── ContadorConstantesInteirasTest.java │ │ └── IntConstCounterTest.java │ │ ├── c10classes │ │ ├── enums │ │ │ └── MaoTest.java │ │ └── model │ │ │ ├── JogadaTest.java │ │ │ └── MelhorDeTresTest.java │ │ ├── math │ │ └── MathTest.java │ │ └── megasena │ │ ├── ApostaTest.java │ │ ├── CalculadoraPremioTest.java │ │ ├── MegaSenaTest.java │ │ ├── modelo │ │ └── CpfTest.java │ │ └── v6 │ │ ├── ApostaTest.java │ │ ├── GloboGiratorioTest.java │ │ ├── PremioTest.java │ │ └── ResultadoTest.java └── tdc2020poa │ ├── DisputaTest.java │ ├── JogadorMock.java │ ├── JogoTest.java │ ├── MaoTest.java │ └── PTPTest.java ├── kotlin └── refactown │ └── cleancode │ ├── README.txt │ ├── c01cleancode │ └── Cap01Test.kt │ ├── c03functions │ ├── FibonacciKtTest.kt │ └── FunctionsKtTest.kt │ ├── c05format │ └── ExampleClassTest.kt │ ├── c06objects │ ├── BookExampleTest.kt │ └── PersonTest.kt │ ├── c07exceptions │ └── JsonParsingKtTest.kt │ ├── c08boundary │ ├── GsonJsonParserTest.kt │ ├── GsonTest.kt │ └── LogonControllerTest.kt │ ├── c10classes │ ├── HandTest.kt │ └── MatchTest.kt │ └── math │ └── MathKtTest.kt └── resources └── README.txt /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled class file 2 | *.class 3 | 4 | # Eclipse 5 | /target/ 6 | /.settings/ 7 | /.classpath 8 | /.project 9 | 10 | # IntelliJ 11 | /.idea 12 | *.attach_pid* 13 | /cleancode.iml 14 | 15 | # Package Files # 16 | *.jar 17 | *.war 18 | *.nar 19 | *.ear 20 | *.zip 21 | *.tar.gz 22 | *.rar 23 | 24 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 25 | hs_err_pid* 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Curso de Clean Code (Udemy) 2 | Este projeto é parte integrante do curso sobre "Clean Code" disponibilizado na Udemy. 3 | 4 | Para maiores informações clique no link abaixo: 5 | [https://www.udemy.com/course/clean-code-na-pratica/?referralCode=24F598EE94626485768C](https://www.udemy.com/course/clean-code-na-pratica/?referralCode=24F598EE94626485768C) 6 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/c01cleancode/BadCode.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c01cleancode; 2 | 3 | import java.lang.reflect.Field; 4 | import java.lang.reflect.Modifier; 5 | import java.math.BigInteger; 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | import static java.lang.reflect.Modifier.isFinal; 10 | import static java.lang.reflect.Modifier.isStatic; 11 | 12 | public class BadCode { 13 | 14 | public static int constants(Class c) { // count integer constants 15 | if (c == null || c.isEnum() || Modifier.isAbstract(c.getModifiers())) { 16 | return -1; 17 | } 18 | List list = new ArrayList<>(); // field list 19 | for (Field field : c.getDeclaredFields()) { 20 | list.add(field); 21 | } 22 | Class s = c.getSuperclass(); 23 | while (s != null && !s.equals(Object.class)) { 24 | for (Field field : s.getDeclaredFields()) { 25 | list.add(field); 26 | } 27 | s = s.getSuperclass(); // Superclass of c 28 | } 29 | int count = 0; 30 | Class t; 31 | for (Field field : list) { 32 | t = field.getType(); 33 | if (t.equals(Integer.class) || t.equals(int.class) 34 | || t.equals(Long.class) || t.equals(long.class) 35 | || t.equals(Short.class) || t.equals(short.class) 36 | || t.equals(Byte.class) || t.equals(byte.class) 37 | || t.equals(BigInteger.class)) { 38 | if (isStatic(field.getModifiers()) && isFinal(field.getModifiers())) { 39 | System.out.println("Int Constant:" + field); 40 | count++; 41 | } 42 | } 43 | } 44 | return count; 45 | 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/c01cleancode/Refactoring1.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c01cleancode; 2 | 3 | import java.lang.reflect.Field; 4 | import java.lang.reflect.Modifier; 5 | import java.math.BigInteger; 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | import static java.lang.reflect.Modifier.isFinal; 10 | import static java.lang.reflect.Modifier.isStatic; 11 | 12 | public class Refactoring1 { 13 | 14 | public static int countIntConstants(Class clazz) { 15 | if (clazz == null || clazz.isEnum() || Modifier.isAbstract(clazz.getModifiers())) { 16 | return -1; 17 | } 18 | List fields = new ArrayList<>(); 19 | for (Field field : clazz.getDeclaredFields()) { 20 | fields.add(field); 21 | } 22 | Class superClass = clazz.getSuperclass(); 23 | while (superClass != null && !superClass.equals(Object.class)) { 24 | for (Field field : superClass.getDeclaredFields()) { 25 | fields.add(field); 26 | } 27 | superClass = superClass.getSuperclass(); 28 | } 29 | int count = 0; 30 | Class fieldType; 31 | for (Field field : fields) { 32 | fieldType = field.getType(); 33 | if (fieldType.equals(Integer.class) || fieldType.equals(int.class) 34 | || fieldType.equals(Long.class) || fieldType.equals(long.class) 35 | || fieldType.equals(Short.class) || fieldType.equals(short.class) 36 | || fieldType.equals(Byte.class) || fieldType.equals(byte.class) 37 | || fieldType.equals(BigInteger.class)) { 38 | if (isStatic(field.getModifiers()) && isFinal(field.getModifiers())) { 39 | System.out.println("Int Constant:" + field); 40 | count++; 41 | } 42 | } 43 | } 44 | return count; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/c01cleancode/Refactoring2.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c01cleancode; 2 | 3 | import java.lang.reflect.Field; 4 | import java.lang.reflect.Modifier; 5 | import java.math.BigInteger; 6 | import java.util.*; 7 | 8 | import static java.lang.reflect.Modifier.isFinal; 9 | import static java.lang.reflect.Modifier.isStatic; 10 | 11 | public class Refactoring2 { 12 | 13 | private static final Set> INTEGER_TYPES = new HashSet<>(); 14 | 15 | static { 16 | INTEGER_TYPES.add(Integer.class); INTEGER_TYPES.add(int.class); 17 | INTEGER_TYPES.add(Long.class); INTEGER_TYPES.add(long.class); 18 | INTEGER_TYPES.add(Short.class); INTEGER_TYPES.add(short.class); 19 | INTEGER_TYPES.add(Byte.class); INTEGER_TYPES.add(byte.class); 20 | INTEGER_TYPES.add(BigInteger.class); 21 | } 22 | 23 | public static int countIntegerConstants(Class clazz) { // +1 24 | if (!isClasseComConst(clazz)) { // +1 25 | return -1; // +1 26 | } 27 | 28 | List fields = getFieldsFromClass(clazz); 29 | 30 | int count = 0; 31 | for (Field field : fields) { // +1 32 | if (isIntConst(field)) { // +1 33 | System.out.println("Int Constant:" + field); 34 | count++; 35 | } 36 | } 37 | return count; // CC = 5 (Total = 22) 38 | } 39 | 40 | public static boolean isClasseComConst(Class clazz) { // +1 41 | return clazz != null && !clazz.isEnum() // +1 42 | && !Modifier.isAbstract(clazz.getModifiers()); // +1 cc = 3 43 | } 44 | 45 | public static List getFieldsFromClass(Class clazz) { // +1 46 | List fields = new ArrayList<>(); 47 | fields.addAll(Arrays.asList(clazz.getDeclaredFields())); 48 | Class superClass = clazz.getSuperclass(); 49 | if (superClass != null && !superClass.equals(Object.class)) { // +2 50 | fields.addAll(getFieldsFromClass(superClass)); 51 | } 52 | return fields; // CC = 3 53 | 54 | } 55 | 56 | public static boolean isIntConst(Field field) { // +1 57 | return INTEGER_TYPES.contains(field.getType()) 58 | && isStatic(field.getModifiers()) 59 | && isFinal(field.getModifiers()); // +1 CC = 3 60 | } 61 | 62 | 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/c02names/BadCode.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c02names; 2 | 3 | import java.lang.reflect.Field; 4 | import java.time.LocalDate; 5 | import java.time.Month; 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | public class BadCode { 10 | // nomes genéricos 11 | int d = 5; 12 | List list = new ArrayList(); 13 | void func(int n){ 14 | for (int i=0; i < 10; i++){ 15 | if (n == 3) System.out.println("count:" + i + " = 3"); 16 | } 17 | } 18 | 19 | // Nomes não pronunciáveis 20 | LocalDate genymdhms= LocalDate.now(); 21 | LocalDate modymdhms= LocalDate.now(); 22 | int pszqint = 102; 23 | 24 | // Número mágico - difpicil de encontrar depois 25 | public static boolean podeSerEireli(int socios){ 26 | return socios <= 3; 27 | } 28 | 29 | // Notação húngara 30 | String strNome = "Fulano"; 31 | int intIdade = 30; 32 | LocalDate dtNascimento = LocalDate.of(1990, Month.APRIL, 12); 33 | 34 | // Etc 35 | private IPessoa pessoa =new Pessoa(); 36 | EnderecoDoCliente enderecoDeCobrancaDoCliente=new EnderecoDoCliente(); 37 | EnderecoDoCliente enderecoDeEntregaDoCliente= new EnderecoDoCliente(); 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/c02names/Refactoring.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c02names; 2 | 3 | import java.lang.reflect.Field; 4 | import java.time.LocalDate; 5 | import java.time.Month; 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | public class Refactoring { 10 | 11 | private static final int MAX_SOCIOS_EIRELI = 5; 12 | 13 | // nomes Significativos 14 | int tempoDecorrido = 5; 15 | List fields = new ArrayList(); 16 | void imprimeSoNoTres(int n){ 17 | for (int i=0; i < 10; i++){ 18 | if (n == 3) System.out.println("count:" + i + " = 3"); 19 | } 20 | } 21 | 22 | // Nomes não pronunciáveis 23 | LocalDate generationTimestamp= LocalDate.now(); 24 | LocalDate modificationTimestamp= LocalDate.now(); 25 | int recordId = 102; 26 | 27 | // Constantes para números mágicos e afins 28 | public static boolean podeSerEireli(int socios){ 29 | return socios <= MAX_SOCIOS_EIRELI; 30 | } 31 | 32 | // Notação húngara 33 | String nome = "Fulano"; 34 | int idade = 30; 35 | LocalDate nascimento = LocalDate.of(1990, Month.APRIL, 12); 36 | 37 | // Etc 38 | private Pessoa pessoa =new PessoaImpl(); 39 | Endereco enderecoDeCobranca=new Endereco(); 40 | Endereco enderecoDeEntrega= new Endereco(); 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/c02names/order/Item.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c02names.order; 2 | 3 | public class Item { 4 | 5 | private String productId; 6 | private int quantity; 7 | private double price; 8 | 9 | public Item(String productId, int quantity, double price) { 10 | super(); 11 | this.productId = productId; 12 | this.quantity = quantity; 13 | this.price = price; 14 | } 15 | 16 | public String getProductId() { 17 | return productId; 18 | } 19 | 20 | public void setProductId(String productId) { 21 | this.productId = productId; 22 | } 23 | 24 | public int getQuantity() { 25 | return quantity; 26 | } 27 | 28 | public void setQuantity(int quantity) { 29 | this.quantity = quantity; 30 | } 31 | 32 | public double getPrice() { 33 | return price; 34 | } 35 | 36 | public void setPrice(double price) { 37 | this.price = price; 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/c02names/order/ItemDTO.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c02names.order; 2 | 3 | public class ItemDTO { 4 | 5 | private final String productId; 6 | private final int quantity; 7 | private final double price; 8 | 9 | public ItemDTO(String productId, int quantity, double price) { 10 | super(); 11 | this.productId = productId; 12 | this.quantity = quantity; 13 | this.price = price; 14 | } 15 | 16 | public String getProductId() { 17 | return productId; 18 | } 19 | 20 | public int getQuantity() { 21 | return quantity; 22 | } 23 | 24 | public double getPrice() { 25 | return price; 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/c02names/order/Order.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c02names.order; 2 | 3 | // PROBLEM: Order, Item - SOLUTION: Repository, Mapper, Service, DTO 4 | 5 | 6 | import java.time.LocalDate; 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | 10 | public class Order { 11 | private String number; 12 | private LocalDate date; 13 | private List items = new ArrayList(); 14 | 15 | public Order (String number, LocalDate date){ 16 | this.number = number; 17 | this.date = date; 18 | } 19 | 20 | public String getNumber() { 21 | return number; 22 | } 23 | 24 | public void setNumber(String number) { 25 | this.number = number; 26 | } 27 | 28 | public LocalDate getDate() { 29 | return date; 30 | } 31 | 32 | public void setDate(LocalDate date) { 33 | this.date = date; 34 | } 35 | 36 | public List getItems() { 37 | return items; 38 | } 39 | 40 | public void setItems(List items) { 41 | this.items = items; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/c02names/order/OrderDTO.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c02names.order; 2 | 3 | import java.time.LocalDate; 4 | import java.util.List; 5 | 6 | public class OrderDTO { 7 | 8 | private final String number; 9 | private final LocalDate date; 10 | private final List items; 11 | 12 | public OrderDTO(String number, LocalDate date, List items) { 13 | super(); 14 | this.number = number; 15 | this.date = date; 16 | this.items = items; 17 | } 18 | 19 | public String getNumber() { 20 | return number; 21 | } 22 | 23 | public LocalDate getDate() { 24 | return date; 25 | } 26 | 27 | public List getItems() { 28 | return items; 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/c02names/order/OrderMapper.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c02names.order; 2 | 3 | public class OrderMapper { 4 | 5 | public Order dtoToEntity(OrderDTO dto) { 6 | return null; // TODO 7 | } 8 | 9 | public OrderDTO entityToDto(Order order) { 10 | return null;// TODO 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/c02names/order/OrderRepository.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c02names.order; 2 | 3 | public class OrderRepository implements Repository{ 4 | 5 | @Override 6 | public void insert(Order entity) { 7 | // TODO Auto-generated method stub 8 | } 9 | 10 | @Override 11 | public void update(Order entity) { 12 | // TODO Auto-generated method stub 13 | } 14 | 15 | @Override 16 | public Order load(String id) { 17 | // TODO Auto-generated method stub 18 | return null; 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/c02names/order/OrderService.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c02names.order; 2 | 3 | public class OrderService { 4 | 5 | private final OrderMapper mapper; 6 | private final OrderRepository repository; 7 | 8 | public OrderService(OrderMapper mapper, OrderRepository repository) { 9 | super(); 10 | this.mapper = mapper; 11 | this.repository = repository; 12 | } 13 | 14 | public void place(OrderDTO orderDTO) { 15 | Order order = mapper.dtoToEntity(orderDTO); 16 | repository.insert(order); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/c02names/order/Repository.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c02names.order; 2 | 3 | public interface Repository { 4 | public void insert(T entity); 5 | 6 | public void update(T entity); 7 | 8 | public T load(ID id); 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/c03functions/CommandQuery.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c03functions; 2 | 3 | public class CommandQuery { 4 | 5 | public static boolean sett(String attribute, String value) { 6 | return true; 7 | } 8 | 9 | public static boolean attributeExists(String attribute) { 10 | return true; 11 | } 12 | 13 | public static void setAttribute(String attribute, String value) { 14 | 15 | } 16 | 17 | public static void main(String[] args) { 18 | if (sett("username", "bill")) {} 19 | 20 | if (attributeExists("username")){ 21 | setAttribute("username", "bill"); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/c03functions/Fibonacci.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c03functions; 2 | 3 | public class Fibonacci { 4 | 5 | public static int fib(int x) { 6 | if (x == 0 || x == 1) { 7 | return x; 8 | } 9 | return fib(x - 1) + fib(x - 2); 10 | } 11 | 12 | public static String seq(int x) { 13 | if (x == 0) { 14 | return "0"; 15 | } 16 | return "" + seq(x - 1) + "," + fib(x); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/c03functions/FileReader.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c03functions; 2 | 3 | public interface FileReader { 4 | 5 | // reads file to buffer 6 | public void read(String filename, StringBuffer buffer); 7 | 8 | // reads file and returns 9 | public StringBuffer read(String filename); 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/c03functions/FileWriter.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c03functions; 2 | 3 | public interface FileWriter { 4 | 5 | // Flag Argument "append" 6 | public void write(String text, boolean append); 7 | 8 | // write appending 9 | public void writeEof(String text); 10 | 11 | // overwrite 12 | public void writeBof(String text); 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/c03functions/PedraPapelTesoura.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c03functions; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | 6 | public class PedraPapelTesoura { 7 | 8 | 9 | 10 | public static int pedraPapelTesoura(char primeiro, char segundo) { 11 | List LETRAS_VALIDAS = Arrays.asList('R', 'S', 'P'); 12 | if (!LETRAS_VALIDAS.contains(primeiro)) { 13 | throw new IllegalArgumentException("Primeira mão inválida:" + primeiro + ". Use " + LETRAS_VALIDAS); 14 | } 15 | if (!LETRAS_VALIDAS.contains(segundo)) { 16 | throw new IllegalArgumentException("Segunda mão inválida:" + segundo + ". Use " + LETRAS_VALIDAS); 17 | } 18 | if (primeiro == 'R') { 19 | if (segundo == 'P') return 1; else if (segundo == 'S') return -1; else return 0; 20 | } else if (primeiro == 'P') { 21 | if (segundo == 'S') return 1; else if (segundo == 'R') return -1; else return 0; 22 | } else { // S 23 | if (segundo == 'R') return 1; else if (segundo == 'P') return -1; else return 0; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/c03functions/RockPaperScissors.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c03functions; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | 6 | public class RockPaperScissors { 7 | 8 | private static List VALID_CHOOSES = Arrays.asList('R', 'S', 'P'); 9 | 10 | public static int rockPaperScissors(char first, char second) { 11 | if (!VALID_CHOOSES.contains(first)) { 12 | throw new IllegalArgumentException("Invalid first choose:" + first + ". Use " + VALID_CHOOSES); 13 | } 14 | if (!VALID_CHOOSES.contains(second)) { 15 | throw new IllegalArgumentException("Invalid second choose:" + second + ". Use " + VALID_CHOOSES); 16 | } 17 | if (first == 'R') { 18 | if (second == 'P') return 1; else if (second == 'S') return -1; else return 0; 19 | } else if (first == 'P') { 20 | if (second == 'S') return 1; else if (second == 'R') return -1; else return 0; 21 | } else { // S 22 | if (second == 'R') return 1; else if (second == 'P') return -1; else return 0; 23 | } 24 | 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/c03functions/employee/CommissionedEmployee.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c03functions.employee; 2 | 3 | public class CommissionedEmployee extends Employee{ 4 | 5 | public CommissionedEmployee(String name) { 6 | super(name, Type.COMMISSIONED); 7 | } 8 | 9 | @Override 10 | public double calculatePay() { 11 | return 1.0; 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/c03functions/employee/Employee.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c03functions.employee; 2 | 3 | public abstract class Employee { 4 | 5 | private String name; 6 | private Type type; 7 | 8 | public Employee(String name, Type type) { 9 | super(); 10 | this.name = name; 11 | this.type = type; 12 | } 13 | 14 | public abstract double calculatePay(); 15 | 16 | public String getName() { 17 | return name; 18 | } 19 | 20 | public void setName(String name) { 21 | this.name = name; 22 | } 23 | 24 | public Type getType() { 25 | return type; 26 | } 27 | 28 | public void setType(Type type) { 29 | this.type = type; 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/c03functions/employee/EmployeeLib.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c03functions.employee; 2 | 3 | public class EmployeeLib { 4 | 5 | public static double calculatePay(Employee employee) { 6 | switch (employee.getType()) { 7 | case COMMISSIONED: 8 | return calculateCommissionedPay(employee); 9 | case HOURLY: 10 | return calculateHourlyPay(employee); 11 | case SALARIED: 12 | return calculateCommissionedPay(employee); 13 | default: 14 | throw new IllegalArgumentException("Unknown type!"); 15 | } 16 | } 17 | 18 | public static double calculateSalariedPay(Employee employee) { 19 | return Double.MIN_VALUE; 20 | } 21 | public static double calculateHourlyPay(Employee employee) { 22 | return Double.POSITIVE_INFINITY; 23 | } 24 | public static double calculateCommissionedPay(Employee employee) { 25 | return Double.MAX_VALUE; 26 | } 27 | 28 | public static Employee create(String name, Type type) { 29 | switch (type) { 30 | case COMMISSIONED: 31 | return new CommissionedEmployee(name); 32 | case HOURLY: 33 | return new HourlyEmployee(name); 34 | case SALARIED: 35 | return new CommissionedEmployee(name); 36 | default: 37 | throw new IllegalArgumentException("Unknown type!"); 38 | } 39 | } 40 | 41 | } -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/c03functions/employee/HourlyEmployee.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c03functions.employee; 2 | 3 | public class HourlyEmployee extends Employee{ 4 | 5 | public HourlyEmployee(String name) { 6 | super(name, Type.HOURLY); 7 | } 8 | 9 | @Override 10 | public double calculatePay() { 11 | return 2.0; 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/c03functions/employee/SalariedEmployee.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c03functions.employee; 2 | 3 | public class SalariedEmployee extends Employee{ 4 | 5 | public SalariedEmployee(String name) { 6 | super(name, Type.SALARIED); 7 | } 8 | 9 | @Override 10 | public double calculatePay() { 11 | return 3.0; 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/c03functions/employee/TryCatch.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c03functions.employee; 2 | 3 | public class TryCatch { 4 | public void delete(Page page) { 5 | try { 6 | deletePageAndAllReferences(page); // indirection -> 7 | } catch (Exception e) { 8 | logError(e); 9 | } 10 | } 11 | 12 | public void deletePageAndAllReferences(Page page) { 13 | deletePage(page); 14 | deleteReferences(page); 15 | page.getConfigKeys().delete(); 16 | } 17 | 18 | private void deleteReferences(Page page) { 19 | } 20 | 21 | private void deletePage(Page page) { 22 | } 23 | 24 | private void logError(Exception e) { 25 | } 26 | 27 | } 28 | 29 | class Page { 30 | private ConfigKeys configKeys; 31 | 32 | public Page(ConfigKeys configKeys) { 33 | super(); 34 | this.configKeys = configKeys; 35 | } 36 | 37 | public ConfigKeys getConfigKeys() { 38 | return configKeys; 39 | } 40 | 41 | public void setConfigKeys(ConfigKeys configKeys) { 42 | this.configKeys = configKeys; 43 | } 44 | } 45 | 46 | class ConfigKeys { 47 | void delete() { 48 | new TryCatch().delete(new Page(new ConfigKeys())); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/c03functions/employee/Type.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c03functions.employee; 2 | 3 | public enum Type { 4 | 5 | COMMISSIONED, HOURLY, SALARIED; 6 | 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/c04comments/Comments.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c04comments; 2 | 3 | import java.io.FileInputStream; 4 | import java.time.LocalDate; 5 | import java.time.Month; 6 | 7 | import refactown.cleancode.c06objects.Order; 8 | 9 | public class Comments { 10 | public void example() { 11 | Order order = new Order(LocalDate.of(2019, Month.APRIL, 4), false); 12 | 13 | // verifica se o pedido não está cancelado nem tem mais de 1 ano 14 | if (!order.getCancelled() && order.getDate().isBefore(order.getDate().plusDays(365))) 15 | 16 | if (order.isValid()) 17 | System.out.println(""); 18 | 19 | } 20 | 21 | public void callLogon() { 22 | 23 | logon("user", "pass"); 24 | } 25 | 26 | public void load(FileInputStream stream) { 27 | 28 | } 29 | 30 | public void loadProperties(){ 31 | try { 32 | FileInputStream stream = new FileInputStream("file.properties"); 33 | load(stream); 34 | } catch (Exception e){ 35 | // Não havia nenhum arquivo para ser lido 36 | // Todos já foram carregados 37 | } 38 | } 39 | 40 | // Efetua logon passando "usuário" e "senha" e recebe 41 | // o usuário logado 42 | public LoggedUser logon(String username, String password){ 43 | // TODO ("implementar quando o SSO ficar pronto") 44 | return new LoggedUser("Mock", "Mock"); 45 | } 46 | 47 | public void append(String text){ 48 | 49 | //val buffer = StringBuffer() // Precisa ser "Thread Safe" 50 | StringBuilder buffer = new StringBuilder(); // Precisa ser rápido 51 | 52 | } 53 | 54 | public void save (String cpfCnpj){ 55 | 56 | /* 57 | // trim é importante, pois pode vir CPF(11) ou CNPJ(14) 58 | if (cpfCnpj.trim().length==11) { 59 | validarCpf(cpfCnpj) 60 | } else { 61 | validarCnpj(cpfCnpj) 62 | } 63 | */ 64 | // alterado por Fulano em 27/11/1986 65 | validarCnpj(cpfCnpj); // não tem mais CPF 66 | 67 | 68 | } 69 | 70 | public void validarCpf(String cpfCnpj) { 71 | //TODO("not implemented") //To change body of created functions use File | Settings | File Templates. 72 | } 73 | 74 | public void validarCnpj(String cpfCnpj) { 75 | //TODO("not implemented") //To change body of created functions use File | Settings | File Templates. 76 | } 77 | 78 | 79 | } 80 | 81 | class LoggedUser{ 82 | private final String login; 83 | private final String role; 84 | public LoggedUser(String login, String role) { 85 | super(); 86 | this.login = login; 87 | this.role = role; 88 | } 89 | public String getLogin() { 90 | return login; 91 | } 92 | public String getRole() { 93 | return role; 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/c05format/JavaExampleClass.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c05format; 2 | 3 | public class JavaExampleClass { 4 | 5 | private int count = 0; 6 | private boolean flag = false; 7 | 8 | public void method1() { 9 | int x = 3; 10 | internalMethod1(x); 11 | internalMethod2(); 12 | } 13 | 14 | private void internalMethod1(int x) { 15 | // 16 | } 17 | 18 | private void internalMethod2() { 19 | // 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/c06objects/Item.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c06objects; 2 | 3 | public class Item { 4 | } 5 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/c06objects/ItemDTO.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c06objects; 2 | 3 | public class ItemDTO { 4 | } 5 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/c06objects/Pedido.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c06objects; 2 | 3 | import java.time.LocalDate; 4 | import java.util.Collections; 5 | import java.util.List; 6 | 7 | public class Pedido { // estado mutável 8 | private String numero; 9 | private LocalDate data; 10 | private List itens; 11 | 12 | public boolean isValido() { 13 | return data.plusDays(365).isBefore(LocalDate.now()) 14 | && !itens.isEmpty(); 15 | } 16 | 17 | public void addItem(Item item){ itens.add(item);} 18 | 19 | public void removeItem(Item item){ itens.remove(item);} 20 | 21 | public List getItens() { // cópia defensiva 22 | return Collections.unmodifiableList(itens); 23 | } 24 | 25 | public String getNumero() { 26 | return numero; 27 | } 28 | public LocalDate getData() { 29 | return data; 30 | } 31 | public void setNumero(String numero) { 32 | this.numero = numero; 33 | } 34 | public void setData(LocalDate data) { 35 | this.data = data; 36 | } 37 | public void setItens(List itens) { 38 | this.itens = itens; 39 | } 40 | } 41 | 42 | class Test{ 43 | public static void main(String[] args) { 44 | Pedido pedido = new Pedido(); 45 | 46 | if (pedido.getData().plusDays(365).isBefore(LocalDate.now()) 47 | && !pedido.getItens().isEmpty() ){ 48 | // feature envy 49 | } 50 | 51 | if (pedido.isValido()){ 52 | // encapsulamento 53 | } 54 | 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/c06objects/PedidoDTO.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c06objects; 2 | 3 | import java.time.LocalDate; 4 | import java.util.Collections; 5 | import java.util.List; 6 | 7 | public class PedidoDTO { // imutável 8 | private final String numero; 9 | private final LocalDate data; 10 | private final List itens; 11 | 12 | public PedidoDTO(String numero, LocalDate data, List itens) { 13 | this.numero = numero; 14 | this.data = data; 15 | this.itens = Collections.unmodifiableList(itens); 16 | } 17 | 18 | public String getNumero() { 19 | return numero; 20 | } 21 | 22 | public LocalDate getData() { 23 | return data; 24 | } 25 | 26 | public List getItens() { 27 | return itens; 28 | } 29 | } -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/c06objects/PersonJ.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c06objects; 2 | 3 | import java.util.Objects; 4 | 5 | public class PersonJ { 6 | 7 | /** name */ 8 | private String name; 9 | /** age */ 10 | private int age; 11 | /** city */ 12 | private String city; 13 | 14 | /** Default Constructor */ 15 | public PersonJ(){ 16 | 17 | } 18 | 19 | /** 20 | * Retorna o nome. 21 | * @return O nome. 22 | * */ 23 | public String getName() { 24 | return name; 25 | } 26 | 27 | /** 28 | * Determina o nome. 29 | * @param name O nome determinado. 30 | * */ 31 | public void setName(String name) { 32 | this.name = name; 33 | } 34 | 35 | public int getAge() { 36 | return age; 37 | } 38 | 39 | public void setAge(int age) { 40 | this.age = age; 41 | } 42 | public String getCity() { 43 | return city; 44 | } 45 | 46 | public void setCity(String city) { 47 | this.city = city; 48 | } 49 | 50 | public PersonJ(String name, int age, String city) { 51 | this.name = name; 52 | this.age = age; 53 | this.city = city; 54 | } 55 | 56 | 57 | @Override 58 | public boolean equals(Object o) { 59 | if (this == o) return true; 60 | if (o == null || getClass() != o.getClass()) return false; 61 | PersonJ personJ = (PersonJ) o; 62 | return age == personJ.age && 63 | Objects.equals(name, personJ.name) && 64 | Objects.equals(city, personJ.city); 65 | } 66 | 67 | @Override 68 | public int hashCode() { 69 | return Objects.hash(name, age, city); 70 | } 71 | 72 | @Override 73 | public String toString() { 74 | return "PersonJ{" + "name='" + name + '\'' + ", age=" + age + 75 | ", city='" + city + '\'' + 76 | '}'; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/c06objects/book/Circle.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c06objects.book; 2 | 3 | public class Circle { // Java common implementation 4 | 5 | private final double radius; 6 | 7 | public Circle(double radius) { 8 | super(); 9 | this.radius = radius; 10 | } 11 | 12 | public double getRadius() { 13 | return radius; 14 | } 15 | 16 | } 17 | 18 | class StructCircle { // Java "Struct" 19 | 20 | public final double radius; 21 | 22 | public StructCircle(double radius) { 23 | super(); 24 | this.radius = radius; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/c06objects/book/CircleOO.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c06objects.book; 2 | 3 | public class CircleOO implements Shape{ 4 | 5 | private final double radius; 6 | 7 | public CircleOO(double radius) { 8 | super(); 9 | this.radius = radius; 10 | } 11 | 12 | @Override 13 | public double area() { 14 | return Geometry.PI * radius * radius; 15 | } 16 | 17 | public double getRadius() { 18 | return radius; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/c06objects/book/Geometry.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c06objects.book; 2 | 3 | public class Geometry { 4 | 5 | public static final double PI = 3.1416; 6 | 7 | public static double calculateArea(Object shape) { 8 | if (shape instanceof Square) { 9 | Square s = (Square)shape; 10 | return s.getSide() * s.getSide(); // s.side 11 | } else if (shape instanceof Rectangle) { 12 | Rectangle r = (Rectangle) shape; 13 | return r.getHeight() * r.getWidth(); 14 | } else if (shape instanceof Circle) { 15 | Circle c = (Circle) shape; 16 | return PI * c.getRadius() * c.getRadius(); 17 | } 18 | throw new IllegalArgumentException("Unknown shape class:" + shape.getClass()); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/c06objects/book/Rectangle.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c06objects.book; 2 | 3 | public class Rectangle { 4 | 5 | private final double height; // immutable 6 | private final double width; // immutable 7 | 8 | public Rectangle(double height, double width) { 9 | super(); 10 | this.height = height; 11 | this.width = width; 12 | } 13 | 14 | public double getHeight() { 15 | return height; 16 | } 17 | 18 | public double getWidth() { 19 | return width; 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/c06objects/book/RectangleOO.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c06objects.book; 2 | 3 | public class RectangleOO implements Shape { 4 | 5 | private final double height; // immutable 6 | private final double width; // immutable 7 | 8 | public RectangleOO(double height, double width) { 9 | super(); 10 | this.height = height; 11 | this.width = width; 12 | } 13 | 14 | @Override 15 | public double area() { 16 | return height * width; 17 | } 18 | 19 | public double getHeight() { 20 | return height; 21 | } 22 | 23 | public double getWidth() { 24 | return width; 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/c06objects/book/Shape.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c06objects.book; 2 | 3 | public interface Shape { 4 | 5 | public double area(); 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/c06objects/book/Square.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c06objects.book; 2 | 3 | public class Square { 4 | 5 | private double side; // mutable 6 | 7 | public Square(double side) { 8 | super(); 9 | this.side = side; 10 | } 11 | 12 | public double getSide() { 13 | return side; 14 | } 15 | 16 | public void setSide(double side) { 17 | this.side = side; 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/c06objects/book/SquareOO.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c06objects.book; 2 | 3 | public class SquareOO implements Shape{ 4 | 5 | private double side; // mutable 6 | 7 | public SquareOO(double side) { 8 | super(); 9 | this.side = side; 10 | } 11 | 12 | @Override 13 | public double area() { 14 | return side * side; 15 | } 16 | 17 | public double getSide() { 18 | return side; 19 | } 20 | 21 | public void setSide(double side) { 22 | this.side = side; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/c06objects/envy/AnemicOrder.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c06objects.envy; 2 | 3 | import java.time.LocalDate; 4 | 5 | public class AnemicOrder { 6 | 7 | private LocalDate date; 8 | private boolean cancelled; 9 | 10 | public AnemicOrder(LocalDate date, boolean cancelled) { 11 | super(); 12 | this.date = date; 13 | this.cancelled = cancelled; 14 | } 15 | 16 | public boolean isCancelled() { 17 | return cancelled; 18 | } 19 | 20 | public void setCancelled(boolean cancelled) { 21 | this.cancelled = cancelled; 22 | } 23 | 24 | public LocalDate getDate() { 25 | return date; 26 | } 27 | 28 | public void setDate(LocalDate date) { 29 | this.date = date; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/c06objects/envy/FeatureEnvy.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c06objects.envy; 2 | 3 | import java.time.LocalDate; 4 | 5 | import refactown.cleancode.c06objects.book.Geometry; 6 | import refactown.cleancode.c06objects.book.Shape; 7 | 8 | public class FeatureEnvy { 9 | 10 | public boolean isValidOrder(AnemicOrder order) { 11 | return !order.isCancelled() && LocalDate.now().isBefore(order.getDate().plusDays(365)); 12 | } 13 | 14 | public static double calculateArea(Object shape) { 15 | if (shape instanceof HibridSquare) { 16 | HibridSquare s = (HibridSquare)shape; 17 | return s.getSide() * s.getSide(); // s.side 18 | } else if (shape instanceof HybridRectangle) { 19 | HybridRectangle r = (HybridRectangle) shape; 20 | return r.getHeight() * r.getWidth(); 21 | } else if (shape instanceof HybidCircle) { 22 | HybidCircle c = (HybidCircle) shape; 23 | return Geometry.PI * c.getRadius() * c.getRadius(); 24 | } 25 | throw new IllegalArgumentException("Unknown shape class:" + shape.getClass()); 26 | } 27 | } 28 | 29 | class HibridSquare implements Shape{ 30 | 31 | private double side; // mutable 32 | 33 | public HibridSquare(double side) { 34 | super(); 35 | this.side = side; 36 | } 37 | 38 | @Override 39 | public double area() { 40 | return side * side; 41 | } 42 | 43 | public double getSide() { 44 | return side; 45 | } 46 | 47 | public void setSide(double side) { 48 | this.side = side; 49 | } 50 | } 51 | 52 | class HybridRectangle implements Shape { 53 | 54 | private final double height; // immutable 55 | private final double width; // immutable 56 | 57 | public HybridRectangle(double height, double width) { 58 | super(); 59 | this.height = height; 60 | this.width = width; 61 | } 62 | 63 | @Override 64 | public double area() { 65 | return height * width; 66 | } 67 | 68 | public double getHeight() { 69 | return height; 70 | } 71 | 72 | public double getWidth() { 73 | return width; 74 | } 75 | 76 | } 77 | 78 | class HybidCircle implements Shape{ 79 | 80 | private final double radius; 81 | 82 | public HybidCircle(double radius) { 83 | super(); 84 | this.radius = radius; 85 | } 86 | 87 | @Override 88 | public double area() { 89 | return Geometry.PI * radius * radius; 90 | } 91 | 92 | public double getRadius() { 93 | return radius; 94 | } 95 | } 96 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/c06objects/envy/Order.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c06objects.envy; 2 | 3 | import java.time.LocalDate; 4 | 5 | public class Order { 6 | 7 | private LocalDate date; 8 | private boolean cancelled; 9 | 10 | public Order(LocalDate date, boolean cancelled) { 11 | super(); 12 | this.date = date; 13 | this.cancelled = cancelled; 14 | } 15 | 16 | public boolean isValid() { 17 | return !cancelled && LocalDate.now().isBefore(date.plusDays(365)); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/c07exceptions/java/JsonException.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c07exceptions.java; 2 | 3 | public class JsonException extends RuntimeException { 4 | 5 | private static final long serialVersionUID = 1L; 6 | 7 | public JsonException(String message) { 8 | super(message); 9 | } 10 | 11 | public JsonException(String message, Throwable cause) { 12 | super(message, cause); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/c07exceptions/java/JsonParsing.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c07exceptions.java; 2 | 3 | import com.google.gson.Gson; 4 | 5 | public class JsonParsing { 6 | 7 | public static Object fromJsonV0(String json, Class clazz) { 8 | Gson gson = new Gson(); 9 | try { 10 | return gson.fromJson(json, clazz); 11 | } catch (Exception e) { 12 | System.out.println("Parsing error. Json text:" + json); 13 | return null; 14 | } 15 | } 16 | 17 | public static Object fromJsonV1(String json, Class clazz) { 18 | Gson gson = new Gson(); 19 | try { 20 | return gson.fromJson(json, clazz); 21 | } catch (Exception e) { 22 | throw new JsonException("Parsing error. Json text:$json"); 23 | } 24 | } 25 | 26 | public static Object fromJsonV2(String json, Class clazz) { 27 | if (json == null){ 28 | throw new NullPointerException("A variável json não pode ser nula!"); 29 | } 30 | Gson gson = new Gson(); 31 | try { 32 | return gson.fromJson(json, clazz); 33 | } catch (Exception e) { 34 | throw new JsonException("Parsing error. Json text:$json", e); // CAUSE 35 | } 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/c08boundary/java/GsonJsonParser.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c08boundary.java; 2 | 3 | import com.google.gson.Gson; 4 | 5 | import refactown.cleancode.c07exceptions.java.JsonException; 6 | 7 | public class GsonJsonParser implements JsonParser { 8 | 9 | private Gson gson = new Gson(); 10 | 11 | @Override 12 | public Object fromJson(String json, Class clazz) { 13 | try { 14 | return gson.fromJson(json, clazz); 15 | } catch (RuntimeException e) { 16 | throw new JsonException("Parsing error. Json:" + json, e); 17 | } 18 | } 19 | 20 | @Override 21 | public String toJson(Object obj) { 22 | try { 23 | return gson.toJson(obj); 24 | } catch (RuntimeException e) { 25 | throw new JsonException("Serializing error. Object:" + obj, e); 26 | } 27 | 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/c08boundary/java/JsonParser.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c08boundary.java; 2 | 3 | public interface JsonParser { 4 | 5 | Object fromJson(String json, Class clazz); 6 | 7 | String toJson(Object obj); 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/c08boundary/java/LogonController.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c08boundary.java; 2 | 3 | public class LogonController { 4 | 5 | private final JsonParser jsonParser; 6 | 7 | public LogonController(JsonParser jsonParser) { 8 | super(); 9 | this.jsonParser = jsonParser; 10 | } 11 | 12 | public User logon(String login, String password) { 13 | String userJson = callHttp(login, password); 14 | return (User) jsonParser.fromJson(userJson, User.class); 15 | } 16 | 17 | private String callHttp(String login, String password) { 18 | return "{\"login\":\"admin\", \"role\":\"admin\"}"; //MOCK 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/c08boundary/java/User.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c08boundary.java; 2 | 3 | public class User { 4 | 5 | private final String login; 6 | private final String role; 7 | public User(String login, String role) { 8 | super(); 9 | this.login = login; 10 | this.role = role; 11 | } 12 | public String getLogin() { 13 | return login; 14 | } 15 | public String getRole() { 16 | return role; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/c09tests/ContadorConstantesInteiras.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c09tests; 2 | 3 | import java.lang.reflect.Field; 4 | import java.lang.reflect.Modifier; 5 | import java.math.BigInteger; 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | import static java.lang.reflect.Modifier.isFinal; 10 | import static java.lang.reflect.Modifier.isStatic; 11 | 12 | public class ContadorConstantesInteiras { 13 | 14 | public int contar(Class clazz){ 15 | if (clazz == null || clazz.isEnum() || Modifier.isAbstract(clazz.getModifiers())) { 16 | return -1; 17 | } 18 | List fields = new ArrayList<>(); 19 | for (Field field : clazz.getDeclaredFields()) { 20 | fields.add(field); 21 | } 22 | Class superClass = clazz.getSuperclass(); 23 | while (superClass != null && !superClass.equals(Object.class)) { 24 | for (Field field : superClass.getDeclaredFields()) { 25 | fields.add(field); 26 | } 27 | superClass = superClass.getSuperclass(); 28 | } 29 | int count = 0; 30 | Class fieldType; 31 | for (Field field : fields) { 32 | fieldType = field.getType(); 33 | if (fieldType.equals(Integer.class) || fieldType.equals(int.class) 34 | || fieldType.equals(Long.class) || fieldType.equals(long.class) 35 | || fieldType.equals(Short.class) || fieldType.equals(short.class) 36 | || fieldType.equals(Byte.class) || fieldType.equals(byte.class) 37 | || fieldType.equals(BigInteger.class)) { 38 | if (isStatic(field.getModifiers()) && isFinal(field.getModifiers())) { 39 | System.out.println("Int Constant:" + field); 40 | count++; 41 | } 42 | } 43 | } 44 | return count; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/c09tests/IntConstCounterV1.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c09tests; 2 | 3 | import java.lang.reflect.Field; 4 | import java.lang.reflect.Modifier; 5 | import java.math.BigInteger; 6 | import java.util.Arrays; 7 | import java.util.HashSet; 8 | import java.util.List; 9 | import java.util.Set; 10 | 11 | public class IntConstCounterV1 { 12 | 13 | // First implementation 14 | public static int countIntConstV1(Class clazz) { 15 | List fields = Arrays.asList(clazz.getDeclaredFields()); 16 | int count = 0; 17 | Set> integerTypes = new HashSet<>(); 18 | integerTypes.add(Integer.class); 19 | integerTypes.add(int.class); 20 | integerTypes.add(Long.class); 21 | integerTypes.add(long.class); 22 | integerTypes.add(Short.class); 23 | integerTypes.add(short.class); 24 | integerTypes.add(Byte.class); 25 | integerTypes.add(byte.class); 26 | integerTypes.add(BigInteger.class); 27 | 28 | for (Field field : fields) { 29 | if (integerTypes.contains(field.getType()) && Modifier.isStatic(field.getModifiers()) 30 | && Modifier.isFinal(field.getModifiers())) { 31 | System.out.println("Int Const:" + field); 32 | count++; 33 | } 34 | } 35 | return count; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/c09tests/IntConstCounterV1AfterRefactoring.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c09tests; 2 | 3 | import java.lang.reflect.Field; 4 | import java.lang.reflect.Modifier; 5 | import java.math.BigInteger; 6 | import java.util.Arrays; 7 | import java.util.HashSet; 8 | import java.util.List; 9 | import java.util.Set; 10 | 11 | public class IntConstCounterV1AfterRefactoring { 12 | 13 | private static final Set> INTEGER_TYPES = new HashSet<>(); 14 | 15 | static { 16 | INTEGER_TYPES.add(Integer.class); INTEGER_TYPES.add(int.class); 17 | INTEGER_TYPES.add(Long.class); INTEGER_TYPES.add(long.class); 18 | INTEGER_TYPES.add(Short.class); INTEGER_TYPES.add(short.class); 19 | INTEGER_TYPES.add(Byte.class); INTEGER_TYPES.add(byte.class); 20 | INTEGER_TYPES.add(BigInteger.class); 21 | } 22 | 23 | // First implementation 24 | public static int countIntConstV1(Class clazz) { 25 | List fields = Arrays.asList(clazz.getDeclaredFields()); 26 | int count = 0; 27 | 28 | for (Field field : fields) { 29 | if (isIntegerField(field)) { 30 | System.out.println("Int Const:" + field); 31 | count++; 32 | } 33 | } 34 | return count; 35 | } 36 | 37 | private static boolean isIntegerField(Field field) { 38 | return INTEGER_TYPES.contains(field.getType()) && Modifier.isStatic(field.getModifiers()) 39 | && Modifier.isFinal(field.getModifiers()); 40 | 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/c09tests/IntConstCounterV2.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c09tests; 2 | 3 | import java.lang.reflect.Field; 4 | import java.lang.reflect.Modifier; 5 | import java.math.BigInteger; 6 | import java.util.Arrays; 7 | import java.util.HashSet; 8 | import java.util.List; 9 | import java.util.Set; 10 | 11 | public class IntConstCounterV2 { 12 | 13 | private static final Set> INTEGER_TYPES = new HashSet<>(); 14 | 15 | static { 16 | INTEGER_TYPES.add(Integer.class); INTEGER_TYPES.add(int.class); 17 | INTEGER_TYPES.add(Long.class); INTEGER_TYPES.add(long.class); 18 | INTEGER_TYPES.add(Short.class); INTEGER_TYPES.add(short.class); 19 | INTEGER_TYPES.add(Byte.class); INTEGER_TYPES.add(byte.class); 20 | INTEGER_TYPES.add(BigInteger.class); 21 | } 22 | 23 | // First implementation 24 | public static int countIntConstV2(Class clazz) { 25 | if (!isConstantClass(clazz)) return -1; 26 | List fields = Arrays.asList(clazz.getDeclaredFields()); 27 | int count = 0; 28 | 29 | for (Field field : fields) { 30 | if (isIntegerField(field)) { 31 | System.out.println("Int Const:" + field); 32 | count++; 33 | } 34 | } 35 | return count; 36 | } 37 | 38 | public static boolean isConstantClass(Class clazz) { // +1 39 | return clazz != null && !clazz.isEnum() // +1 40 | && !Modifier.isAbstract(clazz.getModifiers()); // +1 cc = 3 41 | } 42 | 43 | 44 | private static boolean isIntegerField(Field field) { 45 | return INTEGER_TYPES.contains(field.getType()) && Modifier.isStatic(field.getModifiers()) 46 | && Modifier.isFinal(field.getModifiers()); 47 | 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/c09tests/IntConstCounterV3.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c09tests; 2 | 3 | import java.lang.reflect.Field; 4 | import java.lang.reflect.Modifier; 5 | import java.math.BigInteger; 6 | import java.util.ArrayList; 7 | import java.util.Arrays; 8 | import java.util.HashSet; 9 | import java.util.List; 10 | import java.util.Set; 11 | 12 | public class IntConstCounterV3 { 13 | 14 | private static final Set> INTEGER_TYPES = new HashSet<>(); 15 | 16 | static { 17 | INTEGER_TYPES.add(Integer.class); INTEGER_TYPES.add(int.class); 18 | INTEGER_TYPES.add(Long.class); INTEGER_TYPES.add(long.class); 19 | INTEGER_TYPES.add(Short.class); INTEGER_TYPES.add(short.class); 20 | INTEGER_TYPES.add(Byte.class); INTEGER_TYPES.add(byte.class); 21 | INTEGER_TYPES.add(BigInteger.class); 22 | } 23 | 24 | // First implementation 25 | public static int countIntConstV3(Class clazz) { 26 | if (!isConstantClass(clazz)) return -1; 27 | List fields = getFieldsFromClass(clazz); 28 | int count = 0; 29 | 30 | for (Field field : fields) { 31 | if (isIntegerField(field)) { 32 | System.out.println("Int Const:" + field); 33 | count++; 34 | } 35 | } 36 | return count; 37 | } 38 | 39 | public static List getFieldsFromClass(Class clazz) { 40 | List fields = new ArrayList<>(); 41 | fields.addAll(Arrays.asList(clazz.getDeclaredFields())); 42 | Class superClass = clazz.getSuperclass(); 43 | if (superClass != null && !superClass.equals(Object.class)) { 44 | fields.addAll(getFieldsFromClass(superClass)); 45 | } 46 | return fields; 47 | } 48 | 49 | public static boolean isConstantClass(Class clazz) { 50 | return clazz != null && !clazz.isEnum() 51 | && !Modifier.isAbstract(clazz.getModifiers()); 52 | } 53 | 54 | 55 | private static boolean isIntegerField(Field field) { 56 | return INTEGER_TYPES.contains(field.getType()) && Modifier.isStatic(field.getModifiers()) 57 | && Modifier.isFinal(field.getModifiers()); 58 | 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/c10classes/ClassesMain.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c10classes; 2 | 3 | import refactown.cleancode.c10classes.model.*; 4 | 5 | public class ClassesMain { 6 | 7 | public static void main(String[] args) { 8 | Jogador bill = new Jogador("Bill (Primeiro)"); 9 | Jogador bob = new Jogador("Bob (Segundo)"); 10 | Jogada jogada = new JogadaSimples(bill, bob); 11 | MelhorDeTres melhorDeTres = new MelhorDeTres(jogada, 5); 12 | melhorDeTres.jogar(); 13 | // Print 14 | if (melhorDeTres.temVencedor()) { 15 | System.out.println("Vencedor: " + melhorDeTres.getVencedor().getNome()); 16 | } else { 17 | System.out.println("Empate"); 18 | } 19 | System.out.println("Resultados:" + melhorDeTres.getResultados()); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/c10classes/ProceduralMain.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c10classes; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import refactown.cleancode.c03functions.PedraPapelTesoura; 7 | import refactown.cleancode.c10classes.enums.Mao; 8 | import refactown.cleancode.c10classes.enums.Resultado; 9 | import refactown.cleancode.c10classes.enums.ResultadoJogada; 10 | 11 | public class ProceduralMain { 12 | 13 | public static void main(String[] args) { 14 | int rodadas = 5; 15 | int scoreBill = 0; 16 | int scoreBob = 0; 17 | List resultados = new ArrayList(); 18 | Resultado resultadoDoprimeiro ; 19 | ResultadoJogada resultadoJogada ; 20 | char charBill; 21 | char charBob; 22 | for (int i=0; i < rodadas; i++) { 23 | charBill = Mao.aleatoria().getId(); 24 | charBob = Mao.aleatoria().getId(); 25 | resultadoDoprimeiro = Resultado.of(PedraPapelTesoura.pedraPapelTesoura(charBill, charBob)); 26 | resultadoJogada = ResultadoJogada.of(resultadoDoprimeiro); 27 | if (ResultadoJogada.PRIMEIRO_VENCE.equals(resultadoJogada)) { 28 | scoreBill++; 29 | } else if (ResultadoJogada.SEGUNDO_VENCE.equals(resultadoJogada)) { 30 | scoreBob++; 31 | } // empate não faz nada 32 | resultados.add(resultadoJogada); 33 | } 34 | // Print 35 | if (scoreBill > scoreBob) { 36 | System.out.println("Vencedor: Bill (Primeiro)"); 37 | } else if (scoreBob > scoreBill) { 38 | System.out.println("Vencedor: Bob (Segundo)"); 39 | } else { 40 | System.out.println("Empate"); 41 | } 42 | System.out.println("Resultados:" + resultados); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/c10classes/enums/Mao.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c10classes.enums; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | import java.util.Random; 6 | 7 | public enum Mao { 8 | 9 | PEDRA('R'), // ROCK = R 10 | TESOURA('S'), // SCISSORS = S 11 | PAPEL('P');// PAPER = P 12 | 13 | private static final Map VENCE = new HashMap(); 14 | 15 | static { 16 | VENCE.put(PAPEL, PEDRA); 17 | VENCE.put(TESOURA, PAPEL); 18 | VENCE.put(PEDRA, TESOURA); 19 | } 20 | 21 | private final char id; 22 | 23 | Mao(char id) { 24 | this.id = id; 25 | } 26 | 27 | public static Mao aleatoria() { 28 | return values()[Math.abs(new Random().ints().findFirst().getAsInt() %3)]; 29 | } 30 | public static Mao of(char letra){ 31 | for (Mao mao: values()){ 32 | if (mao.id == letra){ 33 | return mao; 34 | } 35 | } 36 | throw new IllegalArgumentException("Letra inválida:"+letra); 37 | } 38 | 39 | public boolean vence(Mao outraMao) { 40 | return VENCE.get(this) == outraMao; 41 | } 42 | public char getId() { 43 | return id; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/c10classes/enums/Resultado.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c10classes.enums; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | public enum Resultado { 7 | 8 | VENCE(-1), 9 | EMPATE(0), 10 | PERDE(1); 11 | 12 | private final int valor; 13 | 14 | private static final Map RESULTADOS 15 | = new HashMap(); 16 | 17 | static { 18 | RESULTADOS.put(-1, VENCE); 19 | RESULTADOS.put(0, EMPATE); 20 | RESULTADOS.put(1,PERDE); 21 | } 22 | 23 | Resultado(int valor) { 24 | this.valor = valor; 25 | } 26 | 27 | public static Resultado of(int valor) { 28 | return RESULTADOS.get(valor); 29 | } 30 | 31 | public int getValor() { 32 | return valor; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/c10classes/enums/ResultadoJogada.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c10classes.enums; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | public enum ResultadoJogada { 7 | 8 | PRIMEIRO_VENCE(Resultado.VENCE, Resultado.PERDE), 9 | EMPATE(Resultado.EMPATE, Resultado.EMPATE), 10 | SEGUNDO_VENCE(Resultado.PERDE, Resultado.VENCE); 11 | 12 | private final Resultado resultadoDoPrimeiro; 13 | private final Resultado resultadoDoSegundo; 14 | 15 | private static final Map JOGADAS = new HashMap(); 16 | 17 | static { 18 | JOGADAS.put(Resultado.VENCE, ResultadoJogada.PRIMEIRO_VENCE); 19 | JOGADAS.put(Resultado.EMPATE, ResultadoJogada.EMPATE); 20 | JOGADAS.put(Resultado.PERDE, ResultadoJogada.SEGUNDO_VENCE); 21 | } 22 | 23 | ResultadoJogada(Resultado resultadoDoPrimeiro, Resultado resultadoDoSegundo) { 24 | this.resultadoDoPrimeiro = resultadoDoPrimeiro; 25 | this.resultadoDoSegundo = resultadoDoSegundo; 26 | } 27 | 28 | public static ResultadoJogada of(Resultado resultadoDoPrimeiro) { 29 | return JOGADAS.get(resultadoDoPrimeiro); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/c10classes/model/Jogada.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c10classes.model; 2 | 3 | import refactown.cleancode.c10classes.enums.ResultadoJogada; 4 | 5 | public interface Jogada { 6 | 7 | ResultadoJogada jogar(); 8 | 9 | public Jogador getPrimeiroJogador(); 10 | 11 | public Jogador getSegundoJogador(); 12 | 13 | } -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/c10classes/model/JogadaLegada.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c10classes.model; 2 | 3 | import refactown.cleancode.c03functions.PedraPapelTesoura; 4 | import refactown.cleancode.c10classes.enums.Mao; 5 | import refactown.cleancode.c10classes.enums.Resultado; 6 | import refactown.cleancode.c10classes.enums.ResultadoJogada; 7 | 8 | public class JogadaLegada implements Jogada { 9 | private final Jogador primeiroJogador; 10 | private final Jogador segundoJogador; 11 | @Override 12 | public ResultadoJogada jogar() { 13 | Mao primeira = primeiroJogador.jogar(); 14 | Mao segunda = segundoJogador.jogar(); 15 | int resultInt = PedraPapelTesoura.pedraPapelTesoura(primeira.getId(), segunda.getId()); 16 | Resultado resultadoDoPrimeiro = Resultado.of(resultInt); 17 | return ResultadoJogada.of(resultadoDoPrimeiro); 18 | } 19 | 20 | public JogadaLegada(Jogador primeiroJogador, Jogador segundoJogador) { 21 | super(); 22 | this.primeiroJogador = primeiroJogador; 23 | this.segundoJogador = segundoJogador; 24 | } 25 | 26 | public Jogador getPrimeiroJogador() { 27 | return primeiroJogador; 28 | } 29 | 30 | public Jogador getSegundoJogador() { 31 | return segundoJogador; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/c10classes/model/JogadaSimples.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c10classes.model; 2 | 3 | import refactown.cleancode.c10classes.enums.Mao; 4 | import refactown.cleancode.c10classes.enums.ResultadoJogada; 5 | 6 | public class JogadaSimples implements Jogada{ 7 | @Override 8 | public ResultadoJogada jogar() { 9 | Mao primeiraMao = primeiroJogador.jogar(); 10 | Mao segundaMao = segundoJogador.jogar(); 11 | if (primeiraMao.vence(segundaMao)) { 12 | return ResultadoJogada.PRIMEIRO_VENCE; 13 | } 14 | if (segundaMao.vence(primeiraMao)) { 15 | return ResultadoJogada.SEGUNDO_VENCE; 16 | } 17 | return ResultadoJogada.EMPATE; 18 | } 19 | 20 | private final Jogador primeiroJogador; 21 | private final Jogador segundoJogador; 22 | public JogadaSimples(Jogador primeiroJogador, Jogador segundoJogador) { 23 | super(); 24 | if (primeiroJogador == null){ 25 | throw new NullPointerException("O primeiro jogador é obrigatório"); 26 | } 27 | if (segundoJogador == null){ 28 | throw new NullPointerException("O segundo jogador é obrigatório"); 29 | } 30 | this.primeiroJogador = primeiroJogador; 31 | this.segundoJogador = segundoJogador; 32 | } 33 | 34 | 35 | 36 | public Jogador getPrimeiroJogador() { 37 | return primeiroJogador; 38 | } 39 | 40 | public Jogador getSegundoJogador() { 41 | return segundoJogador; 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/c10classes/model/Jogador.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c10classes.model; 2 | 3 | import refactown.cleancode.c10classes.enums.Mao; 4 | 5 | public class Jogador { 6 | private final String nome; 7 | public Jogador(String nome) {super(); this.nome = nome;} 8 | public Mao jogar() { 9 | return Mao.aleatoria(); 10 | } 11 | public String getNome() { 12 | return nome; 13 | } 14 | @Override 15 | public String toString() { 16 | return "Jogador [nome=" + nome + "]"; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/c10classes/model/MelhorDeTres.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c10classes.model; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import refactown.cleancode.c10classes.enums.ResultadoJogada; 7 | 8 | public class MelhorDeTres { 9 | 10 | private final Jogada jogada; 11 | private final int rodadas; 12 | 13 | private int scoreDoPrimeiro; 14 | private int scoreDoSegundo; 15 | private int scoreVencedor; 16 | private List resultados = new ArrayList(); 17 | 18 | public MelhorDeTres(Jogada jogada) { 19 | this(jogada, 3); 20 | } 21 | 22 | public MelhorDeTres(Jogada jogada, int rodadas) { 23 | super(); 24 | this.jogada = jogada; 25 | this.rodadas = rodadas; 26 | scoreVencedor = rodadas / 2 + 1; 27 | } 28 | 29 | public void jogar() { 30 | for (int i=0; i < rodadas; i++) { 31 | ResultadoJogada resultadoJogada = jogada.jogar(); 32 | resultados.add(resultadoJogada); 33 | if (ResultadoJogada.PRIMEIRO_VENCE.equals(resultadoJogada)) { 34 | scoreDoPrimeiro++; 35 | } else if (ResultadoJogada.SEGUNDO_VENCE.equals(resultadoJogada)) { 36 | scoreDoSegundo ++; 37 | } 38 | if (jaTemVencedor()) break; 39 | } 40 | } 41 | 42 | public boolean temVencedor() { 43 | return scoreDoPrimeiro != scoreDoSegundo; 44 | } 45 | 46 | public Jogador getVencedor() { 47 | if (scoreDoPrimeiro > scoreDoSegundo) { 48 | return jogada.getPrimeiroJogador(); 49 | } 50 | if (scoreDoSegundo > scoreDoPrimeiro) { 51 | return jogada.getSegundoJogador(); 52 | } 53 | throw new IllegalStateException("Não houve vencedor. Foi empate!"); 54 | } 55 | 56 | private boolean jaTemVencedor() { 57 | return scoreDoPrimeiro >= scoreVencedor || scoreDoSegundo >= scoreVencedor; 58 | } 59 | 60 | public List getResultados() { 61 | return new ArrayList(resultados); 62 | } 63 | 64 | public int getScoreDoPrimeiro() { 65 | return scoreDoPrimeiro; 66 | } 67 | 68 | public int getScoreDoSegundo() { 69 | return scoreDoSegundo; 70 | } 71 | 72 | 73 | } 74 | 75 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/math/Math.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.math; 2 | 3 | 4 | import java.lang.reflect.Method; 5 | 6 | public class Math { 7 | 8 | public static int add(int a, int b) { 9 | return a + b; 10 | } 11 | 12 | public static int countIntResults(Class clazz){ 13 | int count = 0; 14 | Method[] methods = clazz.getMethods(); 15 | 16 | return count; 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/megasena/Aposta.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.megasena; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.Collections; 6 | import java.util.List; 7 | 8 | public class Aposta { 9 | 10 | private final List numeros; 11 | 12 | public Aposta(List numeros) { 13 | this.numeros = Collections.unmodifiableList(numeros);// cópia defensiva 14 | validarAposta(numeros); 15 | } 16 | 17 | public static Aposta of(Integer... numeros) { 18 | List numerosApostados =Arrays.asList(numeros); 19 | return new Aposta(numerosApostados); 20 | } 21 | 22 | public List getNumeros() { 23 | return numeros; 24 | } 25 | 26 | private List validarAposta(List numerosApostados) { 27 | if (numerosApostados.size() < 6) { 28 | throw new IllegalArgumentException("A aposta mínima é de 6 números"); 29 | } 30 | if (numerosApostados.size() > 15) { 31 | throw new IllegalArgumentException("A aposta máxima é de 15 números"); 32 | } 33 | 34 | List numerosValidos = new ArrayList<>(); 35 | for (Integer apostado : numerosApostados) { 36 | if (apostado < 1 || apostado > 60) { 37 | throw new IllegalArgumentException("Os números apostados devem estar entre 1 e 60"); // inválido 38 | } 39 | if (numerosValidos.contains(apostado)) { 40 | throw new IllegalArgumentException("Número duplicado:" + apostado); // repetido 41 | } 42 | numerosValidos.add(apostado); 43 | } 44 | return numerosValidos; 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/megasena/CalculadoraPremio.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.megasena; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import java.util.Random; 6 | 7 | /** 8 | * Classe que calcula o prêmio da Megasena a partir de um valor total e 9 | * dos números apostados e os sorteados. 10 | * Classe para o exercício de refatoração de um método muito grande e complexo. 11 | *

12 | * Versão Inicial {@link MegaSenaV1} 13 | * Versão Final {@link MegaSenaV5} 14 | */ 15 | public class CalculadoraPremio { 16 | 17 | public static final int ACERTOS_SENA = 6; 18 | public static final int ACERTOS_QUINA = 5; 19 | public static final int ACERTOS_QUADRA = 4; 20 | public static final double PREMIO_QUINA = 0.2; 21 | public static final double PREMIO_QUADRA = 0.05; 22 | 23 | public double calcula(Aposta aposta, List numerosSorteados, 24 | double premioTotal) { 25 | int acertos = contaAcertos(aposta.getNumeros(), numerosSorteados); 26 | 27 | if (acertos == ACERTOS_SENA) { 28 | return premioTotal; // Sena = 100% 29 | } else if (acertos == ACERTOS_QUINA) { 30 | return premioTotal * PREMIO_QUINA; // Quina = 20% 31 | } else if (acertos == ACERTOS_QUADRA) { 32 | return premioTotal * PREMIO_QUADRA; // Quadra = 5% 33 | } 34 | 35 | return 0.0; 36 | } 37 | 38 | private int contaAcertos(List numerosApostados, List numerosSorteados) { 39 | int acertos = 0; 40 | for (Integer apostado : numerosApostados) { 41 | if (numerosSorteados.contains(apostado)) { 42 | acertos++; 43 | } 44 | } 45 | return acertos; 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/megasena/MegaSenaV0.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.megasena; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import java.util.Random; 6 | 7 | public class MegaSenaV0 { 8 | 9 | 10 | public double megasena(List num, double valor) { 11 | List list = new ArrayList<>(); // válidos 12 | for (Integer n: num){ 13 | if (n <1 || n > 60){ 14 | return 0.0; // inválido 15 | } 16 | if (list.contains(n)){ 17 | return 0.0; // repetido 18 | } 19 | list.add(n); 20 | } 21 | if (list.size() >= 6 && list.size() <= 15) { 22 | List sort = new ArrayList<>(); 23 | int s; 24 | while (sort.size() < 6) { 25 | s = new Random().nextInt(59) + 1; 26 | if (!sort.contains(s)) { 27 | sort.add(s); 28 | } 29 | } 30 | int tot =0; 31 | for (Integer apostado: num){ 32 | if (sort.contains(apostado)){ 33 | tot++; 34 | } 35 | } 36 | if (tot ==6){ 37 | return valor; // 100% 38 | } else if (tot == 5){ 39 | return valor * 0.2; // 20% 40 | } else if (tot == 4){ 41 | return valor * 0.05; // 5% 42 | } 43 | } 44 | return 0.0; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/megasena/MegaSenaV1.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.megasena; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import java.util.Random; 6 | 7 | /** 8 | * Versão com nomes, formatação e comentários melhorados. 9 | * O método ainda é monolítico e muito grande (34 linhas). 10 | */ 11 | public class MegaSenaV1 { 12 | 13 | /** 14 | * Método que calcula o valor que uma certa aposta deve receber em função do número de acertos. 15 | * 16 | * @param numerosApostados Os números jogados em uma aposta. 17 | * @param premioTotal O valor to prêmio em relação ao número de acertos. 18 | * @return O valor do prêmio a ser recebido por esta aposta. 19 | */ 20 | public double calculaPremio(List numerosApostados, double premioTotal) { 21 | List numerosValidos = new ArrayList<>(); 22 | for (Integer apostado : numerosApostados) { 23 | if (apostado < 1 || apostado > 60) { 24 | return 0.0; // inválido 25 | } 26 | if (numerosValidos.contains(apostado)) { 27 | return 0.0; // repetido 28 | } 29 | numerosValidos.add(apostado); 30 | } 31 | 32 | if (numerosValidos.size() >= 6 && numerosValidos.size() <= 15) { 33 | List numerosSorteados = new ArrayList<>(); 34 | int numeroSorteado; 35 | while (numerosSorteados.size() < 6) { 36 | numeroSorteado = new Random().nextInt(59) + 1; 37 | if (!numerosSorteados.contains(numeroSorteado)) { 38 | numerosSorteados.add(numeroSorteado); 39 | } 40 | } 41 | 42 | int acertos = 0; 43 | for (Integer apostado : numerosApostados) { 44 | if (numerosSorteados.contains(apostado)) { 45 | acertos++; 46 | } 47 | } 48 | 49 | if (acertos == 6) { 50 | return premioTotal; // Sena = 100% 51 | } else if (acertos == 5) { 52 | return premioTotal * 0.2; // Quina = 20% 53 | } else if (acertos == 4) { 54 | return premioTotal * 0.05; // Quadra = 5% 55 | } 56 | } 57 | return 0.0; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/megasena/MegaSenaV2.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.megasena; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import java.util.Random; 6 | import java.util.stream.Collectors; 7 | 8 | /** 9 | * Versão refatoração do método para fazer somente uma coisa. 10 | * OS níveis de abstração foram separados em outros métodos. 11 | */ 12 | public class MegaSenaV2 { 13 | 14 | /** 15 | * Método que calcula o valor que uma certa aposta deve receber em função 16 | * do número de acertos. 17 | * 18 | * @param apostados Os números jogados em uma aposta. 19 | * @param premioTotal O valor to prêmio em relação ao número de acertos. 20 | * @return O valor do prêmio a ser recebido por esta aposta. 21 | */ 22 | public double calculaPremio(List apostados, double premioTotal) { 23 | if (!isApostaValida(apostados)) return 0.0; 24 | List sorteados = sorteiaSeisNumeros(); 25 | long acertos = calculaAcertos(apostados, sorteados); 26 | if (acertos == 6) { 27 | return premioTotal; // Sena = 100% 28 | } else if (acertos == 5) { 29 | return premioTotal * 0.2; // Quina = 20% 30 | } else if (acertos == 4) { 31 | return premioTotal * 0.05; // Quadra = 5% 32 | } 33 | return 0.0; 34 | } 35 | 36 | private boolean isApostaValida(List numerosApostados) { 37 | if (numerosApostados.size() < 6 || numerosApostados.size() > 15) { 38 | return false; 39 | } 40 | List numerosValidos = new ArrayList<>(); 41 | for (Integer apostado : numerosApostados) { 42 | if (apostado < 1 || apostado > 60) { 43 | return false; // inválido 44 | } 45 | if (numerosValidos.contains(apostado)) { 46 | return false; // repetido 47 | } 48 | numerosValidos.add(apostado); 49 | } 50 | return true; 51 | } 52 | 53 | private List sorteiaSeisNumeros() { 54 | List sorteados = new ArrayList<>(); 55 | int numeroSorteado; 56 | while (sorteados.size() < 6) { 57 | numeroSorteado = new Random().nextInt(59) + 1; 58 | if (!sorteados.contains(numeroSorteado)) { 59 | sorteados.add(numeroSorteado); 60 | } 61 | } 62 | return sorteados; 63 | } 64 | 65 | private int calculaAcertos(List apostados, List sorteados) { 66 | int acertos = 0; 67 | for (Integer apostado : apostados) { 68 | if (sorteados.contains(apostado)) { 69 | acertos++; 70 | } 71 | } 72 | return acertos; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/megasena/MegaSenaV3.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.megasena; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import java.util.Random; 6 | 7 | /** 8 | * Versão com otimização de código para leitura (mais expressivo e menor). 9 | * Uso da API de stream 10 | */ 11 | public class MegaSenaV3 { 12 | 13 | /** 14 | * Método que calcula o valor que uma certa aposta deve receber em função do número de acertos. 15 | * 16 | * @param apostados Os números jogados em uma aposta. 17 | * @param premioTotal O valor to prêmio em relação ao número de acertos. 18 | * @return O valor do prêmio a ser recebido por esta aposta. 19 | */ 20 | public double calculaPremio(List apostados, double premioTotal) { 21 | if (!isApostaValida(apostados)) return 0.0; 22 | List sorteados = sorteiaSeisNumeros(); 23 | long acertos = calculaAcertos(apostados, sorteados); 24 | if (acertos == 6) { 25 | return premioTotal; // Sena = 100% 26 | } else if (acertos == 5) { 27 | return premioTotal * 0.2; // Quina = 20% 28 | } else if (acertos == 4) { 29 | return premioTotal * 0.05; // Quadra = 5% 30 | } 31 | return 0.0; 32 | } 33 | 34 | private boolean isApostaValida(List numerosApostados) { 35 | return numerosApostados.size() >= 6 && numerosApostados.size() <= 15 && 36 | numerosApostados.stream().distinct().filter(n -> n >= 1 && n <= 60). 37 | count() == numerosApostados.size(); 38 | } 39 | 40 | private List sorteiaSeisNumeros() { 41 | List numerosSorteados = new ArrayList<>(); 42 | int numeroSorteado; 43 | while (numerosSorteados.size() < 6) { 44 | numeroSorteado = new Random().nextInt(59) + 1; 45 | if (!numerosSorteados.contains(numeroSorteado)) { 46 | numerosSorteados.add(numeroSorteado); 47 | } 48 | } 49 | return numerosSorteados; 50 | } 51 | 52 | private int calculaAcertos(List apostados, List sorteados) { 53 | return (int) apostados.stream().filter(n -> sorteados.contains(n)).count(); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/megasena/MegaSenaV4.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.megasena; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import java.util.Random; 6 | 7 | /** 8 | * Versão que dispara exceção para aposta inválida. 9 | * Apostas que não acertam nada recebem zero, mas inválidas geram erro. 10 | */ 11 | public class MegaSenaV4 { 12 | 13 | /** 14 | * Método que calcula o valor que uma certa aposta deve receber em função do número de acertos. 15 | * 16 | * @param apostados Os números jogados em uma aposta. 17 | * @param premioTotal O valor to prêmio em relação ao número de acertos. 18 | * @return O valor do prêmio a ser recebido por esta aposta. 19 | * @throws IllegalArgumentException se a aposta for inválida 20 | */ 21 | public double calculaPremio(List apostados, double premioTotal) { 22 | if (!isApostaValida(apostados)) { 23 | throw new IllegalArgumentException("Aposta inválida:" + apostados); 24 | } 25 | List sorteados = sorteiaSeisNumeros(); 26 | long acertos = calculaAcertos(apostados, sorteados); 27 | if (acertos == 6) { 28 | return premioTotal; // Sena = 100% 29 | } else if (acertos == 5) { 30 | return premioTotal * 0.2; // Quina = 20% 31 | } else if (acertos == 4) { 32 | return premioTotal * 0.05; // Quadra = 5% 33 | } 34 | return 0.0; 35 | } 36 | 37 | private boolean isApostaValida(List numerosApostados) { 38 | return numerosApostados.size() >= 6 && numerosApostados.size() <= 15 && 39 | numerosApostados.stream().distinct().filter(n -> n >= 1 && n <= 60). 40 | count() == numerosApostados.size(); 41 | } 42 | 43 | private List sorteiaSeisNumeros() { 44 | List numerosSorteados = new ArrayList<>(); 45 | int numeroSorteado; 46 | while (numerosSorteados.size() < 6) { 47 | numeroSorteado = new Random().nextInt(59) + 1; 48 | if (!numerosSorteados.contains(numeroSorteado)) { 49 | numerosSorteados.add(numeroSorteado); 50 | } 51 | } 52 | return numerosSorteados; 53 | } 54 | 55 | private int calculaAcertos(List apostados, List sorteados) { 56 | return (int) apostados.stream().filter(n -> sorteados.contains(n)).count(); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/megasena/MegaSenaV5.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.megasena; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * Versão com maior testabilidade por receber os números sorteados. 7 | * O sorteio randômico impede o teste de unidade. 8 | */ 9 | public class MegaSenaV5 { 10 | 11 | /** 12 | * Método que calcula o valor que uma certa aposta deve receber em função do número de acertos. 13 | * 14 | * @param apostados Os números jogados em uma aposta. 15 | * @param sorteados Os números previamente sorteados 16 | * @param premioTotal O valor to prêmio em relação ao número de acertos. 17 | * @return O valor do prêmio a ser recebido por esta aposta. 18 | * @throws IllegalArgumentException se a aposta for inválida 19 | */ 20 | public double calculaPremio(List apostados, List sorteados, double premioTotal) { 21 | if (!isApostaValida(apostados)) { 22 | throw new IllegalArgumentException("Aposta inválida:" + apostados); 23 | } 24 | long acertos = calculaAcertos(apostados, sorteados); 25 | if (acertos == 6) { 26 | return premioTotal; // Sena = 100% 27 | } else if (acertos == 5) { 28 | return premioTotal * 0.2; // Quina = 20% 29 | } else if (acertos == 4) { 30 | return premioTotal * 0.05; // Quadra = 5% 31 | } 32 | return 0.0; 33 | } 34 | 35 | private boolean isApostaValida(List numerosApostados) { 36 | return numerosApostados.size() >= 6 && numerosApostados.size() <= 15 && 37 | numerosApostados.stream().distinct().filter(n -> n >= 1 && n <= 60). 38 | count() == numerosApostados.size(); 39 | } 40 | 41 | private int calculaAcertos(List apostados, List sorteados) { 42 | return (int) apostados.stream().filter(n -> sorteados.contains(n)).count(); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/megasena/modelo/Apostador.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.megasena.modelo; 2 | 3 | import java.util.Objects; 4 | 5 | /** 6 | * Representa um apostador que fez uma aposta. Uma aposta pode ter vários apostadores (bolão). 7 | */ 8 | public class Apostador { 9 | 10 | private final Cpf cpf; 11 | 12 | public Apostador(Cpf cpf) { 13 | if (cpf == null){ 14 | throw new NullPointerException("O CPF do apostador não pode ser nulo!"); 15 | } 16 | this.cpf = cpf; 17 | } 18 | 19 | public Cpf getCpf() { 20 | return cpf; 21 | } 22 | 23 | @Override 24 | public boolean equals(Object o) { 25 | if (this == o) return true; 26 | if (o == null || getClass() != o.getClass()) return false; 27 | Apostador apostador = (Apostador) o; 28 | return Objects.equals(cpf, apostador.cpf); 29 | } 30 | 31 | @Override 32 | public int hashCode() { 33 | return Objects.hash(cpf); 34 | } 35 | 36 | @Override 37 | public String toString() { 38 | return cpf.toString(); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/megasena/modelo/Bilhete.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.megasena.modelo; 2 | 3 | import refactown.cleancode.c10classes.Result; 4 | import refactown.cleancode.megasena.v6.Aposta; 5 | import refactown.cleancode.megasena.v6.Resultado; 6 | 7 | import java.util.List; 8 | import java.util.Objects; 9 | import java.util.stream.Collectors; 10 | 11 | /** 12 | * O Bilhete é a relação de um apostador principal (volante) com várias apostas. 13 | * Cada bilhete tem um número de identificação que o torna uma entidade. 14 | * Nesta "Mega Sena" a identificação do apostador volante (principal) é obrigatória). 15 | */ 16 | public class Bilhete { 17 | 18 | private final String numero; // identificadores são String mesmo sendo "número" 19 | 20 | private final Apostador volante; // volante = apostador principal que faz a aposta 21 | 22 | private final List apostas; 23 | 24 | public Bilhete(String numero, Apostador volante, List apostas) { 25 | Objects.requireNonNull(numero, "O número não pode ser nulo"); 26 | Objects.requireNonNull(volante, "O apostador 'volante' não pode ser nulo"); 27 | Objects.requireNonNull(apostas, "O atributo 'apostas' não pode ser nulo"); 28 | if (numero.chars().filter(c-> !Character.isDigit(c)).count() > 0){ 29 | throw new IllegalArgumentException("O número do bilhete deve ser composto somente por números"); 30 | } 31 | if (apostas.size() > quantidadeMaximaApostas()){ 32 | throw new QuantidadeApostasException(quantidadeMaximaApostas(), apostas.size()); 33 | } 34 | this.numero = numero; 35 | this.volante = volante; 36 | this.apostas = apostas; 37 | } 38 | 39 | protected int quantidadeMaximaApostas(){ 40 | return 3; 41 | } 42 | 43 | public String getNumero() { 44 | return numero; 45 | } 46 | 47 | public Apostador getVolante() { 48 | return volante; 49 | } 50 | 51 | public List getApostas() { 52 | return apostas; 53 | } 54 | 55 | public List getApostasByAcerto(int acertos, Resultado resultado) { 56 | return apostas.stream().filter(a-> a.calculaAcertos(resultado) == acertos).collect(Collectors.toList()); 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/megasena/modelo/Bolao.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.megasena.modelo; 2 | 3 | import refactown.cleancode.megasena.v6.Aposta; 4 | 5 | import java.util.Collections; 6 | import java.util.List; 7 | import java.util.Objects; 8 | 9 | public class Bolao extends Bilhete{ 10 | 11 | private final List participantes; 12 | 13 | public Bolao(String numero, Apostador volante, List apostas, List participantes) { 14 | super(numero, volante, apostas); 15 | Objects.requireNonNull(participantes, "Atributo 'participantes' não pode sr nulo"); 16 | if (!apostadoresValidos(participantes)){ 17 | throw new IllegalArgumentException("Participantes inválidos:"); 18 | } 19 | this.participantes = Collections.unmodifiableList(participantes); 20 | } 21 | 22 | private boolean apostadoresValidos(List apostadores) { 23 | return true; 24 | } 25 | 26 | @Override 27 | protected int quantidadeMaximaApostas() { 28 | return 10; 29 | } 30 | 31 | private boolean apostasComMesmoTamanho() { 32 | int tamanho = getApostas().get(0).getNumeros().size(); 33 | return getApostas().stream() 34 | .filter(a-> a.getNumeros().size()!=tamanho).count()==0; 35 | } 36 | 37 | public List getParticipantes() { 38 | return participantes; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/megasena/modelo/BolaoBuilder.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.megasena.modelo; 2 | 3 | import refactown.cleancode.megasena.v6.Aposta; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | /** 9 | * Builder para construção de uma instância de Bolao. 10 | */ 11 | public class BolaoBuilder { 12 | 13 | private String numero; 14 | private Apostador volante; 15 | private List apostas = new ArrayList<>(); 16 | private List participantes = new ArrayList<>(); 17 | 18 | public BolaoBuilder numero(String numero){ 19 | if (numero != null){ 20 | throw new IllegalStateException("Atributo número já foi definido:" + numero); 21 | } 22 | if (numero.chars().filter(c-> !Character.isDigit(c)).count() > 0){ 23 | throw new IllegalArgumentException("O número do bolão deve ser composto somente por números"); 24 | } 25 | this.numero = numero; 26 | return this; 27 | } 28 | 29 | public BolaoBuilder apostadorVolante(Apostador volante){ 30 | if (volante != null){ 31 | throw new IllegalStateException("O apostador volante já foi definido"); 32 | } 33 | this.volante = volante; 34 | participantes.add(volante); 35 | return this; 36 | } 37 | 38 | BolaoBuilder aposta(Aposta aposta){ 39 | apostas.add(aposta); 40 | return this; 41 | } 42 | 43 | BolaoBuilder participante(Apostador participante){ 44 | if (participantes.contains(participante)){ 45 | throw new IllegalArgumentException("Participante '" + participante + "' já está na lista"); 46 | } 47 | participantes.add(participante); 48 | return this; 49 | } 50 | 51 | public Bolao build(){ 52 | return new Bolao(numero, volante, apostas, participantes); 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/megasena/modelo/Concurso.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.megasena.modelo; 2 | 3 | import refactown.cleancode.megasena.v6.Resultado; 4 | import refactown.cleancode.megasena.v6.TipoPremio; 5 | 6 | import java.util.*; 7 | import java.util.stream.Collectors; 8 | 9 | /** 10 | * Representa o conjunto de bilhetes de um concurso bem como seu resultado. 11 | * É uma entidade identificda por seu número único. 12 | */ 13 | public class Concurso { 14 | 15 | private final String numero; 16 | private final List bilhetes = new ArrayList<>(); 17 | private Resultado resultado; 18 | 19 | 20 | public Concurso(String numero) { 21 | Objects.requireNonNull(numero, "O número não pode ser nulo"); 22 | if (numero.chars().filter(c -> !Character.isDigit(c)).count() > 0) { 23 | throw new IllegalArgumentException("O número do concurso deve ser composto somente por números"); 24 | } 25 | this.numero = numero; 26 | } 27 | 28 | /** 29 | * Informa se o concurso está aberto (aceitando novas apostas) ou encerrado (já tem resultado). 30 | * 31 | * @return truu se estiver encerrado ou false se não estiver. 32 | */ 33 | public boolean isEncerrado() { 34 | return resultado != null; 35 | } 36 | 37 | public String getNumero() { 38 | return numero; 39 | } 40 | 41 | public void add(Bilhete bilhete) { 42 | if (isEncerrado()) { 43 | throw new IllegalStateException("O concurso já está encerrado a não aceita novas apostas"); 44 | } 45 | if (bilhetes.contains(bilhete)) { 46 | throw new IllegalArgumentException("Bilhete já presente no concurso:" + bilhete); 47 | } 48 | bilhetes.add(bilhete); 49 | } 50 | 51 | public void addAll(Collection novosBilhetes) { 52 | novosBilhetes.forEach(b -> add(b)); 53 | } 54 | 55 | public List getBilhetes() { 56 | return new ArrayList(bilhetes); // cópia defensiva 57 | } 58 | 59 | public Resultado getResultado() { 60 | return resultado; 61 | } 62 | 63 | public void setResultado(Resultado resultado) { 64 | this.resultado = resultado; 65 | } 66 | 67 | /** 68 | * Filtra os bilhetes premiados e retorna uma lista deles. 69 | * 70 | * @param tipoPremio O tipo de prêmio que se deseja filtrar: Sena, Quina ou Quadra. 71 | * @return Uma lista com os bilhetes premiados ou vazia se nenhum bilhete tiver sido premiado para o tipo selecionado. 72 | */ 73 | public List filtraPremiados(TipoPremio tipoPremio) { 74 | return filtraBilhetesPorAcerto(tipoPremio.getAcertos()); 75 | } 76 | 77 | /** 78 | * Filtra os bilhetes com ao menos uma aposta com o número de acertos definida no parâmetro. 79 | * 80 | * @param acertos o número de acertos usado para filtrar os bilhetes. 81 | * @return Uma lista com os bilhetes premiados ou vazia se nenhum bilhete tiver sido premiado para o tipo selecionado. 82 | */ 83 | public List filtraBilhetesPorAcerto(int acertos) { 84 | return bilhetes.stream() 85 | .filter(b -> !b.getApostasByAcerto(acertos, resultado).isEmpty()) 86 | .collect(Collectors.toList()); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/megasena/modelo/Cpf.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.megasena.modelo; 2 | 3 | import java.util.Objects; 4 | 5 | /** 6 | * Representa um número no Cadastro Nacional de Pessoa Física (CPF). 7 | * É usado para identificar o apostador. 8 | */ 9 | public class Cpf { 10 | 11 | private final String numero; 12 | 13 | public Cpf(String numero) { 14 | Objects.requireNonNull(numero, "O número não pode ser nulo"); 15 | String semTracoOuPontos = semTracoOuPontos(numero); 16 | String somenteNumeros = somenteNumeros(semTracoOuPontos); 17 | if (!semTracoOuPontos.equals(somenteNumeros)) { 18 | throw new IllegalArgumentException("CPF com caracteres inválidos:" + numero); 19 | } 20 | if (!isValido(somenteNumeros)) { 21 | throw new IllegalArgumentException("CPF de tamanho inválido:" + numero); 22 | } 23 | this.numero = somenteNumeros; 24 | } 25 | 26 | private String semTracoOuPontos(String numeroNaoTratado) { 27 | return numeroNaoTratado.replaceAll("\\.", "").replaceAll("-", ""); 28 | } 29 | 30 | private String somenteNumeros(String numeroNaoTratado) { 31 | return numeroNaoTratado.chars().filter(c -> Character.isDigit(c)) 32 | .collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append) 33 | .toString(); 34 | } 35 | 36 | private boolean isValido(String numero) { 37 | return numero.length() == 11; // TODO validar DV 38 | } 39 | 40 | @Override 41 | public boolean equals(Object obj) { 42 | if (obj == null) return false; 43 | if (obj == this) return true; 44 | if (obj instanceof Cpf) { 45 | Cpf other = (Cpf) obj; 46 | return numero.equals(other.numero); 47 | } 48 | return false; 49 | } 50 | 51 | @Override 52 | public int hashCode() { 53 | return numero.hashCode(); 54 | } 55 | 56 | @Override 57 | public String toString() { 58 | return numero; 59 | } 60 | 61 | public String getNumero() { 62 | return numero; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/megasena/modelo/QuantidadeApostasException.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.megasena.modelo; 2 | 3 | /** 4 | * Exceção gerada quando há a tentativa de registrar um bilhete ou bolão com a quantidade inválida de apostas. 5 | * Nestes casoso sistema deve recomendar que o usuário remova alguma (se excedeu). 6 | */ 7 | public class QuantidadeApostasException extends RuntimeException { 8 | 9 | private final int maximo; 10 | private final int jogado; 11 | 12 | public QuantidadeApostasException(int maximo, int jogado) { 13 | super("A quantidade máxima de apostas é" + maximo + ", mas foram jogadas " + jogado); 14 | this.maximo = maximo; 15 | this.jogado = jogado; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/megasena/v6/Aposta.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.megasena.v6; 2 | 3 | import java.util.Collections; 4 | import java.util.List; 5 | import java.util.Objects; 6 | 7 | /** 8 | * Representa uma aposta feita por um apostador. Ou seja, um conjunto de 6 a 15 números entre 1 e 60. 9 | * A aposta tem um estado imutável e não tem identidade única, sendo um "Value Object" com números. 10 | */ 11 | public class Aposta { 12 | 13 | public static final int MENOR = 6; 14 | public static final int MAIOR = 15; 15 | public static final int PRIMEIRO_NUMERO = 1; 16 | public static final int ULTIMO_NUMERO = 60; 17 | 18 | private final List numeros; 19 | 20 | public Aposta(List numeros){ 21 | if (!isApostaValida(numeros)){ 22 | throw new IllegalArgumentException("Aposta inválida:" + numeros); 23 | } 24 | this.numeros = Collections.unmodifiableList(numeros); // cópia defensiva 25 | } 26 | 27 | private boolean isApostaValida(List numerosApostados) { 28 | return numerosApostados.size() >= MENOR && numerosApostados.size() <= MAIOR && 29 | numerosApostados.stream(). 30 | distinct().filter(n -> n >= PRIMEIRO_NUMERO && n <= ULTIMO_NUMERO). 31 | count() == numerosApostados.size(); 32 | } 33 | 34 | public int calculaAcertos(Resultado resultado){ 35 | return (int) numeros.stream().filter(n -> resultado.foiSorteado(n)).count(); 36 | } 37 | 38 | public List getNumeros() { 39 | return numeros; 40 | } 41 | 42 | @Override 43 | public boolean equals(Object o) { 44 | if (this == o) return true; 45 | if (o == null || getClass() != o.getClass()) return false; 46 | Aposta aposta = (Aposta) o; 47 | return Objects.equals(numeros, aposta.numeros); 48 | } 49 | 50 | @Override 51 | public int hashCode() { 52 | return Objects.hash(numeros); 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/megasena/v6/GloboGiratorio.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.megasena.v6; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import java.util.Random; 6 | 7 | /** 8 | * Classe que gera um resultado similado ao de um sorteio de N números. 9 | * Retorna uma instância pronta de Resultado. 10 | */ 11 | public class GloboGiratorio { 12 | 13 | private final int ultimoNumero; 14 | 15 | public GloboGiratorio(int ultimoNumero) { 16 | this.ultimoNumero = ultimoNumero; 17 | } 18 | 19 | public Resultado sorteiaNumeros(int quantidade) { 20 | if (quantidade > ultimoNumero) { 21 | String msg = "A quantidade a ser sorteada '%d' supera a quantidade de números disponíveis '%d'!"; 22 | throw new IllegalArgumentException(String.format(msg, quantidade, ultimoNumero)); 23 | } 24 | List numerosSorteados = new ArrayList<>(); 25 | int numeroSorteado; 26 | while (numerosSorteados.size() < quantidade) { 27 | numeroSorteado = new Random().nextInt(ultimoNumero - 1) + 1; 28 | if (!numerosSorteados.contains(numeroSorteado)) { 29 | numerosSorteados.add(numeroSorteado); 30 | } 31 | } 32 | return new Resultado(numerosSorteados); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/megasena/v6/Premio.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.megasena.v6; 2 | 3 | import java.util.Optional; 4 | 5 | /** 6 | * Prêmio a ser pago para os acertadores dependendo do número de acertos da aposta. 7 | * O cálculo do prêmio pago é feito em funçao da aposta e do resultado do sorteio. 8 | */ 9 | public class Premio { // equivalente a MegaSenaV6 10 | 11 | private final double valor; 12 | 13 | public Premio(double valor) { 14 | this.valor = valor; 15 | } 16 | 17 | public double calcula(Aposta aposta, Resultado resultado){ 18 | int acertos = aposta.calculaAcertos(resultado); 19 | Optional tipoPremio = TipoPremio.of(acertos); 20 | return tipoPremio.isPresent()? tipoPremio.get().calculaValor(valor): 0.0; 21 | } 22 | 23 | public double getValor(){ 24 | return valor; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/megasena/v6/Resultado.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.megasena.v6; 2 | 3 | import java.util.Collections; 4 | import java.util.List; 5 | 6 | /** 7 | * Classe que representa um resultado de um sorteio que pode ser informado no construtor ou gerado randomicamente. 8 | */ 9 | public class Resultado { 10 | 11 | private final List numeros; 12 | 13 | public Resultado(List numeros) { 14 | this.numeros = Collections.unmodifiableList(numeros); // cópia defensiva 15 | } 16 | 17 | public boolean foiSorteado(Integer numero) { 18 | return numeros.contains(numero); 19 | } 20 | 21 | public List getNumeros() { 22 | return numeros; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/refactown/cleancode/megasena/v6/TipoPremio.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.megasena.v6; 2 | 3 | import java.util.Optional; 4 | 5 | /** 6 | * Enum com os três tipos possíveis de prêmio: Sena, Quina e Quadra 7 | */ 8 | public enum TipoPremio { 9 | 10 | SENA(6, 100.0, 62.0), 11 | QUINA(5, 20.0, 19.0), 12 | QUADRA(4, 5.0, 19.0); 13 | 14 | private final int acertos; 15 | private final double percentual; // regra inventada para o exercício 16 | private final double rateio; // regra da Mega Sena real 17 | 18 | TipoPremio(int acertos, double percentual, double rateio) { 19 | this.acertos = acertos; 20 | this.percentual = percentual; 21 | this.rateio = rateio; 22 | } 23 | 24 | public static Optional of(int acertos){ 25 | for (TipoPremio tipoPremio: values()){ 26 | if (tipoPremio.acertos==acertos){ 27 | return Optional.of(tipoPremio); 28 | } 29 | } 30 | return Optional.empty(); 31 | } 32 | 33 | public double calculaValor(double premioTotal){ 34 | return premioTotal * (percentual / 100); 35 | } 36 | 37 | public int getAcertos() { 38 | return acertos; 39 | } 40 | 41 | public double getPercentual() { 42 | return percentual; 43 | } 44 | 45 | public double getRateio() { 46 | return rateio; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/tdc2020poa/Disputa.java: -------------------------------------------------------------------------------- 1 | package tdc2020poa; 2 | /** 3 | * Representa uma disputa entre dois jogadores que 4 | * pode ocorrer inúmeras vezes. A disputa ocorre quando 5 | * é chamado seu método "jogar" e cada jogador informa sua mão. 6 | */ 7 | public abstract class Disputa { 8 | private final Jogador primeiroJogador; 9 | private final Jogador segundoJogador; 10 | 11 | public Disputa(Jogador primeiroJogador, Jogador segundoJogador) { 12 | super(); 13 | this.primeiroJogador = primeiroJogador; 14 | this.segundoJogador = segundoJogador; 15 | } 16 | 17 | public abstract Resultado jogar(); 18 | 19 | public Jogador getPrimeiroJogador() { 20 | return primeiroJogador; 21 | } 22 | public Jogador getSegundoJogador() { 23 | return segundoJogador; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/tdc2020poa/DisputaLegada.java: -------------------------------------------------------------------------------- 1 | package tdc2020poa; 2 | 3 | /** Disputa que usa o código legado "PTP". */ 4 | public class DisputaLegada extends Disputa{ 5 | 6 | public DisputaLegada(Jogador primeiroJogador, Jogador segundoJogador) { 7 | super(primeiroJogador, segundoJogador); 8 | } 9 | 10 | @Override public Resultado jogar() { 11 | Mao primeira = getPrimeiroJogador().jogar(); 12 | Mao segunda = getSegundoJogador().jogar(); 13 | PTP ptp = new PTP(); 14 | int resultadoInt = ptp.jogar(primeira.getId(), segunda.getId()); 15 | return Resultado.of(resultadoInt); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/tdc2020poa/DisputaNova.java: -------------------------------------------------------------------------------- 1 | package tdc2020poa; 2 | 3 | /** Disputa que refaz a regra de negócio e abandona "PTP". */ 4 | public class DisputaNova extends Disputa{ 5 | 6 | public DisputaNova(Jogador primeiroJogador, Jogador segundoJogador) { 7 | super(primeiroJogador, segundoJogador); 8 | } 9 | 10 | @Override public Resultado jogar() { 11 | Mao primeira = getPrimeiroJogador().jogar(); 12 | Mao segunda = getSegundoJogador().jogar(); 13 | if (primeira.vence(segunda)){ 14 | return Resultado.PRIMEIRO_VENCE; 15 | } else if (segunda.vence(primeira)){ 16 | return Resultado.SEGUNDO_VENCE; 17 | } 18 | return Resultado.EMPATE; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/tdc2020poa/Jogador.java: -------------------------------------------------------------------------------- 1 | package tdc2020poa; 2 | 3 | /** 4 | * Representa um Jogador com seu nome 5 | * e sua capacidade e retornar a mão desejada. 6 | */ 7 | public class Jogador { 8 | private final String nome; 9 | public Jogador(String nome) {super(); this.nome = nome;} 10 | public Mao jogar() { 11 | return Mao.aleatoria(); 12 | } 13 | public String getNome() { 14 | return nome; 15 | } 16 | @Override 17 | public String toString() { 18 | return "Jogador [nome=" + nome + "]"; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/tdc2020poa/Jogo.java: -------------------------------------------------------------------------------- 1 | package tdc2020poa; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | public class Jogo { 7 | private final Disputa disputa; 8 | private final int rodadas; 9 | private int scoreDoPrimeiro; 10 | private int scoreDoSegundo; 11 | private int scoreVencedor; 12 | private List resultados = new ArrayList(); 13 | 14 | public Jogo(Disputa disputa) { 15 | this(disputa, 3); 16 | } 17 | 18 | public Jogo(Disputa disputa, int rodadas) { 19 | super(); 20 | this.disputa = disputa; 21 | this.rodadas = rodadas; 22 | scoreVencedor = rodadas / 2 + 1; 23 | } 24 | 25 | public void jogar() { 26 | for (int i=0; i < rodadas; i++) { 27 | Resultado resultado = disputa.jogar(); 28 | resultados.add(resultado); 29 | if (Resultado.PRIMEIRO_VENCE.equals(resultado)) { 30 | scoreDoPrimeiro++; 31 | } else if (Resultado.SEGUNDO_VENCE.equals(resultado)) { 32 | scoreDoSegundo ++; 33 | } 34 | if (jaTemVencedor()) break; 35 | } 36 | } 37 | 38 | public boolean temVencedor() { 39 | return scoreDoPrimeiro != scoreDoSegundo; 40 | } 41 | 42 | public Jogador getVencedor() { 43 | if (scoreDoPrimeiro > scoreDoSegundo) { 44 | return disputa.getPrimeiroJogador(); 45 | } 46 | if (scoreDoSegundo > scoreDoPrimeiro) { 47 | return disputa.getSegundoJogador(); 48 | } 49 | throw new IllegalStateException("Não houve vencedor. Foi empate!"); 50 | } 51 | 52 | private boolean jaTemVencedor() { 53 | return scoreDoPrimeiro >= scoreVencedor || scoreDoSegundo >= scoreVencedor; 54 | } 55 | 56 | public List getResultados() { 57 | return new ArrayList(resultados); 58 | } 59 | 60 | public int getScoreDoPrimeiro() { 61 | return scoreDoPrimeiro; 62 | } 63 | 64 | public int getScoreDoSegundo() { 65 | return scoreDoSegundo; 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/tdc2020poa/Mao.java: -------------------------------------------------------------------------------- 1 | package tdc2020poa; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | import java.util.Random; 6 | 7 | public enum Mao { 8 | PEDRA('R'), // ROCK = R 9 | TESOURA('S'), // SCISSORS = S 10 | PAPEL('P');// PAPER = P 11 | private static final Map VENCE = new HashMap(); 12 | static { 13 | VENCE.put(PAPEL, PEDRA); 14 | VENCE.put(TESOURA, PAPEL); 15 | VENCE.put(PEDRA, TESOURA); 16 | } 17 | private final char id; 18 | Mao(char id) { 19 | this.id = id; 20 | } 21 | public static Mao aleatoria() { 22 | return values()[Math.abs(new Random().ints().findFirst().getAsInt() %3)]; 23 | } 24 | public static Mao of(char letra){ 25 | for (Mao mao: values()){ 26 | if (mao.id == letra){ 27 | return mao; 28 | } 29 | } 30 | throw new IllegalArgumentException("Letra inválida:"+letra); 31 | } 32 | public boolean vence(Mao outraMao) {return VENCE.get(this) == outraMao; } 33 | public char getId() {return id; } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/tdc2020poa/PTP.java: -------------------------------------------------------------------------------- 1 | package tdc2020poa; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | 6 | import static java.util.Arrays.asList; 7 | 8 | /** 9 | * PTP = Pedra, Tesoura e Papel 10 | * Classe que contém a regra de negócio do jogo "Pedra, Tesoura e Papel" 11 | */ 12 | public class PTP { 13 | public static final char PEDRA = 'R'; // ROCK 14 | public static final char TESOURA = 'S'; // SCISSORS 15 | public static final char PAPEL = 'P'; // PAPER 16 | private static final List VALIDAS = asList(PEDRA, TESOURA, PAPEL); 17 | public static final short PRIMEIRO_VENCE = -1; 18 | public static final short EMPATE = 0; 19 | public static final short SEGUNDO_VENCE = 1; 20 | 21 | // EMPATE = 0 -1 1 22 | public int jogar(char primeira, char segunda) { // Ciclomática=11 Cognitiva=17 23 | if (!VALIDAS.contains(primeira)) { 24 | throw new IllegalArgumentException("Primeira letra inválida:" + primeira + ". Válidas=" + VALIDAS); 25 | } 26 | if (!VALIDAS.contains(segunda)) { 27 | throw new IllegalArgumentException("Segunda letra inválida:" + segunda + ". Válidas=" + VALIDAS); 28 | } 29 | if (primeira == PEDRA) { 30 | if (segunda == PAPEL) return SEGUNDO_VENCE; 31 | else if (segunda == TESOURA) return PRIMEIRO_VENCE; 32 | else return EMPATE; 33 | } else if (primeira == PAPEL) { 34 | if (segunda == TESOURA) return SEGUNDO_VENCE; 35 | else if (segunda == PEDRA) return PRIMEIRO_VENCE; 36 | else return EMPATE; 37 | } else { // TESOURA 38 | if (segunda == PEDRA) return SEGUNDO_VENCE; 39 | else if (segunda == PAPEL) return PRIMEIRO_VENCE; 40 | else return EMPATE; 41 | } 42 | } 43 | 44 | public int jogar(Rodada rodada){ // Ciclomática=9 Cognitiva=15 45 | if (rodada.getPrimeira() == PEDRA) { 46 | if (rodada.getSegunda() == PAPEL) return SEGUNDO_VENCE; 47 | else if (rodada.getSegunda() == TESOURA) return PRIMEIRO_VENCE; 48 | else return EMPATE; 49 | } else if (rodada.getPrimeira() == PAPEL) { 50 | if (rodada.getSegunda() == TESOURA) return SEGUNDO_VENCE; 51 | else if (rodada.getSegunda() == PEDRA) return PRIMEIRO_VENCE; 52 | else return EMPATE; 53 | } else { // TESOURA 54 | if (rodada.getSegunda() == PEDRA) return SEGUNDO_VENCE; 55 | else if (rodada.getSegunda() == PAPEL) return PRIMEIRO_VENCE; 56 | else return EMPATE; 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/tdc2020poa/Resultado.java: -------------------------------------------------------------------------------- 1 | package tdc2020poa; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | 7 | public enum Resultado { 8 | PRIMEIRO_VENCE(-1), 9 | EMPATE(0), 10 | SEGUNDO_VENCE(1); 11 | 12 | private final int valor; 13 | 14 | private static final Map RESULTADOS 15 | = new HashMap(); 16 | static { 17 | RESULTADOS.put(PRIMEIRO_VENCE.valor, PRIMEIRO_VENCE); 18 | RESULTADOS.put(EMPATE.valor, EMPATE); 19 | RESULTADOS.put(SEGUNDO_VENCE.valor, SEGUNDO_VENCE); 20 | } 21 | 22 | Resultado(int valor) { 23 | this.valor = valor; 24 | } 25 | 26 | public static Resultado of(int valor) { 27 | if (!RESULTADOS.containsKey(valor)){ 28 | throw new IllegalArgumentException("Valor inválido para um resultado:"+ valor); 29 | } 30 | return RESULTADOS.get(valor); 31 | } 32 | public int getValor() { return valor; } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/tdc2020poa/Rodada.java: -------------------------------------------------------------------------------- 1 | package tdc2020poa; 2 | 3 | import java.util.List; 4 | import java.util.Objects; 5 | 6 | import static java.util.Arrays.asList; 7 | 8 | /** 9 | * Representa uma rodada de uma rodada de "Pedra, Tesoura e Papel". Cada rodada 10 | * é composta por duas "mãos" representadas por suas letras (R, S ou P). 11 | * Não é possível criar uma rodada sem que as duas opções estejam entre 12 | * estas trẽs letras. Dessa forma uma instância de Rodada sempre 13 | * tem um estado válido e imutável. 14 | * Se as mãos mudarem significa que é uma outra rodada e deve ser criada uma outra 15 | * instância desta classe. 16 | */ 17 | public class Rodada { 18 | private static final List VALIDAS = asList(PTP.PEDRA, PTP.TESOURA, PTP.PAPEL); 19 | 20 | private final char primeira; 21 | private final char segunda; 22 | 23 | public Rodada(char primeira, char segunda) { 24 | if (!VALIDAS.contains(primeira)) { 25 | throw new IllegalArgumentException("Primeira letra inválida:" + primeira + ". Válidas=" + VALIDAS); 26 | } 27 | if (!VALIDAS.contains(segunda)) { 28 | throw new IllegalArgumentException("Segunda letra inválida:" + segunda + ". Válidas=" + VALIDAS); 29 | } 30 | this.primeira = primeira; 31 | this.segunda = segunda; 32 | } 33 | 34 | public static Rodada of(char primeira, char segunda){ 35 | return new Rodada(primeira, segunda); 36 | } 37 | 38 | public char getPrimeira() { 39 | return primeira; 40 | } 41 | 42 | public char getSegunda() { 43 | return segunda; 44 | } 45 | 46 | @Override 47 | public String toString() { 48 | return "Rodada{" + 49 | "primeira=" + primeira + 50 | ", segunda=" + segunda + 51 | '}'; 52 | } 53 | 54 | @Override 55 | public boolean equals(Object o) { 56 | if (this == o) return true; 57 | if (o == null || getClass() != o.getClass()) return false; 58 | Rodada rodada = (Rodada) o; 59 | return primeira == rodada.primeira && 60 | segunda == rodada.segunda; 61 | } 62 | 63 | @Override 64 | public int hashCode() { 65 | return Objects.hash(primeira, segunda); 66 | } 67 | } -------------------------------------------------------------------------------- /src/main/java/tdc2020poa/RodadaJava.java: -------------------------------------------------------------------------------- 1 | package tdc2020poa; 2 | 3 | import java.util.List; 4 | import java.util.Objects; 5 | 6 | import static java.util.Arrays.asList; 7 | 8 | /** Versão Java da entidade Rodada */ 9 | public class RodadaJava { 10 | private static final List VALIDAS = asList(PTP.PEDRA, PTP.TESOURA, PTP.PAPEL); 11 | 12 | private final char primeira; 13 | private final char segunda; 14 | 15 | public RodadaJava(char primeira, char segunda) { 16 | if (!VALIDAS.contains(primeira)) { 17 | throw new IllegalArgumentException("Primeira letra inválida:" + primeira + ". Válidas=" + VALIDAS); 18 | } 19 | if (!VALIDAS.contains(segunda)) { 20 | throw new IllegalArgumentException("Segunda letra inválida:" + segunda + ". Válidas=" + VALIDAS); 21 | } 22 | this.primeira = primeira; 23 | this.segunda = segunda; 24 | } 25 | 26 | public static RodadaJava of(char primeira, char segunda){ 27 | return new RodadaJava(primeira, segunda); 28 | } 29 | 30 | public char getPrimeira() { 31 | return primeira; 32 | } 33 | 34 | public char getSegunda() { 35 | return segunda; 36 | } 37 | 38 | @Override 39 | public String toString() { 40 | return "Rodada{" + 41 | "primeira=" + primeira + 42 | ", segunda=" + segunda + 43 | '}'; 44 | } 45 | 46 | @Override 47 | public boolean equals(Object o) { 48 | if (this == o) return true; 49 | if (o == null || getClass() != o.getClass()) return false; 50 | RodadaJava rodada = (RodadaJava) o; 51 | return primeira == rodada.primeira && 52 | segunda == rodada.segunda; 53 | } 54 | 55 | @Override 56 | public int hashCode() { 57 | return Objects.hash(primeira, segunda); 58 | } 59 | } -------------------------------------------------------------------------------- /src/main/java/tdc2020poa/Simulacao.java: -------------------------------------------------------------------------------- 1 | package tdc2020poa; 2 | 3 | public class Simulacao { 4 | public static void main(String[] args) { 5 | Jogador bill = new Jogador("Bill"); 6 | Jogador bob = new Jogador("Bob"); 7 | //Disputa disputa = new DisputaLegada(bill, bob); 8 | Disputa disputa = new DisputaNova(bill, bob); 9 | Jogo jogo = new Jogo(disputa, 7); 10 | jogo.jogar(); 11 | if (jogo.temVencedor()) { 12 | System.out.println("Vencedor: " + jogo.getVencedor().getNome()); 13 | } else { 14 | System.out.println("Empate"); 15 | } 16 | System.out.println("Resultados:" + jogo.getResultados()); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/tdc2020poa/SimulacaoProcedural.java: -------------------------------------------------------------------------------- 1 | package tdc2020poa; 2 | import java.util.ArrayList; 3 | import java.util.List; 4 | 5 | public class SimulacaoProcedural { 6 | 7 | public static void main(String[] args) { 8 | int rodadas = 5; 9 | int scoreBill = 0; 10 | int scoreBob = 0; 11 | List resultados = new ArrayList(); 12 | Resultado resultado ; 13 | char charBill; 14 | char charBob; 15 | PTP ptp = new PTP(); 16 | for (int i=0; i < rodadas; i++) { 17 | charBill = Mao.aleatoria().getId(); 18 | charBob = Mao.aleatoria().getId(); 19 | resultado = Resultado.of(ptp.jogar(charBill, charBob)); 20 | if (Resultado.PRIMEIRO_VENCE.equals(resultado)) { 21 | scoreBill++; 22 | } else if (Resultado.SEGUNDO_VENCE.equals(resultado)) { 23 | scoreBob++; 24 | } // empate não faz nada 25 | resultados.add(resultado); 26 | } 27 | if (scoreBill > scoreBob) { 28 | System.out.println("Vencedor: Bill (Primeiro)"); 29 | } else if (scoreBob > scoreBill) { 30 | System.out.println("Vencedor: Bob (Segundo)"); 31 | } else { 32 | System.out.println("Empate"); 33 | } 34 | System.out.println("Resultados:" + resultados); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/tdc2020poa/codigo-pronto.txt: -------------------------------------------------------------------------------- 1 | // Versão Kotlin da Classe Rodada 2 | data class Rodada(val primeira: Char, val segunda: Char) { 3 | private val validas: List<*> = listOf(PTP.PEDRA, PTP.TESOURA, PTP.PAPEL) 4 | 5 | init { 6 | require(validas.contains(primeira)) { "Primeira letra inválida:$primeira. Válidas=$validas" } 7 | require(validas.contains(segunda)) { "Segunda letra inválida:$segunda. Válidas=$validas" } 8 | } 9 | companion object { 10 | @JvmStatic 11 | fun of(primeira: Char, segunda: Char): Rodada { 12 | return Rodada(primeira, segunda) 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/tdc2020poa/roteiro-palestra.txt: -------------------------------------------------------------------------------- 1 | Roteiro da Palestra 2 | 3 | 1. Apresentar o escopo da palestra e o problema original do jogo "Pedra, Tesoura e Papel" 4 | 1.1. 5 | 1.2. Esquema visual do jogo "Pedra (R) , Tesoura (S) e Papel (P)" 6 | 1.3. Esquema de entrada/saída da lógica central do jogo e seus resultados possíveis 7 | 1.4. Mostrar um código de teste de unidade que descreve os requisitos do jogo 8 | 9 | 2. Apresentar a classe PTP e especialmente o método "jogar()" 10 | 11 | 3. Relacionar o caso com as proposições do capítulo 3 - Funções 12 | 13 | 4. Criar a classe "Rodada" e trocar 2 parâmetros por apenas um em "jogar()" 14 | 15 | 5. [CAPÍTULO 6] Avaliar a questão da classe Rodada 16 | 5.1. Rodada é apenas uma estrutura de dados? 17 | 5.2. Converter Rodada para Kotlin e avaliar o ganho 18 | 5.3. -------------------------------------------------------------------------------- /src/main/kotlin/refactown/cleancode/README.txt: -------------------------------------------------------------------------------- 1 | Clean Code Samples 2 | 3 | This package has kotlin samples -------------------------------------------------------------------------------- /src/main/kotlin/refactown/cleancode/c01cleancode/BadCode.kt: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c01cleancode 2 | 3 | import java.lang.reflect.Field 4 | import java.lang.reflect.Modifier 5 | import java.math.BigInteger 6 | import java.util.* 7 | 8 | fun constants(c: Class<*>?): Int { // count integer constants 9 | if (c != null && !c.isEnum && !Modifier.isAbstract(c.modifiers)) { 10 | val list = ArrayList() // field list 11 | for (field in c.declaredFields) { 12 | list.add(field) 13 | } 14 | var s: Class<*>? = c.superclass 15 | while (s != null && s != Any::class.java) { 16 | for (field in s.declaredFields) { 17 | list.add(field) 18 | } 19 | s = s.superclass // Superclass of c 20 | } 21 | var count = 0 22 | var t: Class<*> 23 | for (f in list) { 24 | t = f.getType() 25 | if (t == Int::class.java || t == Int::class.javaPrimitiveType 26 | || t == Long::class.java || t == Long::class.javaPrimitiveType 27 | || t == Short::class.java || t == Short::class.javaPrimitiveType 28 | || t == Byte::class.java || t == Byte::class.javaPrimitiveType 29 | || t == BigInteger::class.java) { 30 | if (Modifier.isStatic(f.getModifiers()) 31 | && Modifier.isFinal(f.getModifiers())) { 32 | println("Int Constant:$f"); count++ 33 | } 34 | } 35 | } 36 | return count 37 | } else return -1 38 | } 39 | 40 | -------------------------------------------------------------------------------- /src/main/kotlin/refactown/cleancode/c01cleancode/Refactoring1.kt: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c01cleancode 2 | 3 | import java.lang.reflect.Field 4 | import java.lang.reflect.Modifier 5 | import java.math.BigInteger 6 | import java.util.* 7 | 8 | fun countIntConstants(clazz: Class<*>?): Int { 9 | if (clazz != null && !clazz.isEnum && !Modifier.isAbstract(clazz.modifiers)) { 10 | val fields = ArrayList() 11 | for (field in clazz.declaredFields) { 12 | fields.add(field) 13 | } 14 | var superclass: Class<*>? = clazz.superclass 15 | while (superclass != null && superclass != Any::class.java) { 16 | for (field in superclass.declaredFields) { 17 | fields.add(field) 18 | } 19 | superclass = superclass.superclass 20 | } 21 | var count = 0 22 | var type: Class<*> 23 | for (field in fields) { 24 | type = field.getType() 25 | if (type == Int::class.java || type == Int::class.javaPrimitiveType 26 | || type == Long::class.java || type == Long::class.javaPrimitiveType 27 | || type == Short::class.java || type == Short::class.javaPrimitiveType 28 | || type == Byte::class.java || type == Byte::class.javaPrimitiveType 29 | || type == BigInteger::class.java) { 30 | if (Modifier.isStatic(field.getModifiers()) 31 | && Modifier.isFinal(field.getModifiers())) { 32 | println("Int Constant:$field"); count++ 33 | } 34 | } 35 | } 36 | return count 37 | } else return -1 38 | } 39 | -------------------------------------------------------------------------------- /src/main/kotlin/refactown/cleancode/c01cleancode/Refactoring2.kt: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c01cleancode 2 | 3 | import java.lang.reflect.Field 4 | import java.lang.reflect.Modifier 5 | import java.math.BigInteger 6 | 7 | fun countIntegerConstants(clazz: Class<*>): Int { 8 | if (!isConstantClass(clazz)) return -1 9 | val fields = getFieldsFromClass(clazz) 10 | var count = 0 11 | for (field in fields) { 12 | if (isIntegerField(field)) { 13 | println("Int Constant:$field"); count++ 14 | } 15 | } 16 | return count 17 | } 18 | 19 | fun isConstantClass(c: Class<*>?) = c != null && !c.isEnum && !Modifier.isAbstract(c.modifiers) 20 | 21 | fun getFieldsFromClass(clazz: Class<*>): List { 22 | return if (clazz.superclass != null && clazz.superclass != Any::class.java) { 23 | clazz.declaredFields.asList() + getFieldsFromClass(clazz.superclass) 24 | } else clazz.declaredFields.asList() 25 | } 26 | 27 | val integerTypes = listOf(Int::class.java, Int::class.javaPrimitiveType, 28 | Long::class.java, Long::class.javaPrimitiveType, Short::class.java, 29 | Short::class.javaPrimitiveType, Byte::class.java, Byte::class.javaPrimitiveType, 30 | BigInteger::class.java) 31 | 32 | fun isIntegerField(field: Field): Boolean = integerTypes.contains(field.type) 33 | || Modifier.isStatic(field.modifiers) || Modifier.isFinal(field.modifiers) 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /src/main/kotlin/refactown/cleancode/c02names/BadCode.kt: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c02names 2 | 3 | import java.lang.reflect.Field 4 | import java.time.LocalDate 5 | import java.time.Month 6 | import java.util.* 7 | 8 | // Nomes genéricos 9 | val d: Int = 5 // tempo decorrido em dias 10 | val list = ArrayList() // field list 11 | fun func(n: Int){ 12 | for (i in 1..10) 13 | if (n == 3)(println("count:$i = 3")) 14 | } 15 | 16 | // Nomes não pronunciáveis 17 | val genymdhms= LocalDate.now(); 18 | val modymdhms= LocalDate.now(); 19 | val pszqint = 102; 20 | 21 | // Número Mágico - difícil de encontrar depois 22 | fun podeSerEireli(socios: Int) = socios <= 3 23 | 24 | // Notação Húngara 25 | val strNome = "Fulano" 26 | val intIdade = 30 27 | val dtNascimento = LocalDate.of(1990,Month.APRIL, 12) 28 | 29 | // Etc 30 | private val pessoa : IPessoa = Pessoa() 31 | val enderecoDeCobrancaDoCliente= EnderecoDoCliente() 32 | val enderecoDeEntregaDoCliente= EnderecoDoCliente() 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | class EnderecoDoCliente 41 | internal interface IPessoa 42 | open class Pessoa: IPessoa 43 | 44 | 45 | -------------------------------------------------------------------------------- /src/main/kotlin/refactown/cleancode/c02names/Order.kt: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c02names 2 | 3 | import java.time.LocalDate 4 | 5 | // PROBLEM: Order, Item - SOLUTION: Repository, Mapper, Service, DTO 6 | 7 | data class OrderDTO (val number: String, val date: LocalDate, val items: List) 8 | data class ItemDTO (val productId: String, val quantity: Int, val price: Double) 9 | 10 | class Order (val number: String, val date: LocalDate) { 11 | private val items = mutableListOf() 12 | fun addItem(item: Item) = items.add(item) 13 | fun removeItem(item: Item) = items.remove(item) 14 | fun items() = listOf(items) 15 | } 16 | class Item (val productId: String, val quantity: Int, val price: Double) 17 | 18 | interface Repository{ 19 | fun insert(entity: T); fun update (entity: T); fun load(id:ID):T 20 | } 21 | 22 | interface OrderMapper{ 23 | fun dtoToEntity(dto: OrderDTO): Order {TODO()} 24 | fun entityToDTO(entity: Order): OrderDTO {TODO()} 25 | } 26 | 27 | class OrderRepository : Repository{ 28 | override fun insert(entity: Order) { TODO("not implemented") } 29 | override fun update(entity: Order) { TODO("not implemented") } 30 | override fun load(id: String): Order { TODO("not implemented") } 31 | } 32 | 33 | class OrderService(private val mapper: OrderMapper, private val repo: OrderRepository){ 34 | fun place(orderDTO: OrderDTO){TODO()} 35 | } 36 | 37 | 38 | -------------------------------------------------------------------------------- /src/main/kotlin/refactown/cleancode/c02names/Refactoring1.kt: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c02names 2 | 3 | import java.lang.reflect.Field 4 | import java.time.LocalDate 5 | import java.time.Month 6 | import java.util.* 7 | 8 | // Nomes Significativos 9 | val tempoDecorrido: Int = 5 10 | val fields = ArrayList() 11 | fun imprimirSoNoTres(numero: Int){ 12 | for (i in 1..10) 13 | if (numero == PRINT) println("count:$i = $PRINT") 14 | } 15 | 16 | // Nomes pronunciáveis 17 | val generationTimestamp= LocalDate.now() 18 | val modificationTimestamp= LocalDate.now() 19 | val recordId = 102; 20 | 21 | // Constantes para números mágicos e afins 22 | fun isEireli(socios: Int) = socios <= MAX_SOCIOS_EIRELI 23 | 24 | // Sem Notação Húngara 25 | val nome = "Fulano" 26 | val idade = 30 27 | val nascimento = LocalDate.of(1990,Month.APRIL, 12) 28 | 29 | // Etc 30 | val pessoa2 : Pessoa = PessoaImpl() 31 | val enderecoCobranca= Endereco() 32 | val enderecoEntrega= Endereco() 33 | 34 | 35 | 36 | 37 | 38 | 39 | val PRINT = 3 40 | val MAX_SOCIOS_EIRELI = 3 41 | 42 | class Endereco 43 | class PessoaImpl: Pessoa() 44 | 45 | 46 | -------------------------------------------------------------------------------- /src/main/kotlin/refactown/cleancode/c03functions/CommandQuery.kt: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c03functions 2 | 3 | 4 | fun sett(attribute: String, value: String): Boolean = true 5 | 6 | fun attributeExists(attribute: String): Boolean = true 7 | 8 | fun setAttribute(attribute: String, value: String) = print("") 9 | 10 | fun main() { 11 | if (sett("username", "bill")) {} 12 | 13 | if (attributeExists("username")){ 14 | setAttribute("username", "bill") 15 | } 16 | } -------------------------------------------------------------------------------- /src/main/kotlin/refactown/cleancode/c03functions/Employee.kt: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c03functions 2 | 3 | import java.lang.IllegalArgumentException 4 | 5 | open abstract class Employee(val name: String, val type: Type) { 6 | abstract fun calculatePay(): Double 7 | } 8 | 9 | enum class Type { COMMISSIONED, HOURLY, SALARIED; } 10 | 11 | fun calculatePay(employee: Employee): Double { 12 | return when (employee.type) { 13 | Type.COMMISSIONED -> calculateCommissionedPay(employee) 14 | Type.HOURLY -> calculateHourlyPay(employee) 15 | Type.SALARIED -> calculateSalariedPay(employee) 16 | else -> throw IllegalArgumentException("Unknown type!") 17 | } 18 | } 19 | 20 | fun createEmployee(name: String, type: Type): Employee { 21 | return when (type) { 22 | Type.COMMISSIONED -> CommissionedEmployee(name) 23 | Type.HOURLY -> HourlyEmployee(name) 24 | Type.SALARIED -> SalariedEmployee(name) 25 | else -> throw IllegalArgumentException("Unknown type!") 26 | } 27 | } 28 | 29 | class CommissionedEmployee(name: String) : Employee(name, Type.COMMISSIONED) { 30 | override fun calculatePay() = 1.0 31 | } 32 | 33 | class HourlyEmployee(name: String) : Employee(name, Type.HOURLY) { 34 | override fun calculatePay(): Double = 2.0 35 | } 36 | 37 | class SalariedEmployee(name: String) : Employee(name, Type.SALARIED) { 38 | override fun calculatePay(): Double = 3.0 39 | } 40 | 41 | fun calculateSalariedPay(employee: Employee): Double = Double.MIN_VALUE 42 | 43 | fun calculateHourlyPay(employee: Employee): Double = Double.POSITIVE_INFINITY 44 | 45 | fun calculateCommissionedPay(employee: Employee): Double = Double.MAX_VALUE 46 | -------------------------------------------------------------------------------- /src/main/kotlin/refactown/cleancode/c03functions/Fibonacci.kt: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c03functions 2 | 3 | fun fib(x: Int): Int = if (x in 0..1) x else fib(x - 1) + fib(x - 2) 4 | 5 | fun seq(x: Int): String = if (x == 0) "0" else ""+seq(x-1) + "," + fib(x) -------------------------------------------------------------------------------- /src/main/kotlin/refactown/cleancode/c03functions/FileReader.kt: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c03functions 2 | 3 | interface FileReader{ 4 | 5 | // reads file to buffer 6 | fun read(filename: String, buffer: StringBuffer) 7 | 8 | // reads file and returns 9 | fun read(filename: String): StringBuffer 10 | 11 | } 12 | 13 | -------------------------------------------------------------------------------- /src/main/kotlin/refactown/cleancode/c03functions/FileWriter.kt: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c03functions 2 | 3 | interface FileWriter { 4 | 5 | // Flag Argument "append" 6 | fun write(text: String, append: Boolean) 7 | 8 | // write appending 9 | fun writeEof(text: String) 10 | 11 | // overwrite 12 | fun writeBof(text: String) 13 | 14 | } -------------------------------------------------------------------------------- /src/main/kotlin/refactown/cleancode/c03functions/RockPaperScissors.kt: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c03functions 2 | 3 | import java.lang.IllegalArgumentException 4 | 5 | private val VALID_CHOICES = listOf('R', 'S', 'P') // Immutable 6 | 7 | fun rockPaperScissors(first: Char, second: Char): Int { 8 | if (first !in VALID_CHOICES) { 9 | throw IllegalArgumentException("Invalid first choice: $first. Use $VALID_CHOICES") 10 | } 11 | if (second !in VALID_CHOICES) { 12 | throw IllegalArgumentException("Invalid second choice: $second. Use $VALID_CHOICES") 13 | } 14 | return if (first == 'R') { 15 | if (second == 'P') 1 else if (second == 'S') -1 else 0 16 | } else if (first == 'P') { 17 | if (second == 'S') 1 else if (second == 'R') -1 else 0 18 | } else { // S 19 | if (second == 'R') 1 else if (second == 'P') -1 else 0 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/kotlin/refactown/cleancode/c03functions/TryCatch.kt: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c03functions 2 | 3 | 4 | fun delete(page: Page) { 5 | try { 6 | deletePageAndAllReferences(page) 7 | } catch (e: Exception) { 8 | logError(e) 9 | } 10 | } 11 | 12 | private fun deletePageAndAllReferences(page: Page) { 13 | deletePage(page) 14 | deleteReferences(page) 15 | page.configKeys.delete() 16 | } 17 | 18 | private fun deleteReferences(page: Page) {} 19 | 20 | private fun deletePage(page: Page) {} 21 | 22 | fun logError(e: Exception) {} 23 | 24 | class Page(val configKeys: ConfigKeys) { 25 | 26 | } 27 | 28 | class ConfigKeys { 29 | fun delete() { 30 | refactown.cleancode.c03functions.delete(Page(ConfigKeys())) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/kotlin/refactown/cleancode/c04comments/Comments.kt: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c04comments 2 | 3 | import refactown.cleancode.c06objects.Order 4 | import java.io.FileInputStream 5 | import java.lang.Exception 6 | import java.lang.StringBuilder 7 | import java.time.LocalDate 8 | import java.time.Month 9 | 10 | 11 | 12 | fun example(){ 13 | val order = Order(LocalDate.of(2019, Month.APRIL, 4), false) 14 | 15 | // verifica se o pedido não está cancelado nem tem mais de 1 ano 16 | if (!order.cancelled && order.date <= order.date.plusDays(365)) 17 | 18 | if (order.isValid()) println("") 19 | 20 | 21 | } 22 | 23 | fun callLogon(){ 24 | 25 | logon("user", "pass") 26 | } 27 | 28 | fun load(stream: FileInputStream){ 29 | 30 | } 31 | 32 | fun loadProperties(){ 33 | try { 34 | val stream = FileInputStream("file.properties") 35 | load(stream) 36 | } catch (e: Exception){ 37 | // Não havia nenhum arquivo para ser lido 38 | // Todos já foram carregados 39 | } 40 | } 41 | 42 | // Efetua logon passando "usuário" e "senha" e recebe 43 | // o usuário logado 44 | fun logon(username: String, password: String): LoggedUser{ 45 | // TODO ("implementar quando o SSO ficar pronto") 46 | return LoggedUser("Mock", "Mock") 47 | } 48 | 49 | fun append(text: String){ 50 | 51 | //val buffer = StringBuffer() // Precisa ser "Thread Safe" 52 | val buffer = StringBuilder() // Precisa ser rápido 53 | 54 | } 55 | 56 | fun save (cpfCnpj: String){ 57 | 58 | /* 59 | // trim é importante, pois pode vir CPF(11) ou CNPJ(14) 60 | if (cpfCnpj.trim().length==11) { 61 | validarCpf(cpfCnpj) 62 | } else { 63 | validarCnpj(cpfCnpj) 64 | } 65 | */ 66 | // alterado por Fulano em 27/11/1986 67 | validarCnpj(cpfCnpj) // não tem mais CPF 68 | 69 | 70 | } 71 | 72 | fun validarCpf(cpfCnpj: String) { 73 | TODO("not implemented") //To change body of created functions use File | Settings | File Templates. 74 | } 75 | 76 | fun validarCnpj(cpfCnpj: String) { 77 | TODO("not implemented") //To change body of created functions use File | Settings | File Templates. 78 | } 79 | 80 | 81 | data class LoggedUser (val login: String, val role: String) 82 | -------------------------------------------------------------------------------- /src/main/kotlin/refactown/cleancode/c05format/ExampleClass.kt: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c05format 2 | 3 | class ExampleClass { 4 | private var count = 0 5 | private var flag = false 6 | 7 | fun function1() { 8 | val x = 3; 9 | subFunction11(x) 10 | subFunction12() 11 | } 12 | 13 | private fun subFunction11(x: Int) { 14 | // 15 | } 16 | 17 | private fun subFunction12() { 18 | // 19 | } 20 | } -------------------------------------------------------------------------------- /src/main/kotlin/refactown/cleancode/c05format/README.txt: -------------------------------------------------------------------------------- 1 | Clean Code Samples 2 | 3 | This package has kotlin samples -------------------------------------------------------------------------------- /src/main/kotlin/refactown/cleancode/c06objects/BookExample.kt: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c06objects 2 | 3 | import java.lang.IllegalArgumentException 4 | 5 | data class Square(val side: Double) 6 | 7 | data class Rectangle(val height: Double, val width: Double) 8 | 9 | data class Circle(val radius: Double) 10 | 11 | const val PI = 3.1416 12 | 13 | fun calculateArea(shape: Any): Double { 14 | return when (shape) { 15 | is Square -> shape.side * shape.side 16 | is Rectangle -> shape.height * shape.width 17 | is Circle -> PI * shape.radius * shape.radius 18 | else -> throw IllegalArgumentException() 19 | } 20 | } 21 | 22 | interface Shape { fun area(): Double } 23 | 24 | class SquareOO(private val side: Double) : Shape { 25 | override fun area() = side * side 26 | } 27 | 28 | class RectangleOO(private val height: Double, 29 | private val width: Double) : Shape { 30 | override fun area() = height * width 31 | } 32 | 33 | class CircleOO(private val radius: Double) : Shape { 34 | override fun area() = PI * radius * radius 35 | } 36 | 37 | -------------------------------------------------------------------------------- /src/main/kotlin/refactown/cleancode/c06objects/DemeterLaw.kt: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c06objects 2 | 3 | -------------------------------------------------------------------------------- /src/main/kotlin/refactown/cleancode/c06objects/FeatureEnvy.kt: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c06objects 2 | 3 | import java.lang.IllegalArgumentException 4 | import java.time.LocalDate 5 | 6 | class HybridSquare(val side: Double) : Shape { 7 | override fun area() = side * side 8 | } 9 | 10 | class HybridRectangle(val height: Double, val width: Double) : Shape { 11 | override fun area() = height * width 12 | } 13 | 14 | class HybridCircle( val radius: Double) : Shape { 15 | override fun area() = PI * radius * radius 16 | } 17 | 18 | fun calculateAreaFeatureEnvy(shape: Any): Double { 19 | return when (shape) { 20 | is HybridSquare -> shape.side * shape.side 21 | is HybridRectangle -> shape.height * shape.width 22 | is HybridCircle -> PI * shape.radius * shape.radius 23 | else -> throw IllegalArgumentException() 24 | } 25 | } 26 | 27 | class AnemicOrder(val date: LocalDate, var cancelled: Boolean) 28 | 29 | fun isValidOrder(order:AnemicOrder): Boolean{ 30 | return !order.cancelled && order.date <= order.date.plusDays(365) 31 | } 32 | 33 | class Order(val date: LocalDate, var cancelled: Boolean){ 34 | fun isValid()= !cancelled && date <= date.plusDays(365) 35 | } -------------------------------------------------------------------------------- /src/main/kotlin/refactown/cleancode/c06objects/FeatureEnvySideEfects.kt: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c06objects 2 | 3 | import java.lang.IllegalArgumentException 4 | 5 | class MutableSquare(var side: Double) : Shape { 6 | override fun area() = side * side 7 | } 8 | 9 | class MutableRectangle(var height: Double, var width: Double) : Shape { 10 | override fun area() = height * width 11 | } 12 | 13 | class MutableCircle(var radius: Double) : Shape { 14 | override fun area() = PI * radius * radius 15 | } 16 | 17 | fun calculateAreaSideEffects(shape: Any): Double { 18 | return when (shape) { 19 | is MutableSquare -> ++shape.side * shape.side++ 20 | is MutableRectangle -> ++shape.height * shape.width++ 21 | is MutableCircle -> PI * ++shape.radius * shape.radius++ 22 | else -> throw IllegalArgumentException() 23 | } 24 | } -------------------------------------------------------------------------------- /src/main/kotlin/refactown/cleancode/c06objects/Person.kt: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c06objects 2 | 3 | data class Person (val name: String, val age: Int, val city: String) -------------------------------------------------------------------------------- /src/main/kotlin/refactown/cleancode/c07exceptions/JsonException.kt: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c07exceptions 2 | 3 | import java.io.IOException 4 | 5 | class JsonException : IOException{ 6 | 7 | constructor(message: String, cause: Throwable) : super(message, cause) 8 | 9 | constructor(message: String) : super(message) 10 | 11 | constructor(cause: Throwable) : super(cause) 12 | 13 | companion object { 14 | 15 | private val serialVersionUID = 1L 16 | } 17 | } -------------------------------------------------------------------------------- /src/main/kotlin/refactown/cleancode/c07exceptions/JsonParsing.kt: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c07exceptions 2 | 3 | import com.google.gson.Gson 4 | 5 | typealias JsonParserFunction = (String, Class<*>) -> Any 6 | 7 | fun fromJsonV0(json: String, clazz: Class<*>): Any?{ 8 | val gson = Gson() 9 | try { 10 | return gson.fromJson(json, clazz) 11 | } catch (e: Exception){ 12 | println("Parsing error. Json text:$json") 13 | return null 14 | } 15 | } 16 | 17 | fun fromJsonV1(json: String, clazz: Class<*>): Any{ 18 | val gson = Gson() 19 | try { 20 | return gson.fromJson(json, clazz) 21 | } catch (e: Exception){ 22 | throw JsonException("Parsing error. Json text:$json") 23 | } 24 | } 25 | 26 | fun fromJsonV2(json: String, clazz: Class<*>): Any{ 27 | val gson = Gson() 28 | try { 29 | return gson.fromJson(json, clazz) 30 | } catch (e: Exception){ 31 | throw JsonException("Parsing error. Json text:$json", e) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/kotlin/refactown/cleancode/c08boundary/GsonJsonParser.kt: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c08boundary 2 | 3 | import com.google.gson.Gson 4 | import refactown.cleancode.c07exceptions.JsonException 5 | 6 | class GsonJsonParser: JsonParser{ 7 | 8 | private val gson = Gson() 9 | 10 | override fun toJson(obj: Any): String { 11 | try { 12 | return gson.toJson(obj) 13 | } catch (e: Exception){ 14 | throw JsonException("Serialize error. Object:$obj", e) 15 | } 16 | } 17 | 18 | override fun fromJson(json: String, clazz: Class<*>): Any { 19 | try { 20 | return gson.fromJson(json, clazz) 21 | } catch (e: Exception){ 22 | throw JsonException("Parsing error. Json text:$json", e) 23 | } 24 | } 25 | 26 | } -------------------------------------------------------------------------------- /src/main/kotlin/refactown/cleancode/c08boundary/JsonParser.kt: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c08boundary 2 | 3 | interface JsonParser{ 4 | 5 | fun fromJson(json: String, clazz: Class<*>): Any 6 | 7 | fun toJson(obj: Any): String 8 | } -------------------------------------------------------------------------------- /src/main/kotlin/refactown/cleancode/c08boundary/LogonController.kt: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c08boundary 2 | 3 | class LogonController(private val jsonParser: JsonParser){ 4 | 5 | fun logon(login: String, password: String): User{ 6 | val userJson = callHttp(login, password) 7 | return jsonParser.fromJson(userJson, User::class.java) as User 8 | } 9 | 10 | private fun callHttp(login: String, password: String): String { 11 | return "{\"login\":\"admin\", \"role\":\"admin\"}" //MOCK 12 | } 13 | } 14 | 15 | data class User (val login: String, val role: String) 16 | -------------------------------------------------------------------------------- /src/main/kotlin/refactown/cleancode/c09tests/IntConstCounterV1.kt: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c09tests 2 | 3 | import java.lang.reflect.Modifier 4 | import java.math.BigInteger 5 | 6 | fun countIntConstV1(clazz: Class<*>): Int{ 7 | val fields = clazz.declaredFields.asList() 8 | var count = 0 9 | val integerTypes = listOf(Int::class.java, Int::class.javaPrimitiveType, 10 | Long::class.java, Long::class.javaPrimitiveType, Short::class.java, 11 | Short::class.javaPrimitiveType, Byte::class.java, Byte::class.javaPrimitiveType, 12 | BigInteger::class.java) 13 | 14 | for (field in fields) { 15 | if (integerTypes.contains(field.type) 16 | || Modifier.isStatic(field.modifiers) || Modifier.isFinal(field.modifiers)) { 17 | println("Int Constant:$field"); count++ 18 | } 19 | } 20 | return count 21 | } 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /src/main/kotlin/refactown/cleancode/c09tests/IntConstCounterV2.kt: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c09tests 2 | 3 | import java.lang.reflect.Field 4 | import java.lang.reflect.Modifier 5 | import java.math.BigInteger 6 | 7 | 8 | fun countIntConstV2(clazz: Class<*>): Int{ 9 | if (!isConstantClass(clazz)) return -1 10 | val fields = clazz.declaredFields.asList() 11 | var count = 0 12 | for (field in fields) { 13 | if (isIntegerField(field)) { 14 | println("Int Constant:$field"); count++ 15 | } 16 | } 17 | return count 18 | } 19 | 20 | private fun isConstantClass(c: Class<*>?) = c != null && !c.isEnum && !Modifier.isAbstract(c.modifiers) 21 | 22 | private val integerTypes = listOf(Int::class.java, Int::class.javaPrimitiveType, 23 | Long::class.java, Long::class.javaPrimitiveType, Short::class.java, 24 | Short::class.javaPrimitiveType, Byte::class.java, Byte::class.javaPrimitiveType, 25 | BigInteger::class.java) 26 | 27 | private fun isIntegerField(field: Field): Boolean = integerTypes.contains(field.type) 28 | || Modifier.isStatic(field.modifiers) || Modifier.isFinal(field.modifiers) 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /src/main/kotlin/refactown/cleancode/c09tests/IntConstCounterV3.kt: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c09tests 2 | 3 | import java.lang.reflect.Field 4 | import java.lang.reflect.Modifier 5 | import java.math.BigInteger 6 | 7 | 8 | fun countIntConstV3(clazz: Class<*>): Int{ 9 | if (!isConstantClass(clazz)) return -1 10 | val fields = getFieldsFromClass(clazz) 11 | var count = 0 12 | for (field in fields) { 13 | if (isIntegerField(field)) { 14 | println("Int Constant:$field"); count++ 15 | } 16 | } 17 | return count 18 | } 19 | 20 | fun getFieldsFromClass(clazz: Class<*>): List { 21 | return if (clazz.superclass != null && clazz.superclass != Any::class.java) { 22 | clazz.declaredFields.asList() + getFieldsFromClass(clazz.superclass) 23 | } else clazz.declaredFields.asList() 24 | } 25 | 26 | private fun isConstantClass(c: Class<*>?) = c != null && !c.isEnum && !Modifier.isAbstract(c.modifiers) 27 | 28 | private val integerTypes = listOf(Int::class.java, Int::class.javaPrimitiveType, 29 | Long::class.java, Long::class.javaPrimitiveType, Short::class.java, 30 | Short::class.javaPrimitiveType, Byte::class.java, Byte::class.javaPrimitiveType, 31 | BigInteger::class.java) 32 | 33 | private fun isIntegerField(field: Field): Boolean = integerTypes.contains(field.type) 34 | || Modifier.isStatic(field.modifiers) || Modifier.isFinal(field.modifiers) 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /src/main/kotlin/refactown/cleancode/c09tests/RefactoringV1.kt: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c09tests 2 | 3 | import java.lang.reflect.Field 4 | import java.lang.reflect.Modifier 5 | import java.math.BigInteger 6 | 7 | fun countIntConstV1Refac(clazz: Class<*>): Int{ 8 | val fields = clazz.declaredFields.asList() 9 | var count = 0 10 | for (field in fields) { 11 | if (isIntegerField(field)) { 12 | println("Int Constant:$field"); count++ 13 | } 14 | } 15 | return count 16 | } 17 | 18 | private val integerTypes = listOf(Int::class.java, Int::class.javaPrimitiveType, 19 | Long::class.java, Long::class.javaPrimitiveType, Short::class.java, 20 | Short::class.javaPrimitiveType, Byte::class.java, Byte::class.javaPrimitiveType, 21 | BigInteger::class.java) 22 | 23 | private fun isIntegerField(field: Field): Boolean = integerTypes.contains(field.type) 24 | || Modifier.isStatic(field.modifiers) || Modifier.isFinal(field.modifiers) 25 | 26 | 27 | -------------------------------------------------------------------------------- /src/main/kotlin/refactown/cleancode/c10classes/BestOfThree.kt: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c10classes 2 | 3 | import java.lang.IllegalStateException 4 | 5 | class BestOfThree(val match: Match, val rounds: Int = 3) { 6 | 7 | private var scoreFirstPlayer = 0 8 | private var scoreSecondPlayer = 0 9 | private val winnerScore = rounds / 2 + 1 10 | private val results = mutableListOf() 11 | 12 | fun play() { 13 | for (i in 0 until rounds) { 14 | val matchResult = match.play() 15 | results.add(matchResult) 16 | when (matchResult) { 17 | MatchResult.FIRST_WINS -> scoreFirstPlayer++ 18 | MatchResult.SECOND_WINS -> scoreSecondPlayer++ 19 | } 20 | if (alreadyHasWinner()) break 21 | } 22 | } 23 | 24 | private fun alreadyHasWinner(): Boolean = scoreFirstPlayer >= winnerScore 25 | || scoreSecondPlayer >= winnerScore 26 | 27 | fun hasWinner() = scoreFirstPlayer != scoreSecondPlayer 28 | 29 | fun results() = results.toList() 30 | 31 | fun winner(): Player { 32 | return when { 33 | scoreFirstPlayer > scoreSecondPlayer -> match.firstPlayer 34 | scoreSecondPlayer > scoreFirstPlayer -> match.secondPlayer 35 | else -> throw IllegalStateException("There is no winner!") 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /src/main/kotlin/refactown/cleancode/c10classes/ClassesMain.kt: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c10classes 2 | 3 | fun main() { 4 | val bill = Player("Bill (First)") 5 | val bob = Player("Bob (Second)") 6 | val match = Match(bill, bob) 7 | val bestOf = BestOfThree(match, 5) 8 | bestOf.play() 9 | // Print Results 10 | if (bestOf.hasWinner()){ 11 | println("Winner: ${bestOf.winner()}") 12 | } else { 13 | println ("Draw") 14 | } 15 | println("Results: ${bestOf.results()}") 16 | } 17 | 18 | -------------------------------------------------------------------------------- /src/main/kotlin/refactown/cleancode/c10classes/Match.kt: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c10classes 2 | 3 | import refactown.cleancode.c03functions.rockPaperScissors 4 | 5 | open class Match(val firstPlayer: Player, 6 | val secondPlayer: Player) { 7 | 8 | open fun play(): MatchResult { 9 | val first: Char = firstPlayer.play().id 10 | val second: Char = secondPlayer.play().id 11 | val result = rockPaperScissors(first, second) 12 | val firstResult = Result.of(result) 13 | return MatchResult.of(firstResult) 14 | } 15 | } 16 | 17 | class SmartMatch(firstPlayer: Player, secondPlayer: Player) 18 | : Match(firstPlayer, secondPlayer) { 19 | 20 | override fun play(): MatchResult { 21 | val firstHand = firstPlayer.play() 22 | val secondHand = secondPlayer.play() 23 | return when { 24 | firstHand.beats(secondHand) -> MatchResult.FIRST_WINS 25 | secondHand.beats(firstHand) -> MatchResult.SECOND_WINS 26 | else -> MatchResult.DRAW 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/kotlin/refactown/cleancode/c10classes/Player.kt: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c10classes 2 | 3 | open class Player(val name: String) { 4 | 5 | open fun play(): Hand = Hand.randomHand() 6 | 7 | override fun toString(): String = name 8 | } -------------------------------------------------------------------------------- /src/main/kotlin/refactown/cleancode/c10classes/ProceduralMain.kt: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c10classes 2 | 3 | import refactown.cleancode.c03functions.rockPaperScissors 4 | 5 | fun main() { 6 | val rounds = 5 7 | var scoreBill = 0 8 | var scoreBob = 0 9 | val results = mutableListOf() 10 | var firstResult: Result? 11 | var matchResult: MatchResult? 12 | for (i in 0 until rounds) { 13 | var billHand = Hand.randomHand() 14 | var bobHand = Hand.randomHand() 15 | firstResult = Result.of(rockPaperScissors(billHand.id, bobHand.id)) 16 | matchResult = MatchResult.of(firstResult) 17 | when (matchResult) { 18 | MatchResult.FIRST_WINS -> scoreBill++ 19 | MatchResult.SECOND_WINS -> scoreBob++ 20 | } 21 | results.add(matchResult) 22 | } 23 | // Print Results 24 | if (scoreBill > scoreBob) { 25 | println("Winner: Bill") 26 | } else if (scoreBob > scoreBill) { 27 | println("Winner: Bob") 28 | } else { 29 | println("Draw") 30 | } 31 | println("Results: ${results}") 32 | } -------------------------------------------------------------------------------- /src/main/kotlin/refactown/cleancode/c10classes/RockPaperScissors.kt: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c10classes 2 | 3 | import java.lang.Math.abs 4 | import java.util.* 5 | 6 | private val beatsMap = mapOf(Hand.PAPER to Hand.ROCK, 7 | Hand.SCISSORS to Hand.PAPER, Hand.ROCK to Hand.SCISSORS) 8 | 9 | enum class Hand(val id: Char) { 10 | ROCK('R'), PAPER('P'), SCISSORS('S'); 11 | 12 | infix fun beats(hand: Hand) = beatsMap[this] == hand 13 | 14 | companion object { 15 | fun randomHand(): Hand { 16 | return values()[abs(Random().ints().findFirst().asInt % 3)] 17 | } 18 | } 19 | } 20 | 21 | private val matchMap = mapOf(Result.WIN to MatchResult.FIRST_WINS, 22 | Result.DRAW to MatchResult.DRAW, Result.LOSE to MatchResult.SECOND_WINS) 23 | 24 | enum class MatchResult(val firstResult: Result, val secondResult: Result) { 25 | FIRST_WINS(Result.WIN, Result.LOSE), 26 | DRAW(Result.DRAW, Result.DRAW), 27 | SECOND_WINS(Result.LOSE, Result.WIN); 28 | 29 | companion object { 30 | fun of(firstResult: Result) = matchMap[firstResult]!! 31 | } 32 | } 33 | 34 | private val resultMap = mapOf(-1 to Result.LOSE, 0 to Result.DRAW, 1 to Result.WIN) 35 | 36 | enum class Result(val value: Int) { 37 | LOSE(-1), DRAW(0), WIN(1); 38 | 39 | companion object { 40 | fun of(value: Int): Result = resultMap[value]!! 41 | } 42 | } 43 | 44 | -------------------------------------------------------------------------------- /src/main/kotlin/refactown/cleancode/math/Math.kt: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.math 2 | 3 | fun add(a: Int, b:Int): Int = a + b 4 | 5 | -------------------------------------------------------------------------------- /src/main/kotlin/refactown/cleancode/quiz/domain/Answer.kt: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.quiz.domain 2 | 3 | class Answer (val index: Int, val text: String, val correct: Boolean){ 4 | 5 | } 6 | -------------------------------------------------------------------------------- /src/main/kotlin/refactown/cleancode/quiz/domain/Game.kt: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.quiz.domain 2 | 3 | import java.time.LocalDateTime 4 | import java.util.* 5 | 6 | fun startGame(pin: String, quiz: Quiz, startTime: LocalDateTime, owner: User, players: SortedSet): Game = 7 | Game(pin, quiz, startTime, owner, players) 8 | 9 | class Game(val pin: String, val quiz: Quiz, val startTime: LocalDateTime, val owner: User, val players: SortedSet) { 10 | var finishTime: LocalDateTime = LocalDateTime.MAX 11 | val isFinished: Boolean get() = finishTime != LocalDateTime.MAX 12 | val rounds = mutableListOf() 13 | var roundIndex = -1 14 | 15 | fun startNextRound(): Round { 16 | roundIndex++ 17 | val newRound = Round(LocalDateTime.now()) 18 | rounds[roundIndex] = newRound 19 | return newRound 20 | } 21 | 22 | fun finish(finishTime: LocalDateTime) { 23 | validateBeforeFinish(finishTime) 24 | this.finishTime = finishTime 25 | } 26 | 27 | private fun validateBeforeFinish(finishTime: LocalDateTime) { 28 | if (isFinished) throw IllegalStateException("Match already finished!") 29 | } 30 | 31 | fun currentRound(): Round = rounds[roundIndex] 32 | 33 | } -------------------------------------------------------------------------------- /src/main/kotlin/refactown/cleancode/quiz/domain/Guess.kt: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.quiz.domain 2 | 3 | data class Guess (val player: String, val question: Question, val choose: Answer, val timeInMillis: Long) 4 | -------------------------------------------------------------------------------- /src/main/kotlin/refactown/cleancode/quiz/domain/Question.kt: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.quiz.domain 2 | 3 | class Question (val index: Int, val text: String, val timeLimit: Int, val answers: List){ 4 | 5 | } 6 | -------------------------------------------------------------------------------- /src/main/kotlin/refactown/cleancode/quiz/domain/Quiz.kt: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.quiz.domain 2 | 3 | class Quiz (val id: String, val title: String, val description: String, val questions: List){ 4 | 5 | } -------------------------------------------------------------------------------- /src/main/kotlin/refactown/cleancode/quiz/domain/Round.kt: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.quiz.domain 2 | 3 | import java.time.LocalDateTime 4 | 5 | class Round (val begin: LocalDateTime, val end: LocalDateTime= LocalDateTime.MAX, 6 | val skipped: Boolean=false){ 7 | 8 | } 9 | -------------------------------------------------------------------------------- /src/main/kotlin/refactown/cleancode/quiz/domain/User.kt: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.quiz.domain 2 | 3 | data class User(val login: String, val role: String) -------------------------------------------------------------------------------- /src/main/kotlin/refactown/cleancode/quiz/service/GameService.kt: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.quiz.service 2 | 3 | class GameService{ 4 | 5 | fun playerGuess(guessEvent: GuessEvent){ 6 | 7 | } 8 | } -------------------------------------------------------------------------------- /src/main/kotlin/refactown/cleancode/quiz/service/GuessEvent.kt: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.quiz.service 2 | 3 | import java.time.LocalDateTime 4 | 5 | data class GuessEvent(val gamePin: String, val roundNumber: Int, val nickname: String, val choose: Int , 6 | val moment: LocalDateTime) -------------------------------------------------------------------------------- /src/main/resources/README.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/refactown/cleancode/921639d08022db03410b87990e97e2ce219680bb/src/main/resources/README.txt -------------------------------------------------------------------------------- /src/main/resources/cpbsb6/pratica-funcoes.txt: -------------------------------------------------------------------------------- 1 | Atividade prática com Gemini 2 | 3 | [PROMPT 1] 4 | 5 | Considere a seguinte lista de regras para funções baseadas em clean code: 6 | 7 | 1. Funções devem ser pequenas (<= 20 linhas) 8 | 2. Funções devem fazer apenas uma coisa 9 | 3. Devem ter nomes descritivos do que fazem 10 | 4. Somente um nível de abstração por função 11 | 5. Funções devem ter poucos parâmetros 12 | 13 | Para cada regra mostre um exemplo de código que descumpre esta regra. 14 | 15 | [PROMPT 2] 16 | 17 | Considere o código a seguir: 18 | 19 | import java.util.ArrayList; 20 | import java.util.List; 21 | import java.util.Random; 22 | 23 | /** 24 | * Versão com nomes, formatação e comentários melhorados. 25 | * O método ainda é monolítico e muito grande (34 linhas). 26 | */ 27 | public class MegaSenaV1 { 28 | 29 | /** 30 | * Método que calcula o valor que uma certa aposta deve receber em função do número de acertos. 31 | * 32 | * @param numerosApostados Os números jogados em uma aposta. 33 | * @param premioTotal O valor to prêmio em relação ao número de acertos. 34 | * @return O valor do prêmio a ser recebido por esta aposta. 35 | */ 36 | public double calculaPremio(List numerosApostados, double premioTotal) { 37 | List numerosValidos = new ArrayList<>(); 38 | for (Integer apostado : numerosApostados) { 39 | if (apostado < 1 || apostado > 60) { 40 | return 0.0; // inválido 41 | } 42 | if (numerosValidos.contains(apostado)) { 43 | return 0.0; // repetido 44 | } 45 | numerosValidos.add(apostado); 46 | } 47 | 48 | if (numerosValidos.size() >= 6 && numerosValidos.size() <= 15) { 49 | List numerosSorteados = new ArrayList<>(); 50 | int numeroSorteado; 51 | while (numerosSorteados.size() < 6) { 52 | numeroSorteado = new Random().nextInt(59) + 1; 53 | if (!numerosSorteados.contains(numeroSorteado)) { 54 | numerosSorteados.add(numeroSorteado); 55 | } 56 | } 57 | 58 | int acertos = 0; 59 | for (Integer apostado : numerosApostados) { 60 | if (numerosSorteados.contains(apostado)) { 61 | acertos++; 62 | } 63 | } 64 | 65 | if (acertos == 6) { 66 | return premioTotal; // Sena = 100% 67 | } else if (acertos == 5) { 68 | return premioTotal * 0.2; // Quina = 20% 69 | } else if (acertos == 4) { 70 | return premioTotal * 0.05; // Quadra = 5% 71 | } 72 | } 73 | return 0.0; 74 | } 75 | } 76 | 77 | Avalie este código com base nas cinco regras apresentadas anteriormente e diga qual delas está sendo cumprida e qual não está. 78 | -------------------------------------------------------------------------------- /src/test/java/refactown/cleancode/c01cleancode/CountIntConstTest.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c01cleancode; 2 | 3 | import org.junit.jupiter.api.Test; 4 | 5 | import java.time.Month; 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | import static org.junit.jupiter.api.Assertions.assertEquals; 10 | 11 | class CountIntConstTest { 12 | 13 | @Test 14 | void testBadCode() { 15 | assertEquals(-1, BadCode.constants(null)); 16 | assertEquals(-1, BadCode.constants(List.class)); 17 | assertEquals(-1, BadCode.constants(Month.class)); 18 | assertEquals(0, BadCode.constants(Object.class)); 19 | assertEquals(4, BadCode.constants(ArrayList.class)); 20 | } 21 | 22 | @Test 23 | void testrefactoring1() { 24 | assertEquals(-1, Refactoring1.countIntConstants(null)); 25 | assertEquals(-1, Refactoring1.countIntConstants(List.class)); 26 | assertEquals(-1, Refactoring1.countIntConstants(Month.class)); 27 | assertEquals(0, Refactoring1.countIntConstants(Object.class)); 28 | assertEquals(4, Refactoring1.countIntConstants(ArrayList.class)); 29 | } 30 | 31 | @Test 32 | void testrefactoring2() { 33 | assertEquals(-1, Refactoring2.countIntegerConstants(null)); 34 | assertEquals(-1, Refactoring2.countIntegerConstants(List.class)); 35 | assertEquals(-1, Refactoring2.countIntegerConstants(Month.class)); 36 | assertEquals(0, Refactoring2.countIntegerConstants(Object.class)); 37 | assertEquals(4, Refactoring2.countIntegerConstants(ArrayList.class)); // java = 4 38 | } 39 | 40 | } -------------------------------------------------------------------------------- /src/test/java/refactown/cleancode/c03functions/FibonacciTest.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c03functions; 2 | 3 | import static org.junit.jupiter.api.Assertions.*; 4 | import static refactown.cleancode.c03functions.Fibonacci.fib; 5 | import static refactown.cleancode.c03functions.Fibonacci.seq; 6 | 7 | import org.junit.jupiter.api.Test; 8 | 9 | class FibonacciTest { 10 | 11 | @Test 12 | void testFib() { 13 | assertEquals(0, fib(0)); 14 | assertEquals(1, fib(1)); 15 | assertEquals(1, fib(2)); 16 | assertEquals(2, fib(3)); 17 | assertEquals(3, fib(4)); 18 | assertEquals(5, fib(5)); 19 | assertEquals(8, fib(6)); 20 | assertEquals(13, fib(7)); 21 | assertEquals(21, fib(8)); 22 | assertEquals(34, fib(9)); 23 | assertEquals(55, fib(10)); 24 | } 25 | 26 | @Test 27 | void testSeq() { 28 | assertEquals("0,1,1,2,3,5", seq(5)); 29 | assertEquals("0,1,1,2,3,5,8,13,21,34,55", seq(10)); 30 | assertEquals("0,1,1,2,3,5,8,13,21,34,55,89,144,233,377,610," 31 | + "987,1597,2584,4181,6765,10946,17711,28657,46368,75025," 32 | + "121393,196418,317811,514229,832040,1346269,2178309,3524578," 33 | + "5702887,9227465,14930352,24157817,39088169,63245986,102334155", seq(40)); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/test/java/refactown/cleancode/c03functions/PedraPapelTesouraTest.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c03functions; 2 | 3 | import static org.junit.jupiter.api.Assertions.*; 4 | import static refactown.cleancode.c03functions.PedraPapelTesoura.pedraPapelTesoura; 5 | 6 | import org.junit.jupiter.api.Test; 7 | 8 | class PedraPapelTesouraTest { 9 | 10 | @Test 11 | void testPedraPapelTesoura() { 12 | // Empate = 0 13 | assertEquals(0, pedraPapelTesoura('R', 'R')); 14 | assertEquals(0, pedraPapelTesoura('P', 'P')); 15 | assertEquals(0, pedraPapelTesoura('S', 'S')); 16 | // Primeiro vence = -1 17 | assertEquals(-1, pedraPapelTesoura('R', 'S')); 18 | assertEquals(-1, pedraPapelTesoura('S', 'P')); 19 | assertEquals(-1, pedraPapelTesoura('P', 'R')); 20 | // Segundo vence = 1 21 | assertEquals(1, pedraPapelTesoura('S', 'R')); 22 | assertEquals(1, pedraPapelTesoura('P', 'S')); 23 | assertEquals(1, pedraPapelTesoura('R', 'P')); 24 | // Illegal Argument 25 | try { 26 | pedraPapelTesoura('A', 'R'); 27 | } catch (IllegalArgumentException e) { 28 | } 29 | try { 30 | pedraPapelTesoura('S', '*'); 31 | } catch (IllegalArgumentException e) { 32 | } 33 | try { 34 | pedraPapelTesoura(' ', '%'); 35 | } catch (IllegalArgumentException e) { 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/test/java/refactown/cleancode/c03functions/RockPaperScissorsTest.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c03functions; 2 | 3 | import static org.junit.jupiter.api.Assertions.*; 4 | import static refactown.cleancode.c03functions.RockPaperScissors.rockPaperScissors; 5 | 6 | import org.junit.jupiter.api.Test; 7 | 8 | class RockPaperScissorsTest { 9 | 10 | @Test 11 | void testRockPaperScissors() { 12 | // DRAW = 0 13 | assertEquals(0, rockPaperScissors('R', 'R')); 14 | assertEquals(0, rockPaperScissors('P', 'P')); 15 | assertEquals(0, rockPaperScissors('S', 'S')); 16 | // Fisrt Wins = -1 17 | assertEquals(-1, rockPaperScissors('R', 'S')); 18 | assertEquals(-1, rockPaperScissors('S', 'P')); 19 | assertEquals(-1, rockPaperScissors('P', 'R')); 20 | // Second Wins = 1 21 | assertEquals(1, rockPaperScissors('S', 'R')); 22 | assertEquals(1, rockPaperScissors('P', 'S')); 23 | assertEquals(1, rockPaperScissors('R', 'P')); 24 | // Illegal Argument 25 | try { 26 | rockPaperScissors('A', 'R'); 27 | } catch (IllegalArgumentException e) { 28 | } 29 | try { 30 | rockPaperScissors('S', '*'); 31 | } catch (IllegalArgumentException e) { 32 | } 33 | try { 34 | rockPaperScissors(' ', '%'); 35 | } catch (IllegalArgumentException e) { 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/test/java/refactown/cleancode/c06objects/book/GeometryTest.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c06objects.book; 2 | 3 | import static org.junit.jupiter.api.Assertions.*; 4 | import static refactown.cleancode.c06objects.book.Geometry.calculateArea; 5 | 6 | import org.junit.jupiter.api.Test; 7 | 8 | class GeometryTest { 9 | 10 | @Test 11 | void proceduralExample() { 12 | Square square = new Square(3.0); 13 | Rectangle rectangle = new Rectangle(2.0, 4.5); 14 | Circle circle = new Circle(2.0); 15 | 16 | assertEquals(calculateArea(square), 9.0); 17 | assertEquals(calculateArea(rectangle), 9.0); 18 | assertEquals(calculateArea(circle), 12.5664); 19 | } 20 | 21 | @Test 22 | void ooExample() { 23 | SquareOO square = new SquareOO(3.0); 24 | RectangleOO rectangle = new RectangleOO(2.0, 4.5); 25 | CircleOO circle = new CircleOO(2.0); 26 | 27 | assertEquals(square.area(), 9.0); 28 | assertEquals(rectangle.area(), 9.0); 29 | assertEquals(circle.area(), 12.5664); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/test/java/refactown/cleancode/c06objects/envy/FeatureEnvyTest.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c06objects.envy; 2 | 3 | import static org.junit.jupiter.api.Assertions.*; 4 | 5 | import java.time.LocalDate; 6 | 7 | import org.junit.jupiter.api.Test; 8 | 9 | class FeatureEnvyTest { 10 | 11 | @Test 12 | void test() { 13 | // Feature Envy 14 | AnemicOrder anemicOrder = new AnemicOrder(LocalDate.now(), false); 15 | FeatureEnvy featureEnvy = new FeatureEnvy(); 16 | assertTrue(featureEnvy.isValidOrder(anemicOrder)); // is Valid? 17 | 18 | // Order Feature 19 | Order order = new Order(LocalDate.now(), false); 20 | assertTrue(order.isValid()); // is Valid? 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/test/java/refactown/cleancode/c07exceptions/JsonParsingTest.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c07exceptions; 2 | 3 | import static org.junit.jupiter.api.Assertions.*; 4 | import static refactown.cleancode.c07exceptions.java.JsonParsing.fromJsonV0; 5 | import static refactown.cleancode.c07exceptions.java.JsonParsing.fromJsonV1; 6 | import static refactown.cleancode.c07exceptions.java.JsonParsing.fromJsonV2; 7 | 8 | import org.junit.jupiter.api.Test; 9 | 10 | import com.google.gson.JsonSyntaxException; 11 | 12 | import refactown.cleancode.c06objects.Person; 13 | import refactown.cleancode.c07exceptions.java.JsonException; 14 | 15 | class JsonParsingTest { 16 | 17 | @Test 18 | void testV0NullVersion() { 19 | // Parsing ok 20 | String billJson = "{name:\"Bill\", age:25, city:\"Rio de Janeiro\"}"; 21 | Person billPerson = (Person) fromJsonV0(billJson, Person.class); 22 | assertEquals(billPerson.getName(), "Bill"); 23 | assertEquals(billPerson.getAge(), 25); 24 | assertEquals(billPerson.getCity(), "Rio de Janeiro"); 25 | // Error Parsing 26 | String joeJson = "{ age:25, city:\"Rio de Janeiro\""; // invalid 27 | Person joePerson = (Person) fromJsonV0(joeJson, Person.class); 28 | if (joePerson != null) { // forced by "return null" 29 | assertEquals(joePerson.getName(), null); 30 | assertEquals(joePerson.getAge(), 0); 31 | assertEquals(joePerson.getCity(), null); 32 | } 33 | } 34 | 35 | @Test 36 | void testV1() { 37 | // Parsing ok 38 | String billJson = "{name:\"Bill\", age:25, city:\"Rio de Janeiro\"}"; 39 | Person billPerson = (Person) fromJsonV1(billJson, Person.class); 40 | assertEquals(billPerson.getName(), "Bill"); 41 | assertEquals(billPerson.getAge(), 25); 42 | assertEquals(billPerson.getCity(), "Rio de Janeiro"); 43 | // Error Parsing 44 | String joeJson = "{ age:25, city:\"Rio de Janeiro\""; // invalid 45 | try { 46 | Person joePerson = (Person) fromJsonV1(joeJson, Person.class); 47 | fail(); // must throw JavaJsonException 48 | } catch (JsonException jjpe) { 49 | 50 | } 51 | } 52 | 53 | @Test 54 | void testV2() { 55 | // Parsing ok 56 | String billJson = "{name:\"Bill\", age:25, city:\"Rio de Janeiro\"}"; 57 | Person billPerson = (Person) fromJsonV2(billJson, Person.class); 58 | assertEquals(billPerson.getName(), "Bill"); 59 | assertEquals(billPerson.getAge(), 25); 60 | assertEquals(billPerson.getCity(), "Rio de Janeiro"); 61 | // Error Parsing 62 | String joeJson = "{ age:25, city:\"Rio de Janeiro\""; // invalid 63 | try { 64 | Person joePerson = (Person) fromJsonV2(joeJson, Person.class); 65 | fail(); // must throw JavaJsonException 66 | } catch (JsonException jjpe) { 67 | assertEquals(JsonSyntaxException.class, jjpe.getCause().getClass()); 68 | } 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /src/test/java/refactown/cleancode/c08boundary/java/GsonJsonParserTest.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c08boundary.java; 2 | 3 | import static org.junit.jupiter.api.Assertions.*; 4 | 5 | import org.junit.jupiter.api.Test; 6 | 7 | import refactown.cleancode.c06objects.PersonJ; 8 | 9 | class GsonJsonParserTest { 10 | 11 | @Test 12 | public void toJson() { 13 | GsonJsonParser parser = new GsonJsonParser(); 14 | PersonJ billPerson = new PersonJ("Bill", 25, "Rio de Janeiro"); 15 | String billJson = "{\"name\":\"Bill\",\"age\":25,\"city\":\"Rio de Janeiro\"}"; 16 | assertEquals(billJson, parser.toJson(billPerson)); 17 | } 18 | 19 | @Test 20 | public void fromJson() { 21 | GsonJsonParser parser = new GsonJsonParser(); 22 | PersonJ billPerson = new PersonJ("Bill", 25, "Rio de Janeiro"); 23 | String billJson = "{\"name\":\"Bill\",\"age\":25,\"city\":\"Rio de Janeiro\"}"; 24 | assertEquals(billPerson, parser.fromJson(billJson, PersonJ.class)); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/test/java/refactown/cleancode/c08boundary/java/GsonTest.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c08boundary.java; 2 | 3 | import org.junit.jupiter.api.Assertions; 4 | import org.junit.jupiter.api.Test; 5 | 6 | import com.google.gson.Gson; 7 | 8 | import refactown.cleancode.c06objects.Person; 9 | import refactown.cleancode.c06objects.PersonJ; 10 | 11 | public class GsonTest { 12 | 13 | @Test 14 | public void toJsonUsingGson() { 15 | Gson gson = new Gson(); 16 | PersonJ billPerson = new PersonJ("Bill", 25, "Rio de Janeiro"); 17 | String billJson = "{\"name\":\"Bill\",\"age\":25,\"city\":\"Rio de Janeiro\"}"; 18 | Assertions.assertEquals(billJson, gson.toJson(billPerson)); 19 | } 20 | 21 | @Test 22 | public void fromJsonUsingGson() { 23 | Gson gson = new Gson(); 24 | PersonJ billPerson = new PersonJ("Bill", 25, "Rio de Janeiro"); 25 | String billJson = "{\"name\":\"Bill\",\"age\":25,\"city\":\"Rio de Janeiro\"}"; 26 | Assertions.assertEquals(billPerson, gson.fromJson(billJson, PersonJ.class)); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/test/java/refactown/cleancode/c08boundary/java/LogonControllerTest.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c08boundary.java; 2 | 3 | import static org.junit.jupiter.api.Assertions.*; 4 | 5 | import org.junit.jupiter.api.Test; 6 | 7 | class LogonControllerTest { 8 | 9 | @Test 10 | public void logonManualDependency() { 11 | User userMock = new User("admin", "admin"); 12 | GsonJsonParser parser = new GsonJsonParser(); 13 | LogonController controller = new LogonController(parser); 14 | User user = controller.logon("admin", "123"); 15 | 16 | assertEquals(userMock.getLogin(), user.getLogin()); 17 | assertEquals(userMock.getRole(), user.getRole()); 18 | } 19 | 20 | @Test 21 | public void logonInjectDependency() { 22 | User userMock = new User("admin", "admin"); 23 | LogonController controller = inject(LogonController.class); 24 | User user = controller.logon("admin", "123"); 25 | 26 | assertEquals(userMock.getLogin(), user.getLogin()); 27 | assertEquals(userMock.getRole(), user.getRole()); 28 | 29 | } 30 | 31 | private LogonController inject(Class class1) { 32 | return new LogonController(new GsonJsonParser()); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/test/java/refactown/cleancode/c09tests/ContadorConstantesInteirasTest.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c09tests; 2 | 3 | import org.junit.jupiter.api.Assertions; 4 | import org.junit.jupiter.api.Test; 5 | 6 | import java.time.Month; 7 | import java.util.List; 8 | 9 | import static org.junit.jupiter.api.Assertions.assertEquals; 10 | 11 | public class ContadorConstantesInteirasTest { 12 | 13 | @Test 14 | public void testContagem(){ 15 | // parte1: preparação / cenário (s) 16 | ContadorConstantesInteiras contador = new ContadorConstantesInteiras(); 17 | // parte 3: validação 18 | assertEquals(2, contador.contar(Classe1.class)); 19 | assertEquals(-1, contador.contar(List.class)); 20 | assertEquals(-1, contador.contar(Month.class)); 21 | assertEquals(-1, contador.contar(null)); 22 | assertEquals(4, contador.contar(Classe2.class)); 23 | } 24 | } 25 | 26 | class Classe0{ 27 | public static final int CONST1 = 1; 28 | } 29 | 30 | class Classe1 extends Classe0{ 31 | public static final int CONST1 = 1; 32 | } 33 | 34 | class Classe2 extends Classe1 { 35 | public static final int CONST2 = 1; 36 | public static final int CONST3 = 1; 37 | } 38 | -------------------------------------------------------------------------------- /src/test/java/refactown/cleancode/c09tests/IntConstCounterTest.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c09tests; 2 | 3 | import static org.junit.jupiter.api.Assertions.*; 4 | 5 | import java.time.Month; 6 | import java.util.List; 7 | 8 | import org.junit.jupiter.api.Test; 9 | 10 | class IntConstCounterTest { 11 | 12 | // Requirement 1 - count integer constants 13 | @Test 14 | void testV1() { 15 | assertEquals(1, IntConstCounterV1.countIntConstV1(Class1.class)); 16 | } 17 | 18 | @Test 19 | void testV1AfterRefactoring() { 20 | assertEquals(1, IntConstCounterV1AfterRefactoring.countIntConstV1(Class1.class)); 21 | } 22 | 23 | // Requirement 2 - excludes Enum, null and Abstract 24 | @Test 25 | void testV2() { 26 | assertEquals(1, IntConstCounterV2.countIntConstV2(Class1.class)); 27 | 28 | assertEquals(-1, IntConstCounterV2.countIntConstV2(List.class)); // Abstract 29 | assertEquals(-1, IntConstCounterV2.countIntConstV2(Month.class));// Enum 30 | assertEquals(-1, IntConstCounterV2.countIntConstV2(null));// null 31 | } 32 | 33 | // Requirement 3 - inherited constants 34 | @Test 35 | void testV3() { 36 | assertEquals(1, IntConstCounterV3.countIntConstV3(Class1.class)); 37 | 38 | assertEquals(-1, IntConstCounterV3.countIntConstV3(List.class)); // Abstract 39 | assertEquals(-1, IntConstCounterV3.countIntConstV3(Month.class));// Enum 40 | assertEquals(-1, IntConstCounterV3.countIntConstV3(null));// null 41 | 42 | assertEquals(3, IntConstCounterV3.countIntConstV3(Class2.class)); // 2 inherited consts 43 | } 44 | 45 | } 46 | 47 | class Class1{ 48 | public static final int CONST1 = 1000; 49 | } 50 | 51 | class Class2 extends Class1{ 52 | public static final int CONST2 = 2000; 53 | public static final int CONST3 = 3000; 54 | } -------------------------------------------------------------------------------- /src/test/java/refactown/cleancode/c10classes/enums/MaoTest.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c10classes.enums; 2 | 3 | import static org.junit.jupiter.api.Assertions.*; 4 | 5 | import org.junit.jupiter.api.Test; 6 | 7 | class MaoTest { 8 | 9 | @Test 10 | void testRegraPrincipalPedraPapelTesoura() { 11 | assertTrue(Mao.PEDRA.vence(Mao.TESOURA)); 12 | assertTrue(Mao.TESOURA.vence(Mao.PAPEL)); 13 | assertTrue(Mao.PAPEL.vence(Mao.PEDRA)); 14 | } 15 | 16 | @Test 17 | void testMaoOf() { 18 | assertEquals(Mao.PEDRA, Mao.of('R')); 19 | assertEquals(Mao.PAPEL, Mao.of('P')); 20 | assertEquals(Mao.TESOURA, Mao.of('S')); 21 | assertThrows(IllegalArgumentException.class, ()->{ 22 | Mao.of('x'); 23 | }); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/test/java/refactown/cleancode/c10classes/model/JogadaTest.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c10classes.model; 2 | 3 | import static org.junit.jupiter.api.Assertions.*; 4 | 5 | import org.junit.jupiter.api.Test; 6 | 7 | import refactown.cleancode.c10classes.enums.Mao; 8 | import refactown.cleancode.c10classes.enums.ResultadoJogada; 9 | 10 | class JogadaTest { 11 | @Test void test() { 12 | Jogador bill = new JogadorMock("Bill (Primeiro)", Mao.PAPEL); 13 | Jogador bob = new JogadorMock("Bob (Segundo)", Mao.PEDRA); 14 | Jogada jogada = new JogadaSimples(bill, bob); 15 | assertEquals(ResultadoJogada.PRIMEIRO_VENCE, jogada.jogar()); 16 | } 17 | } 18 | 19 | class JogadorMock extends Jogador{ 20 | private final Mao mao; 21 | public JogadorMock(String nome, Mao mao) { 22 | super(nome); 23 | this.mao = mao; 24 | } 25 | @Override public Mao jogar() { 26 | return mao; 27 | } 28 | } 29 | 30 | -------------------------------------------------------------------------------- /src/test/java/refactown/cleancode/c10classes/model/MelhorDeTresTest.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c10classes.model; 2 | 3 | import org.junit.jupiter.api.Assertions; 4 | import org.junit.jupiter.api.Test; 5 | import refactown.cleancode.c10classes.enums.Mao; 6 | 7 | import static org.junit.jupiter.api.Assertions.*; 8 | 9 | class MelhorDeTresTest { 10 | 11 | @Test 12 | public void testJogo(){ 13 | // parte 1: cenário 14 | Jogador bill = new JogadorMock("Bill", Mao.PAPEL); 15 | Jogador bob = new JogadorMock("Bill", Mao.PEDRA); 16 | Jogada jogada = new JogadaSimples(bill, bob); 17 | MelhorDeTres melhorDeTres = new MelhorDeTres(jogada, 7); 18 | // parte 2: ação 19 | melhorDeTres.jogar(); 20 | // parte 3: validação 21 | assertFalse(!melhorDeTres.temVencedor()); 22 | assertEquals(bill, melhorDeTres.getVencedor()); 23 | assertTrue(bill == melhorDeTres.getVencedor()); 24 | assertEquals(4, melhorDeTres.getResultados().size()); 25 | } 26 | 27 | } -------------------------------------------------------------------------------- /src/test/java/refactown/cleancode/math/MathTest.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.math; 2 | 3 | import static org.junit.jupiter.api.Assertions.*; 4 | 5 | import org.junit.jupiter.api.Test; 6 | 7 | public class MathTest { 8 | 9 | @Test 10 | public void testAdd() { 11 | System.out.println("Test Java"); 12 | assertEquals(5, Math.add(2, 3)); 13 | assertEquals(5, MathKt.add(2, 3)); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/test/java/refactown/cleancode/megasena/ApostaTest.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.megasena; 2 | 3 | import org.junit.jupiter.api.Assertions; 4 | import org.junit.jupiter.api.Test; 5 | 6 | import java.util.Arrays; 7 | import java.util.List; 8 | 9 | import static org.junit.jupiter.api.Assertions.*; 10 | 11 | class ApostaTest { 12 | 13 | @Test 14 | public void testAposta() { 15 | //Aposta aposta = new Aposta(12, 15, 21, 36, 45, 54); 16 | Aposta aposta = Aposta.of(12, 15, 21, 36, 45, 54); 17 | assertEquals(Arrays.asList(12, 15, 21, 36, 45, 54), aposta.getNumeros()); 18 | } 19 | 20 | @Test 21 | public void deveDarErroApostaInvalidaPorMenosNumerosQueOMinimo(){ 22 | Assertions.assertThrows(IllegalArgumentException.class, ()->{ 23 | Aposta.of(04, 15, 22, 32, 47); // 5 números 24 | }); 25 | } 26 | 27 | @Test 28 | public void deveDarErroApostaInvalidaPorMaximo15Numeros(){ 29 | Assertions.assertThrows(IllegalArgumentException.class, ()->{ 30 | Aposta.of(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16); 31 | }); 32 | } 33 | 34 | @Test 35 | public void deveDarErroApostaInvalidaPorNumerosForaDaFaixa(){ 36 | Assertions.assertThrows(IllegalArgumentException.class, ()->{ 37 | Aposta.of(04, 15, 22, 61, 47, 55); // 61 = invalido 38 | }); 39 | } 40 | 41 | @Test 42 | public void deveDarErroApostaInvalidaPorNumeroDuplicado(){ 43 | Assertions.assertThrows(IllegalArgumentException.class, ()->{ 44 | Aposta.of(04, 15, 22, 32, 47, 47); // 47 duplicado 45 | }); 46 | } 47 | 48 | 49 | } -------------------------------------------------------------------------------- /src/test/java/refactown/cleancode/megasena/CalculadoraPremioTest.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.megasena; 2 | 3 | import org.junit.jupiter.api.Assertions; 4 | import org.junit.jupiter.api.Test; 5 | 6 | import java.util.Arrays; 7 | import java.util.List; 8 | 9 | public class CalculadoraPremioTest { 10 | 11 | @Test 12 | public void devePagarSenaOuCemPorCento(){ 13 | CalculadoraPremio calculadora = new CalculadoraPremio(); 14 | Aposta aposta = Aposta.of(03, 14, 21, 32, 47, 55); 15 | List sorteados = Arrays.asList(03, 14, 21, 32, 47, 55); 16 | double premio = calculadora.calcula(aposta, sorteados,1000.00); 17 | Assertions.assertEquals(1000.00, premio); 18 | } 19 | 20 | @Test 21 | public void devePagarQuinaOuVintePorCento(){ 22 | CalculadoraPremio calculadora = new CalculadoraPremio(); 23 | Aposta aposta = Aposta.of(04, 14, 21, 32, 47, 55); 24 | List sorteados = Arrays.asList(03, 14, 21, 32, 47, 55); 25 | double premio = calculadora.calcula(aposta, sorteados,1000.00); 26 | Assertions.assertEquals(200.00, premio); 27 | } 28 | 29 | @Test 30 | public void devePagarQuadraOuCincoPorCento(){ 31 | CalculadoraPremio calculadora = new CalculadoraPremio(); 32 | Aposta aposta = Aposta.of(04, 15, 21, 32, 47, 55); 33 | List sorteados = Arrays.asList(03, 14, 21, 32, 47, 55); 34 | double premio = calculadora.calcula(aposta, sorteados,1000.00); 35 | Assertions.assertEquals(50.00, premio); 36 | } 37 | 38 | @Test 39 | public void devePagarNada(){ 40 | CalculadoraPremio calculadora = new CalculadoraPremio(); 41 | Aposta aposta = Aposta.of(04, 15, 22, 32, 47, 55); 42 | List sorteados = Arrays.asList(03, 14, 21, 32, 47, 55); 43 | double premio = calculadora.calcula(aposta, sorteados,1000.00); 44 | Assertions.assertEquals(0.00, premio); 45 | } 46 | 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/test/java/refactown/cleancode/megasena/MegaSenaTest.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.megasena; 2 | 3 | import org.junit.jupiter.api.Test; 4 | 5 | import static org.junit.jupiter.api.Assertions.*; 6 | 7 | 8 | import java.util.Arrays; 9 | import java.util.List; 10 | 11 | class MegaSenaTest { 12 | 13 | @Test 14 | void calculaPremioV1() { 15 | MegaSenaV1 megaSena = new MegaSenaV1(); 16 | double premio = megaSena.calculaPremio(Arrays.asList(12, 34, 55, 23, 14, 44), 2000.0); 17 | assertTrue(premio >=0.0); 18 | } 19 | 20 | @Test 21 | void deveLancarExcecaoPorApostaInvalida() { 22 | MegaSenaV4 megaSena = new MegaSenaV4(); 23 | assertThrows(IllegalArgumentException.class, () -> { 24 | megaSena.calculaPremio(Arrays.asList(23, 14, 44), 2000.0); 25 | }); 26 | } 27 | 28 | @Test 29 | void devePagarPremioTotalV5() { 30 | List apostados = Arrays.asList(05, 12, 25, 32, 44, 51); 31 | List sorteados = Arrays.asList(05, 12, 25, 32, 44, 51); 32 | double premio = 2000.0; 33 | MegaSenaV5 megaSena = new MegaSenaV5(); 34 | assertEquals(premio, megaSena.calculaPremio(apostados, sorteados, premio)); 35 | } 36 | 37 | @Test 38 | void devePagarQuinaV5() { 39 | List apostados = Arrays.asList(05, 12, 25, 32, 44, 51); 40 | List sorteados = Arrays.asList(05, 12, 25, 32, 44, 59); 41 | double premio = 2000.0; 42 | MegaSenaV5 megaSena = new MegaSenaV5(); 43 | assertEquals(premio * 0.2, megaSena.calculaPremio(apostados, sorteados, premio)); 44 | } 45 | 46 | @Test 47 | void devePagarQuadraV5() { 48 | List apostados = Arrays.asList(05, 12, 25, 32, 44, 51); 49 | List sorteados = Arrays.asList(05, 12, 25, 32, 49, 59); 50 | double premio = 2000.0; 51 | MegaSenaV5 megaSena = new MegaSenaV5(); 52 | assertEquals(premio * 0.05, megaSena.calculaPremio(apostados, sorteados, premio)); 53 | } 54 | 55 | @Test 56 | void devePagarNadaV5() { 57 | List apostados = Arrays.asList(05, 12, 25, 32, 44, 51); 58 | List sorteados = Arrays.asList(05, 12, 25, 39, 49, 59); 59 | double premio = 2000.0; 60 | MegaSenaV5 megaSena = new MegaSenaV5(); 61 | assertEquals(0.0, megaSena.calculaPremio(apostados, sorteados, premio)); 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /src/test/java/refactown/cleancode/megasena/modelo/CpfTest.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.megasena.modelo; 2 | 3 | import org.junit.jupiter.api.Test; 4 | 5 | import static org.junit.jupiter.api.Assertions.*; 6 | 7 | class CpfTest { 8 | 9 | @Test 10 | void deveCriarCpfComNumeroPassado(){ 11 | String numeroSimples = "07311631769"; 12 | Cpf cpfPuro = new Cpf(numeroSimples); 13 | assertEquals(numeroSimples, cpfPuro.getNumero()); 14 | } 15 | 16 | @Test 17 | void deveCriarCpfComNumeroPassadoIgnorandoPontosTracos(){ 18 | String numeroSimples = "07311631769"; 19 | String numeroFormatado = "073.116.317-69"; 20 | Cpf cpfFormatado = new Cpf(numeroFormatado); 21 | assertEquals(numeroSimples, cpfFormatado.getNumero()); 22 | } 23 | 24 | @Test 25 | void deveSubirExcecaoSeNumeroForNull(){ 26 | assertThrows(NullPointerException.class, () -> { new Cpf(null); }); 27 | } 28 | 29 | @Test 30 | void deveSubirExcecaoParaNumerosComCaracteresInvalidos(){ // 0-9, ponto ou traço 31 | assertThrows(IllegalArgumentException.class, () -> { new Cpf("073.116.317/69"); });// barra 32 | assertThrows(IllegalArgumentException.class, () -> { new Cpf("073,116,317-69"); });// virgula 33 | assertThrows(IllegalArgumentException.class, () -> { new Cpf("073.116.317-6A"); });// A 34 | 35 | } 36 | 37 | @Test 38 | void deveSubirExcecaoParaNumerosComTamanhoInvalidoDiferenteDe11(){ 39 | assertThrows(IllegalArgumentException.class, () -> { new Cpf("123"); });//3 40 | assertThrows(IllegalArgumentException.class, () -> { new Cpf("12345678901234567890"); });//20 41 | } 42 | 43 | @Test 44 | void deveConsiderarIgual() { 45 | assertEquals(new Cpf("07311631769"), new Cpf("07311631769")); 46 | } 47 | 48 | @Test 49 | void deveConsiderarDiferente() { 50 | assertNotEquals(new Cpf("12345678900"), new Cpf("07311631769")); 51 | } 52 | 53 | @Test 54 | void deveConsiderarHashCodeIgual() { 55 | assertTrue(new Cpf("07311631769").hashCode()== new Cpf("07311631769").hashCode()); 56 | } 57 | 58 | @Test 59 | void deveConsiderarHashCodeDiferente() { 60 | assertFalse(new Cpf("07311631769").hashCode() != new Cpf("07311631769").hashCode()); 61 | } 62 | 63 | @Test 64 | void deveUsarNumeroComoSaidaParaToString() { 65 | Cpf cpf = new Cpf("07311631769"); 66 | assertEquals("07311631769", cpf.getNumero()); 67 | } 68 | } -------------------------------------------------------------------------------- /src/test/java/refactown/cleancode/megasena/v6/ApostaTest.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.megasena.v6; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import refactown.cleancode.megasena.v6.Aposta; 5 | import refactown.cleancode.megasena.v6.Resultado; 6 | 7 | import java.util.List; 8 | 9 | import static java.util.Arrays.*; 10 | 11 | import static org.junit.jupiter.api.Assertions.*; 12 | 13 | 14 | class ApostaTest { 15 | 16 | @Test 17 | void deveDarErroApostaInvalida() { 18 | assertThrows(IllegalArgumentException.class, () -> { new Aposta(asList(23, 14, 44)); }); 19 | assertThrows(IllegalArgumentException.class, () -> { new Aposta(asList()); }); 20 | List maisQue15 = asList(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16); 21 | assertThrows(IllegalArgumentException.class, () -> { new Aposta(maisQue15); }); 22 | 23 | } 24 | @Test 25 | void testCalculaAcertos() { 26 | Aposta aposta = new Aposta(asList(5, 13, 27, 34, 41, 52)); 27 | Resultado resultado = new Resultado(asList(5, 13, 27, 34, 41, 52)); 28 | assertEquals(6, new Aposta(asList(5, 13, 27, 34, 41, 52)).calculaAcertos(resultado)); 29 | assertEquals(6, new Aposta(asList(1, 05, 13, 27, 34, 41, 52, 56)).calculaAcertos(resultado)); 30 | assertEquals(4, new Aposta(asList(9, 13, 27, 34, 41, 59)).calculaAcertos(resultado)); 31 | assertEquals(0, new Aposta(asList(9, 19, 29, 39, 49, 59)).calculaAcertos(resultado)); 32 | } 33 | 34 | @Test 35 | void deveRetornarOsSeisNumerosPassadosAoCriar() { 36 | Aposta aposta = new Aposta(asList(05, 13, 27, 34, 41, 52)); 37 | assertEquals(asList(05, 13, 27, 34, 41, 52), aposta.getNumeros()); 38 | 39 | } 40 | } -------------------------------------------------------------------------------- /src/test/java/refactown/cleancode/megasena/v6/GloboGiratorioTest.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.megasena.v6; 2 | 3 | import org.junit.jupiter.api.Test; 4 | 5 | import static org.junit.jupiter.api.Assertions.*; 6 | 7 | class GloboGiratorioTest { 8 | 9 | @Test 10 | void sorteioRandomicoDeveGerarSeisNumerosDiferentesEntre1e60() { 11 | GloboGiratorio globoGiratorio = new GloboGiratorio(Aposta.ULTIMO_NUMERO); 12 | Resultado resultado = globoGiratorio.sorteiaNumeros(6); 13 | assertEquals(6, resultado.getNumeros().size()); 14 | assertEquals(6, resultado.getNumeros().stream().distinct().count()); 15 | assertEquals(6, resultado.getNumeros().stream().filter(n-> n >=1 && n <= 60).count()); 16 | } 17 | 18 | } -------------------------------------------------------------------------------- /src/test/java/refactown/cleancode/megasena/v6/PremioTest.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.megasena.v6; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import refactown.cleancode.megasena.v6.Aposta; 5 | import refactown.cleancode.megasena.v6.Premio; 6 | import refactown.cleancode.megasena.v6.Resultado; 7 | 8 | import static java.util.Arrays.asList; 9 | import static org.junit.jupiter.api.Assertions.*; 10 | 11 | class PremioTest { 12 | 13 | @Test 14 | void devePagar100PorCento() { // sena 15 | Aposta aposta = new Aposta(asList(5, 13, 27, 34, 41, 52)); 16 | Resultado resultado = new Resultado(asList(5, 13, 27, 34, 41, 52)); 17 | Premio premio = new Premio(1000.0); 18 | assertEquals(1000.0, premio.calcula(aposta, resultado));// 100% 19 | } 20 | 21 | @Test 22 | void devePagar20PorCento() { // quina 23 | Aposta aposta = new Aposta(asList(5, 13, 27, 34, 41, 59));// 1 errado 24 | Resultado resultado = new Resultado(asList(5, 13, 27, 34, 41, 52)); 25 | Premio premio = new Premio(1000.0); 26 | assertEquals(1000.0 * 0.2, premio.calcula(aposta, resultado));// 20% 27 | } 28 | 29 | @Test 30 | void devePagar5PorCento() { // quadra 31 | Aposta aposta = new Aposta(asList(5, 13, 27, 34, 49, 59));// 2 errados 32 | Resultado resultado = new Resultado(asList(5, 13, 27, 34, 41, 52)); 33 | Premio premio = new Premio(1000.0); 34 | assertEquals(1000.0 * 0.05, premio.calcula(aposta, resultado));// 5% 35 | } 36 | 37 | @Test 38 | void devePagarNada() { 39 | Aposta aposta = new Aposta(asList(5, 13, 27, 39, 49, 59));// 3 errados 40 | Resultado resultado = new Resultado(asList(5, 13, 27, 34, 41, 52)); 41 | Premio premio = new Premio(1000.0); 42 | assertEquals(0.0, premio.calcula(aposta, resultado));// 0 43 | } 44 | 45 | } -------------------------------------------------------------------------------- /src/test/java/refactown/cleancode/megasena/v6/ResultadoTest.java: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.megasena.v6; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import refactown.cleancode.megasena.v6.Resultado; 5 | 6 | import java.util.Arrays; 7 | 8 | import static org.junit.jupiter.api.Assertions.*; 9 | 10 | class ResultadoTest { 11 | 12 | 13 | @Test 14 | void deveRetornarSeisNumerosNaOrdem0() { 15 | Resultado resultado = new Resultado(Arrays.asList(5, 13, 27, 34, 41, 52)); 16 | assertEquals(Arrays.asList(5, 13, 27, 34, 41, 52), resultado.getNumeros()); 17 | assertTrue(resultado.foiSorteado(5)); 18 | assertTrue(resultado.foiSorteado(13)); 19 | assertTrue(resultado.foiSorteado(27)); 20 | assertTrue(resultado.foiSorteado(34)); 21 | assertTrue(resultado.foiSorteado(41)); 22 | assertTrue(resultado.foiSorteado(52)); 23 | 24 | assertFalse(resultado.foiSorteado(59)); 25 | } 26 | 27 | } -------------------------------------------------------------------------------- /src/test/java/tdc2020poa/DisputaTest.java: -------------------------------------------------------------------------------- 1 | package tdc2020poa; 2 | 3 | import org.junit.jupiter.api.Test; 4 | 5 | import static org.junit.jupiter.api.Assertions.*; 6 | 7 | class DisputaTest { 8 | 9 | @Test 10 | public void testDisputaLegada(){ 11 | Jogador bill = new JogadorMock("Bill (Primeiro)", Mao.PAPEL); 12 | Jogador bob = new JogadorMock("Bob (Segundo)", Mao.PEDRA); 13 | Disputa disputa = new DisputaLegada(bill, bob); 14 | Resultado resultado = disputa.jogar(); 15 | assertEquals(Resultado.PRIMEIRO_VENCE, resultado); 16 | } 17 | 18 | @Test 19 | public void testDisputaNova(){ 20 | Jogador bill = new JogadorMock("Bill (Primeiro)", Mao.PAPEL); 21 | Jogador bob = new JogadorMock("Bob (Segundo)", Mao.PEDRA); 22 | Disputa disputa = new DisputaNova(bill, bob); 23 | Resultado resultado = disputa.jogar(); 24 | assertEquals(Resultado.PRIMEIRO_VENCE, resultado); 25 | } 26 | 27 | } 28 | 29 | -------------------------------------------------------------------------------- /src/test/java/tdc2020poa/JogadorMock.java: -------------------------------------------------------------------------------- 1 | package tdc2020poa; 2 | 3 | public class JogadorMock extends Jogador { 4 | private final Mao mao; 5 | public JogadorMock(String nome, Mao mao) { 6 | super(nome); 7 | this.mao = mao; 8 | } 9 | @Override public Mao jogar() { 10 | return mao; 11 | } 12 | } -------------------------------------------------------------------------------- /src/test/java/tdc2020poa/JogoTest.java: -------------------------------------------------------------------------------- 1 | package tdc2020poa; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import refactown.cleancode.c10classes.Result; 5 | 6 | import static org.junit.jupiter.api.Assertions.*; 7 | 8 | class JogoTest { 9 | 10 | @Test 11 | public void testJogo(){ 12 | // parte 1: cenário 13 | Jogador bill = new JogadorMock("Bill", Mao.PAPEL); 14 | Jogador bob = new JogadorMock("Bob", Mao.PEDRA); 15 | Disputa disputa = new DisputaLegada(bill, bob); 16 | Jogo jogo = new Jogo(disputa, 7); 17 | // parte 2: ação 18 | jogo.jogar(); 19 | // parte 3: validação 20 | assertFalse(!jogo.temVencedor()); 21 | assertEquals(bill, jogo.getVencedor()); 22 | assertTrue(bill == jogo.getVencedor()); 23 | assertEquals(4, jogo.getResultados().size()); 24 | } 25 | 26 | @Test 27 | public void testJogoMocandoDisputa(){ 28 | // parte 1: cenário 29 | Jogador bill = new Jogador("Bill"); 30 | Jogador bob = new Jogador("Bob"); 31 | Disputa disputa = new Disputa(bill, bob){ 32 | @Override public Resultado jogar() { 33 | return Resultado.SEGUNDO_VENCE; 34 | } 35 | }; 36 | Jogo jogo = new Jogo(disputa, 7); 37 | // parte 2: ação 38 | jogo.jogar(); 39 | // parte 3: validação 40 | assertFalse(!jogo.temVencedor()); 41 | assertEquals(bob, jogo.getVencedor()); 42 | assertTrue(bob == jogo.getVencedor()); 43 | assertEquals(4, jogo.getResultados().size()); 44 | } 45 | 46 | 47 | } -------------------------------------------------------------------------------- /src/test/java/tdc2020poa/MaoTest.java: -------------------------------------------------------------------------------- 1 | package tdc2020poa; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import refactown.cleancode.c10classes.enums.Mao; 5 | 6 | import static org.junit.jupiter.api.Assertions.*; 7 | 8 | class MaoTest { 9 | 10 | @Test 11 | void testRegraPrincipalPedraPapelTesoura() { 12 | assertTrue(Mao.PEDRA.vence(Mao.TESOURA)); 13 | assertTrue(Mao.TESOURA.vence(Mao.PAPEL)); 14 | assertTrue(Mao.PAPEL.vence(Mao.PEDRA)); 15 | } 16 | 17 | @Test 18 | void testMaoOf() { 19 | assertEquals(Mao.PEDRA, Mao.of('R')); 20 | assertEquals(Mao.PAPEL, Mao.of('P')); 21 | assertEquals(Mao.TESOURA, Mao.of('S')); 22 | assertThrows(IllegalArgumentException.class, ()->{ 23 | Mao.of('x'); 24 | }); 25 | } 26 | 27 | } -------------------------------------------------------------------------------- /src/test/kotlin/refactown/cleancode/README.txt: -------------------------------------------------------------------------------- 1 | Clean Code Samples 2 | 3 | This package has kotlin samples -------------------------------------------------------------------------------- /src/test/kotlin/refactown/cleancode/c01cleancode/Cap01Test.kt: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c01cleancode 2 | 3 | import org.junit.jupiter.api.Assertions.* 4 | import java.util.ArrayList 5 | import java.time.Month 6 | import org.junit.jupiter.api.Test 7 | 8 | 9 | internal class Cap01Test { 10 | 11 | @Test 12 | fun testBadCode() { 13 | assertEquals(-1, constants(null)) 14 | assertEquals(-1, constants(List::class.java)) 15 | assertEquals(-1, constants(Month::class.java)) 16 | 17 | assertEquals(0, constants(Any::class.java)) 18 | 19 | assertEquals(4, constants(ArrayList::class.java)) 20 | } 21 | 22 | @Test 23 | fun testrefactoring1() { 24 | assertEquals(-1, countIntConstants(null)) 25 | assertEquals(-1, countIntConstants(List::class.java)) 26 | assertEquals(-1, countIntConstants(Month::class.java)) 27 | 28 | assertEquals(0, countIntConstants(Any::class.java)) 29 | 30 | assertEquals(4, countIntConstants(ArrayList::class.java)) 31 | } 32 | 33 | @Test 34 | fun testrefactoring2() { 35 | //assertEquals(-1, countIntegerConstants(null)) 36 | assertEquals(-1, countIntegerConstants(List::class.java)) 37 | assertEquals(-1, countIntegerConstants(Month::class.java)) 38 | 39 | assertEquals(0, countIntegerConstants(Any::class.java)) 40 | 41 | assertEquals(8, countIntegerConstants(ArrayList::class.java)) 42 | } 43 | 44 | } -------------------------------------------------------------------------------- /src/test/kotlin/refactown/cleancode/c03functions/FibonacciKtTest.kt: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c03functions 2 | 3 | import org.junit.jupiter.api.Test 4 | 5 | import org.junit.jupiter.api.Assertions.* 6 | 7 | internal class FibonacciKtTest { 8 | 9 | @Test 10 | fun testFib() { 11 | assertEquals(0, fib(0)) 12 | assertEquals(1, fib(1)) 13 | assertEquals(1, fib(2)) 14 | assertEquals(2, fib(3)) 15 | assertEquals(3, fib(4)) 16 | assertEquals(5, fib(5)) 17 | assertEquals(8, fib(6)) 18 | assertEquals(13, fib(7)) 19 | assertEquals(21, fib(8)) 20 | assertEquals(34, fib(9)) 21 | assertEquals(55, fib(10)) 22 | } 23 | 24 | @Test 25 | fun testSeq(){ 26 | assertEquals("0,1,1,2,3,5", seq(5)) 27 | assertEquals("0,1,1,2,3,5,8,13,21,34,55", seq(10)) 28 | assertEquals("0,1,1,2,3,5,8,13,21,34,55,89,144,233,377,610," + 29 | "987,1597,2584,4181,6765,10946,17711,28657,46368,75025," + 30 | "121393,196418,317811,514229,832040,1346269,2178309,3524578," + 31 | "5702887,9227465,14930352,24157817,39088169,63245986,102334155", seq(40)) 32 | } 33 | } -------------------------------------------------------------------------------- /src/test/kotlin/refactown/cleancode/c03functions/FunctionsKtTest.kt: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c03functions 2 | 3 | import org.junit.jupiter.api.Test 4 | 5 | import org.junit.jupiter.api.Assertions.* 6 | import refactown.cleancode.c06objects.Person 7 | import refactown.cleancode.c07exceptions.JsonException 8 | import refactown.cleancode.c07exceptions.fromJsonV1 9 | import java.lang.IllegalArgumentException 10 | 11 | internal class FunctionsKtTest { 12 | 13 | @Test 14 | fun testRockPaperScissors() { 15 | // DRAW = 0 16 | assertEquals(0, rockPaperScissors('R','R')) 17 | assertEquals(0, rockPaperScissors('P','P')) 18 | assertEquals(0, rockPaperScissors('S','S')) 19 | // Fisrt Wins = -1 20 | assertEquals(-1, rockPaperScissors('R','S')) 21 | assertEquals(-1, rockPaperScissors('S','P')) 22 | assertEquals(-1, rockPaperScissors('P','R')) 23 | // Second Wins = 1 24 | assertEquals(1, rockPaperScissors('S','R')) 25 | assertEquals(1, rockPaperScissors('P','S')) 26 | assertEquals(1, rockPaperScissors('R','P')) 27 | // Illegal Argument 28 | assertThrows(IllegalArgumentException::class.java) { 29 | rockPaperScissors('A', 'R') 30 | } 31 | assertThrows(IllegalArgumentException::class.java) { 32 | rockPaperScissors('S', '*') 33 | } 34 | assertThrows(IllegalArgumentException::class.java) { 35 | rockPaperScissors(' ', '%') 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /src/test/kotlin/refactown/cleancode/c05format/ExampleClassTest.kt: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c05format 2 | 3 | import org.junit.jupiter.api.Test 4 | 5 | import org.junit.jupiter.api.Assertions.* 6 | 7 | internal class ExampleClassTest { 8 | 9 | @Test 10 | fun testFunction1() { 11 | val obj = ExampleClass() 12 | obj.function1() 13 | } 14 | 15 | } -------------------------------------------------------------------------------- /src/test/kotlin/refactown/cleancode/c06objects/BookExampleTest.kt: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c06objects 2 | 3 | import org.junit.jupiter.api.Assertions.* 4 | import org.junit.jupiter.api.Test 5 | 6 | internal class BookExampleTest { 7 | 8 | @Test 9 | fun proceduralExample() { 10 | val square = Square(3.0) 11 | val rectangle = Rectangle(2.0, 4.5) 12 | val circle = Circle(2.0) 13 | 14 | assertEquals(calculateArea(square), 9.0) 15 | assertEquals(calculateArea(rectangle), 9.0) 16 | assertEquals(calculateArea(circle), 12.5664) 17 | } 18 | 19 | @Test 20 | fun ooExample() { 21 | val square = SquareOO(3.0) 22 | val rectangle = RectangleOO(2.0, 4.5) 23 | val circle = CircleOO(2.0) 24 | 25 | assertEquals(square.area(), 9.0) 26 | assertEquals(rectangle.area(), 9.0) 27 | assertEquals(circle.area(), 12.5664) 28 | } 29 | 30 | } -------------------------------------------------------------------------------- /src/test/kotlin/refactown/cleancode/c06objects/PersonTest.kt: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c06objects 2 | 3 | import org.junit.jupiter.api.Assertions.* 4 | import org.junit.jupiter.api.Test 5 | 6 | internal class PersonTest{ 7 | 8 | @Test 9 | fun testBadCode() { 10 | val personKotlin = Person("Bill", 25, "Rio de Janeiro") 11 | //val personKotlin = Person("Bill", 25, "Rio de Janeiro") 12 | val personJava = PersonJ("Bill", 25, "Rio de Janeiro") 13 | assertNotEquals(personKotlin, personJava) 14 | assertEquals(personKotlin.name, personJava.name) 15 | assertEquals(personKotlin.age, personJava.age) 16 | assertEquals(personKotlin.city, personJava.city) 17 | } 18 | } -------------------------------------------------------------------------------- /src/test/kotlin/refactown/cleancode/c07exceptions/JsonParsingKtTest.kt: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c07exceptions 2 | 3 | import com.google.gson.JsonSyntaxException 4 | import org.junit.jupiter.api.Test 5 | 6 | import org.junit.jupiter.api.Assertions.* 7 | import refactown.cleancode.c06objects.Person 8 | import java.io.IOException 9 | 10 | internal class JsonParsingKtTest { 11 | 12 | @Test 13 | fun testNullVersion(){ 14 | // Parsing ok 15 | val billJson = "{name:\"Bill\", age:25, city:\"Rio de Janeiro\"}"; 16 | val billPerson= fromJsonV0(billJson, Person::class.java) as Person? 17 | assertEquals(billPerson?.name, "Bill") 18 | assertEquals(billPerson?.age, 25) 19 | assertEquals(billPerson?.city, "Rio de Janeiro") 20 | // Error Parsing 21 | val joeJson = "{ age:25, city:\"Rio de Janeiro\"" 22 | val joePerson = fromJsonV0(joeJson, Person::class.java) as Person? 23 | assertEquals(joePerson?.name, null) 24 | assertEquals(joePerson?.age, null) 25 | assertEquals(joePerson?.city, null) 26 | } 27 | 28 | @Test 29 | fun testV1(){ 30 | // Parsing ok 31 | val billJson = "{name:\"Bill\", age:25, city:\"Rio de Janeiro\"}"; 32 | val billPerson= fromJsonV1(billJson, Person::class.java) as Person 33 | assertEquals(billPerson.name, "Bill") 34 | assertEquals(billPerson.age, 25) 35 | assertEquals(billPerson.city, "Rio de Janeiro") 36 | // Error Parsing 37 | val joeJson = "{ age:25, city:\"Rio de Janeiro\"" 38 | assertThrows(JsonException::class.java) { 39 | fromJsonV1(joeJson, Person::class.java) as Person 40 | } 41 | } 42 | 43 | @Test 44 | fun testV2(){ 45 | // Parsing ok 46 | val billJson = "{name:\"Bill\", age:25, city:\"Rio de Janeiro\"}"; 47 | val billPerson= fromJsonV2(billJson, Person::class.java) as Person 48 | assertEquals(billPerson.name, "Bill") 49 | assertEquals(billPerson.age, 25) 50 | assertEquals(billPerson.city, "Rio de Janeiro") 51 | // Error Parsing 52 | val joeJson = "{ age:25, city:\"Rio de Janeiro\"" 53 | try { 54 | fromJsonV2(joeJson, Person::class.java) as Person 55 | } catch (e: JsonException) { 56 | assertEquals(JsonSyntaxException::class.java, e?.cause?.javaClass) 57 | } 58 | } 59 | 60 | 61 | } -------------------------------------------------------------------------------- /src/test/kotlin/refactown/cleancode/c08boundary/GsonJsonParserTest.kt: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c08boundary 2 | 3 | import org.junit.jupiter.api.Test 4 | 5 | import org.junit.jupiter.api.Assertions.* 6 | import refactown.cleancode.c06objects.Person 7 | 8 | internal class GsonJsonParserTest { 9 | 10 | @Test 11 | fun toJson() { 12 | val parser = GsonJsonParser() 13 | val billPerson = Person("Bill", 25, "Rio de Janeiro") 14 | val billJson = "{\"name\":\"Bill\",\"age\":25,\"city\":\"Rio de Janeiro\"}" 15 | assertEquals(billJson, parser.toJson(billPerson)) 16 | } 17 | 18 | @Test 19 | fun fromJson() { 20 | val parser = GsonJsonParser() 21 | val billPerson = Person("Bill", 25, "Rio de Janeiro") 22 | val billJson = "{\"name\":\"Bill\",\"age\":25,\"city\":\"Rio de Janeiro\"}" 23 | assertEquals(billPerson, parser.fromJson(billJson, Person::class.java)) 24 | } 25 | } -------------------------------------------------------------------------------- /src/test/kotlin/refactown/cleancode/c08boundary/GsonTest.kt: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c08boundary 2 | 3 | import com.google.gson.Gson 4 | import org.junit.jupiter.api.Assertions 5 | import org.junit.jupiter.api.Test 6 | import refactown.cleancode.c06objects.Person 7 | 8 | class GsonTest { 9 | 10 | @Test 11 | fun toJsonUsingGson() { 12 | val gson = Gson() 13 | val billPerson = Person("Bill", 25, "Rio de Janeiro") 14 | val billJson = "{\"name\":\"Bill\",\"age\":25,\"city\":\"Rio de Janeiro\"}" 15 | Assertions.assertEquals(billJson, gson.toJson(billPerson)) 16 | } 17 | 18 | @Test 19 | fun fromJsonUsingGson() { 20 | val gson = Gson() 21 | val billPerson = Person("Bill", 25, "Rio de Janeiro") 22 | val billJson = "{\"name\":\"Bill\",\"age\":25,\"city\":\"Rio de Janeiro\"}" 23 | Assertions.assertEquals(billPerson, gson.fromJson(billJson, Person::class.java)) 24 | } 25 | } -------------------------------------------------------------------------------- /src/test/kotlin/refactown/cleancode/c08boundary/LogonControllerTest.kt: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c08boundary 2 | 3 | import org.junit.jupiter.api.* 4 | 5 | import org.junit.jupiter.api.Assertions.* 6 | 7 | internal class LogonControllerTest { 8 | 9 | 10 | @Test 11 | fun logonManualDependency() { 12 | val userMock = User("admin", "admin") 13 | val parser = GsonJsonParser() 14 | val controller = LogonController(parser) 15 | val user = controller.logon("admin", "123") 16 | 17 | assertEquals(userMock, user) 18 | } 19 | 20 | @Test 21 | fun logonInjectDependency() { 22 | val userMock = User("admin", "admin") 23 | val controller = inject(LogonController::class.java) as LogonController 24 | val user = controller.logon("admin", "123") 25 | 26 | assertEquals(userMock, user) 27 | } 28 | 29 | } 30 | 31 | fun inject(clazz: Class<*>): Any{ 32 | return LogonController(GsonJsonParser()) 33 | } 34 | -------------------------------------------------------------------------------- /src/test/kotlin/refactown/cleancode/c10classes/HandTest.kt: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c10classes 2 | 3 | import org.junit.jupiter.api.Test 4 | 5 | import org.junit.jupiter.api.Assertions.* 6 | 7 | internal class HandTest { 8 | 9 | @Test 10 | fun testBeats() { 11 | assertTrue(Hand.ROCK beats Hand.SCISSORS) 12 | assertTrue(Hand.SCISSORS.beats(Hand.PAPER)) 13 | assertTrue(Hand.PAPER.beats(Hand.ROCK)) 14 | } 15 | } -------------------------------------------------------------------------------- /src/test/kotlin/refactown/cleancode/c10classes/MatchTest.kt: -------------------------------------------------------------------------------- 1 | package refactown.cleancode.c10classes 2 | 3 | import org.junit.jupiter.api.Test 4 | 5 | import org.junit.jupiter.api.Assertions.* 6 | 7 | internal class MatchTest { 8 | 9 | @Test 10 | fun testPlay() { 11 | val bill = MockPlayer("Bill", Hand.PAPER) 12 | val bob = MockPlayer("Bob", Hand.ROCK) 13 | val match = Match(bill,bob) 14 | assertEquals(MatchResult.SECOND_WINS, match.play()) 15 | } 16 | } 17 | 18 | class MockPlayer(name: String, private val hand: Hand) 19 | : Player(name) { 20 | override fun play() = hand 21 | } -------------------------------------------------------------------------------- /src/test/kotlin/refactown/cleancode/math/MathKtTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of Refactown Clean Code. 3 | * 4 | * Refactown Clean Code is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * Refactown Clean Code is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with Refactown Clean Code. If not, see . 16 | */ 17 | package refactown.cleancode.math 18 | 19 | import org.junit.jupiter.api.Assertions.assertEquals 20 | import org.junit.jupiter.api.Test 21 | 22 | 23 | /** 24 | * @author Douglas Siviotti 25 | */ 26 | class MathKtTest { 27 | 28 | @Test 29 | fun testAdd() { 30 | println("Test Kotlin") 31 | assertEquals(5, Math.add(2,3)) 32 | assertEquals(5, add(2,3)) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/test/resources/README.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/refactown/cleancode/921639d08022db03410b87990e97e2ce219680bb/src/test/resources/README.txt --------------------------------------------------------------------------------