## 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>
  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>
  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>
  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>   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>
  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>
  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>
  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>
  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>
  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;
}
}
```