---
# System prepended metadata

title: '**Code Smells**'

---

##  Trabalho da disciplina <b>Tópicos Especiais em Desenvolvimento de Software</b>
## Projetos em C# e Java
<p>
    <b>Nome: Adriano Andrade<br>
        6° Periodo
    </b>
</p>


# **Code Smells**

<font size = "4"><b>1° problema: código dublicado</b></font>

<p>
     &nbsp Linhas em vários métodos da classe repository com a mesma finalidade de busca passando data mínima e máxima.
</p>

```csharp
public async Task < List < SalesRecord >> FindByDateAsync(DateTime ? minDate, DateTime ? maxDate) {
  var result = from obj in _context.SalesRecord select obj;

  if (minDate.HasValue) {
    result = result.Where(x => x.Date >= minDate.Value);
  }
  if (maxDate.HasValue) {
    result = result.Where(x => x.Date <= maxDate.Value);
  }
    
  return await result
    .Include(x => x.Seller)
    .Include(x => x.Seller.Department)
    .OrderByDescending(x => x.Date)
    .ToListAsync();
}

public async Task < List < IGrouping < Department, SalesRecord >>> FindByDateGroupingAsync(DateTime ? minDate, DateTime ? maxDate) {
  var result = from obj in _context.SalesRecord select obj;

  if (minDate.HasValue) {
    result = result.Where(x => x.Date >= minDate.Value);
  }
  if (maxDate.HasValue) {
    result = result.Where(x => x.Date <= maxDate.Value);
  }
  return await result
    .Include(x => x.Seller)
    .Include(x => x.Seller.Department)
    .OrderByDescending(x => x.Date)
    .GroupBy(x => x.Seller.Department)
    .ToListAsync();
}
```
<font size = "4"><b>Solução: extração de métodos</b></font>
<p>
   &nbsp Foi aplicado a <b>extração de métodos</b> na classe repository onde havia repetição de linhas em vários métodos.
</p>

```csharp
public async Task < List < SalesRecord >> FindByDateAsync(DateTime ? minDate, DateTime ? maxDate) {
  var result = from obj in _context.SalesRecord select obj;
  result = GetMinMaxDate(minDate, maxDate, result);

  return await result
    .Include(x => x.Seller)
    .Include(x => x.Seller.Department)
    .OrderByDescending(x => x.Date)
    .ToListAsync();
}

public async Task < List < IGrouping < Department, SalesRecord >>> FindByDateGroupingAsync(DateTime ? minDate, DateTime ? maxDate) {
  var result = from obj in _context.SalesRecord select obj;
  result = GetMinMaxDate(minDate, maxDate, result);

  return await result
    .Include(x => x.Seller)
    .Include(x => x.Seller.Department)
    .OrderByDescending(x => x.Date)
    .GroupBy(x => x.Seller.Department)
    .ToListAsync();
}
```

<font size = "4"><b>método extraido </b></font>

```csharp
private static IQueryable < SalesRecord > GetMinMaxDate(DateTime ? minDate, DateTime ? maxDate, IQueryable < SalesRecord > result) {
    
  if (minDate.HasValue)
    result = result.Where(x => x.Date >= minDate.Value);

  if (maxDate.HasValue)
    result = result.Where(x => x.Date <= maxDate.Value);

  return result;
}
```

<font size = "4"><b>2° problema: feature envy</b></font>
<p>
 &nbsp Veja como o cliente acessa os dados da agenda para formatar a consulta, 
</p>

```java

public class Cliente {
    private Agenda agenda;

    public String getAgenda() {
        return agenda.getNome() + " - " + agenda.getTelefone() + " - " + agenda.getEmail();
    }
}

public class Agenda {

    public String nome;
    public String telefone;
    public String email;

    public Agenda(String nome, String telefone, String email) {
        this.nome = nome;
        this.telefone = telefone;
        this.email = email;
    }

    public String getNome() {
        return nome;
    }

    public String getTelefone() {
        return telefone;
    }

    public String getEmail() {
        return email;
    }
}

```
<font size = "4"><b>Solução: extract method </b></font>

<p> &nbsp Foi feita extração do método criando agendaFormatada() na classe da agenda para formatação.</p>

```java
public class Agenda {

    public String nome;
    public String telefone;
    public String email;

    public Agenda(String nome, String telefone, String email) {
        this.nome = nome;
        this.telefone = telefone;
        this.email = email;
    }

    public String getNome() {
        return nome;
    }

    public String getTelefone() {
        return telefone;
    }

    public String getEmail() {
        return email;
    }

    public String agendaFormatada() {
        return  getNome() + " - " + getTelefone() + " - " + getEmail();
    }
}

public class Cliente {
    private Agenda agenda;

    public String getAgendaContatos() {
        return agenda.agendaFormatada();
    }
}
```

<font size = "4"><b> 3° problema: variável inútil </b></font>

```csharp
public void InformarQuantidade(int quantidade, double valor) {
  int Quantidade = quantidade;
  ValorTotalItem = valor * Quantidade;
}
```

<font size = "4"><b>Solução: apagar a variável</b></font>
<p>
    &nbsp Foi aplicada a refatação, pois foi declarada uma variável que é obsoleta no método.
</p>

```csharp
public void InformarQuantidade(int quantidade, double valor) {
  ValorTotalItem = valor * quantidade;
}
```

<font size = "4"><b>4° problema: comentário inútil </b></font>
<p>
    &nbsp Comentários desnecessários no código deve ser retirado, neste exemplo foi feito um comentário para dizer que a seção contia atributos.
</p>

```csharp
public class Serie 
{
    // Atributos
    private Genero Genero { get; set; }
    private string Titulo { get; set; }
    private string Descricao { get; set; }
    private int Ano { get; set; }
    private bool Excluido { get; set; }
}

```
<font size = "4"><b>Solução: retirar comentário</b></font>

```csharp
public class Serie 
{
    private Genero Genero { get; set; }
    private string Titulo { get; set; }
    private string Descricao { get; set; }
    private int Ano { get; set; }
    private bool Excluido { get; set; }
}
```

# **Débito Técnico**
<font size = "4"><b>1° problema: nome fora do padrão.</b></font>
<p>
&nbsp Nome fora do padrão na interface.
</p>

```csharp
namespace WebApiDesafioFinal.Contracts {
  public interface IGeralPersist {
    void Add < T > (T entity) where T: class;
    void Update < T > (T entity) where T: class;
    void Delete < T > (T entity) where T: class;
    Task < bool > SaveChangesAsync();
  }
}
```
<font size = "4"><b>Solução: renomeação da interface</b></font>
<p>
&nbsp Realizei a renomeação  do nome da interface IgeralPersist para IEntityPersist.
</p>   

```csharp
namespace WebApiDesafioFinal.Contracts {
  public interface IEntityPersist {
    void Add < T > (T entity) where T: class;
    void Update < T > (T entity) where T: class;
    void Delete < T > (T entity) where T: class;
    Task < bool > SaveChangesAsync();
  }
}
```
<font size = "4"><b>2° problema: atributos fora do contexto </b></font>
<p>
    Na classe escola havia também atributos referentes a aluno.
</p>

```csharp
public class Escola
{
    private string nome { get; set; }
    private string endereco { get; set; }
    private string cnpj { get; set; }
    private Date dataFundacao { get; set; }

    private string nomeAluno { get; set; }
    private string matricula { get; set; }
    private int classe { get; set; }
    private Date dataAniversario { get; set; }
    private string cpf { get; set; }
}

```
<font size = "4"><b>Solução: extração de classes</b></font>
<P>
&nbsp Foi criada uma nova classe aluno para receber esses atributos.
</P>

```csharp
public class Escola
{
    private string nome { get; set; }
    private string endereco { get; set; }
    private string cnpj { get; set; }
    private Date dataFundacao { get; set; }
    public List<Aluno> Alunos = new List<Aluno>();
}

public class Aluno
{
    private string nome { get; set; }
    private string matricula { get; set; }
    private string nomeEscola { get; set; }
    private int classe { get; set; }
    private Date dataAniversario { get; set; }
    private string cpf { get; set; }
}
```
<font size = "4"><b>3° problema: ausência de testes </b></font>

<p>
    Ausência de testes da classe BuscarProduto
</p>

```java
@Service
public class BuscarProduto implements BuscarProdutoService {
    @Autowired
    private ProdutoRepository repository;

    public BuscarProduto(ProdutoRepository repository) {
        this.repository = repository;
    }
    public Produto buscarProdutoId(long id) {
        return repository.findById(id).orElseThrow(
                () -> new IllegalArgumentException("Id not found" + id));
    }
    public List<Produto> buscarProdutos() {
        return (repository.findAll().isEmpty()) ? Collections.emptyList() : repository.findAll();
    }
}
```

<font size = "4"><b>Solução: foi aplicado os testes </b></font>

```java
public class BuscarProdutoTest {

    private static BuscarProdutoService buscarProdutoService;

    @BeforeAll
    public static void init() {
        buscarProdutoService = mock(BuscarProdutoService.class);
        Mockito.when(buscarProdutoService.buscarProdutoId(Mockito.anyInt())).thenReturn(ProdutoCONST.NULL);
        Mockito.when(buscarProdutoService.buscarProdutoId(10)).thenReturn(ProdutoCONST.GELADEIRA);
    }

    @Test
    public void testBuscarProdutoId() {
        Produto produto = buscarProdutoService.buscarProdutoId(10);
        assert produto != null;
        assert produto.getId() == 10;
        assert produto.getDescricao().equals("Geladeira");
        assert produto.getValor() == 1500.00;
        assert produto.getQuantidade() == 2000;
    }

    @Test
    public void testBuscarProdutoIdNull() {
        Produto produto = buscarProdutoService.buscarProdutoId(Mockito.anyInt());
        assert produto == null;
    }
}
```
















