Refatoração de Código: Substituir Lógica Condicional Por Strategy

Investir em Você é Barra de Ouro a R$ 2,00. Cadastre-se e receba grátis conteúdos Android sem precedentes! Você receberá um email de confirmação. Somente depois de confirma-lo é que eu poderei lhe enviar os conteúdos semanais exclusivos. Os artigos em PDF são entregues somente para os inscritos na lista.

Email inválido.
Blog /Android /Refatoração de Código: Substituir Lógica Condicional Por Strategy

Refatoração de Código: Substituir Lógica Condicional Por Strategy

Vinícius Thiengo
(3194)
Go-ahead
"Sempre sonhe e mire mais alto do que você sabe que você pode fazer. Não se preocupe em ser melhor do que seus contemporâneos e antecessores. Tente ser melhor do que você mesmo."
William Faulkner
Kotlin Android
Capa do livro Mapas Android de Alta Qualidade - Masterização Android
TítuloMapas Android de Alta Qualidade - Masterização Android
CategoriasAndroid, Kotlin, Masterização, Especialização
AutorVinícius Thiengo
Edição
Ano2020
Capítulos11
Páginas166
Acessar Livro
Quer aprender a programar para Android? Acesse abaixo o curso gratuito no Blog.
Conteúdo Exclusivo
Investir em Você é Barra de Ouro a R$ 2,00. Cadastre-se e receba gratuitamente conteúdos Android sem precedentes!
Email inválido

Tudo bem?

Dando continuidade a série Refatoração de Código, para termos um código mais limpo...

... neste artigo vamos falar da aplicação do padrão Strategy por meio do método de refatoração Substituir Lógica Condicional por Strategy.

Antes de prosseguir lembro que os artigos dessa série são úteis para developers de qualquer linguagem de programação, especificamente para aqueles que programam no paradigma orientado a objetos.

Note que para o entendimento do método abaixo ser possível, é essencial que você conheça antes o padrão Strategy.

Caso ainda não o conheça, acesse o artigo que tem aqui no Blog sobre esse design pattern:

Antes de prosseguir, não esqueça de se inscrever na 📫 lista de e-mails do Blog para receber em primeira mão todos os conteúdos exclusivos sobre desenvolvimento e codificação limpa.

A seguir os tópicos que estaremos abordando em artigo:

Motivação

Devido a velocidade necessária para terminarmos nossos projetos pode ser inteligente passar por alguns pontos sem a aplicação de padrões que minimizariam a dor de cabeça quando a volta ao código fosse necessária.

Não somente diminuiriam a dor como também diminuiriam a repetição de código e colocaria mais intenção em nossas lógicas de negócio dispensando comentários em certos trechos.

Em casos onde há condicionais complexas para a execução de scripts específicos, muitas vezes de acordo com o tipo de uma variável de instância da classe.

Nesse contexto podemos aplicar uma refatoração onde colocaríamos as lógicas de execução desses condicionais em métodos específicos dentro da própria classe onde se encontra o método com condicionais complexos.

Porém essa abordagem pode sobrecarregar nossa classe colocando uma série de métodos pequenos e que poderiam ser reutilizados em outras classes do domínio do problema.

Uma outra abordagem é a utilização de polimorfismo, onde utilizaríamos subclasses para trabalhar os métodos específicos.

A problemática aqui é quando somente poucos métodos, muitas vezes somente um, devem ter comportamento especifico.

Dessa forma estamos sobrecarregando o domínio do problema de nosso projeto além de termos de modificar todo o código que trabalhava diretamente com a classe que vai se tornar superclasse.

A solução que nos resta é a utilização do padrão Strategy que permite que criemos classes especificas para cada trecho de código que está entre as condicionais complexas.

Eliminando assim as condicionais e colocando intenção no código facilitando a leitura dele, além de permitir a reutilização desse código por outras classes do projeto e não somente a classe de origem do problema.

Código de exemplo

No exemplo a seguir vamos utilizar trechos de um código bancário, mais especificamente o trecho necessário para compreender a refatoração proposta nesse artigo.

A classe Emprestimo do código a seguir é a classe que será refatorada.

Nela há um método onde é definido o cálculo de empréstimo bancário a ser utilizado.

O resultado desse cálculo é retornado depois de passar por alguns testes complexos com vários condicionais.

Os cálculos são específicos para empréstimos do tipo: tempo limitado, recorrente e linha sugerida.

Segue trecho do código do método capital() na classe Emprestimo:

public class Emprestimo {
...

public double capital(){

if( expiracao == null && maturidade != null ){ /* TEMPO LIMITE */
return comprometimento * duracao() * fatorRisco();
}
else if( expiracao != null && maturidade == null ){

if( getPorcentagemNaoUtilizada() != 1.0 ){ /* LINHA SUGERIDA */
return comprometimento * getPorcentagemNaoUtilizada() * duracao() * fatorRisco();
}
else{ /* RECORRENTE */
return(
(proeminenteQuantidadeRisco() * duracao() * fatorRisco())
+
(quantidadeRiscoNaoUtilizado() * duracao() * fatorRiscoNaoUtilizado())
);
}
}

return 0.0;
}
...
}

 

Note que no código acima não é trivial o entendimento de qual condicional é relativa a qual método de empréstimo, quase que impossível saber o tipo de empréstimo se o código não for refatorado ou comentado.

É importante que você não foque no cálculo e nas variáveis e métodos sendo utilizados.

Muito do código de Emprestimo vai ser ocultado.

O que tem de entender é como colocar o padrão por meio do método de refatoração proposto, movendo a complexidade das condicionais de escolha de cálculo para classes Strategy.

Abaixo o construtor e os métodos de criação de instância da classe Emprestimo.

Os métodos de criação são úteis para que o código cliente saiba quando criar uma instância de Emprestimo com comportamento de:

  • Tempo limite;
  • Recorrente;
  • ou Linha sugerida.

Segue código:

public class Emprestimo {

private Emprestimo(
double comprometimento,
double proeminente,
Date inicio,
Date expiracao,
Date maturidade,
int classificacaoRisco ){
...
}

public static Emprestimo criarTempoLimitado(...){
...
}

public static Emprestimo criarRecorrente(...){
...
}

public static Emprestimo criarLinhaSugerida(...){
...
}
...
}

 

Os métodos de criação apresentados acima são conseguidos por meio do método de refatoração Substituir Construtores Por Métodos de Criação.

Abaixo estão os métodos auxiliares ao método capital():

public class Emprestimo {
...

private double proeminenteQuantidadeRisco(){
return proeminente;
}

private double quantidadeRiscoNaoUtilizado(){
return comprometimento - proeminente;
}

public double duracao(){

if( expiracao == null && maturidade != null ){
return pesoDuracaoMedia();
}
else if( expiracao != null && maturidade == null ){
return anosPara( expiracao );
}

return 0.0;
}

private double pesoDuracaoMedia(){

double duracao = 0.0;
double pesoMedio = 0.0;
double somaPagamentos = 0.0;
Iterator pagamentosEmprestimo = pagamentos.iterator();

while( pagamentosEmprestimo.hasNext() ){

Pagamento pagamento = (Pagamento) pagamentosEmprestimo.next();
somaPagamentos += pagamento.quantidade();
pesoMedio += anosPara( pagamento.data() ) * pagamento.quantidade();
}

if( comprometimento != 0.0 ){
duracao = pesoMedio / somaPagamentos;
}

return duracao;
}

private double anosPara( Date dataFinal ){

Date dataInicio = hoje == null ? inicio : hoje;

return ((dataFinal.getTime() - dataInicio.getTime()) / MILISSEGUNDOS_POR_DIA) / DIAS_POR_ANO;
}

private double fatorRisco(){

return FatorRisco
.getFatores()
.paraClassificacao( fatorRisco );
}

private double fatorRiscoNaoUtilizado(){

return FatorRiscoNaoUtilizado
.getFatores()
.paraClassificacao( fatorRisco );
}
...
}

 

Com o código de exemplo apresentado podemos seguir para a refatoração.

Mecânica

O primeiro passo é criar uma classe representando a ConcreteStrategy do padrão, onde o nome dela será de acordo com o comportamento que o padrão Strategy terá de encapsular por meio de classes de estratégia.

Em nosso caso será CapitalStrategy, pois é o método capital() que contém a complexidade que queremos remover.

O Strategy no final do nome da classe é opcional, mas indicado para ser fácil a identificação do tipo de padrão sendo implementado, além de passar a característica de linguagem universal, no código, ganho comum na utilização de padrões de projeto.

Segue algoritmo da nova classe:

public class CapitalStrategy {
// TODO
}

 

Nosso segundo passo é mover o método capital() de Emprestimo para CapitalStrategy.

Junto devemos mover todos os métodos e atributos que são utilizados somente no método capital().

Logo nossa nova classe segue como:

public class CapitalStrategy {
...

/* COPIADO DE EMPRESTIMO */
public double capital(){

if( expiracao == null && maturidade != null ){ /* TEMPO LIMITE */
return comprometimento * duracao() * fatorRisco();
}
else if( expiracao != null && maturidade == null ){

if( getPorcentagemNaoUtilizada() != 1.0 ){ /* LINHA SUGERIDA */
return comprometimento * getPorcentagemNaoUtilizada() * duracao() * fatorRisco();
}
else{ /* RECORRENTE */
return(
(proeminenteQuantidadeRisco() * duracao() * fatorRisco())
+
(quantidadeRiscoNaoUtilizado() * duracao() * fatorRiscoNaoUtilizado())
);
}
}

return 0.0;
}

/* MOVIDO DE EMPRESTIMO */
private double fatorRisco(){

return FatorRisco
.getFatores()
.paraClassificacao( fatorRisco );
}

/* MOVIDO DE EMPRESTIMO */
private double fatorRiscoNaoUtilizado(){

return FatorRiscoNaoUtilizado
.getFatores()
.paraClassificacao( fatorRisco );
}
}

 

Mesmo que não tenha aqui todo o código da classe Emprestimo, pode assumir seguramente que esses são os métodos que somente são utilizados dentro do método capital().

As variáveis de instancia deles também ou são somente utilizados neles ou no método capital().

Os outros métodos não podem ser movidos para CapitalStrategy pois dependem de entidades que não são somente utilizadas diretamente ou indiretamente pelo método capital().

Note que a classe Emprestimo ainda tem o método capital(), porém agora esse método delega o cálculo para uma instância de CapitalStrategy.

Antes de mostrar como ficou o método capital() em Emprestimo, devemos definir como acessar os métodos e atributos de Emprestimo que não foram passíveis de mudança de classe.

Temos mais de uma estratégia, são elas:

1ª ➙ Passar a instância de Emprestimo como parâmetro e então alterar a classe Emprestimo a ponto de ter de modificar a visibilidade de métodos que antes somente podiam ser acessados dentro da classe (os private) e também adicionar métodos getters para encapsular o acesso a atributos private.

O ponto negativo aqui é a modificação da classe Emprestimo.

2ª ➙ Passar todas as entidades necessárias em CapitalStrategy por meio do construtor dele ou por métodos de atribuição, setters.

O ponto negativo aqui é quando há muitos dados a serem passados como argumento além de termos de mover ainda mais código de Emprestimo para CapitalStrategy devido aos métodos que ainda estão em Emprestimo e não são de uso exclusivo de capital().

3ª ➙ Utilizar um objeto de uma classe extra somente para conter os valores dos atributos de Emprestimo que seriam necessários em CapitalStrategy.

O ponto negativo é ter de criar uma nova classe no domínio do problema além de não poder utilizar os métodos de Emprestimo sem movê-los para a classe CapitalStrategy.

Devido aos métodos que não são de uso exclusivo do método capital() vamos ficar com a primeira opção, passar uma instância de Emprestimo como referência em CapitalStrategy.

Logo nossa classe estratégia de capital agora tem a seguinte estrutura:

public class CapitalStrategy {
...
public double capital( Emprestimo emp ){

if( emp.getExpiracao() == null && emp.getMaturidade() != null ){ /* TEMPO LIMITE */

return emp.getComprometimento() * emp.duracao() * fatorRisco( emp );
}
else if( emp.getExpiracao() != null && emp.getMaturidade() == null ){

if( emp.getPorcentagemNaoUtilizada() != 1.0 ){ /* LINHA SUGERIDA */

return emp.getComprometimento() * emp.getPorcentagemNaoUtilizada() * emp.duracao() * fatorRisco( emp );
}
else{ /* RECORRENTE */
return(
(emp.proeminenteQuantidadeRisco() * emp.duracao() * fatorRisco( emp ))
+
(emp.quantidadeRiscoNaoUtilizado() * emp.duracao() * fatorRiscoNaoUtilizado( emp ))
);
}
}

return 0.0;
}

private double fatorRisco( Emprestimo emp ){

return FatorRisco
.getFatores()
.paraClassificacao( emp.getClassificacaoRisco() );
}

private double fatorRiscoNaoUtilizado( Emprestimo emp ){

return FatorRiscoNaoUtilizado
.getFatores()
.paraClassificacao( emp.getClassificacaoRisco() );
}
}

 

Lembrando que como passamos uma instância de Emprestimo para o método capital() devemos modificar (ou adicionar) algumas entidades em Emprestimo.

Logo a classe agora tem a seguinte estrutura:

public class Emprestimo {
...
public double capital(){
return new CapitalStrategy().capital( this );
}

public Date getExpiracao(){
return expiracao;
}

public Date getMaturidade(){
return maturidade;
}

public double getComprometimento(){
return comprometimento;
}

public double getPorcentagemNaoUtilizada(){
return porcentagemNaoUtilizada;
}

public double proeminenteQuantidadeRisco(){
return proeminente;
}

public double quantidadeRiscoNaoUtilizado(){
return comprometimento - proeminente;
}
...
}

 

Os tipos de acesso são todos public e o método capital() somente delega o cálculo para uma instância CapitalStrategy.

Note que ainda temos métodos em Emprestimo que são utilizados somente para o cálculo de capital().

Porém esses utilizam atributos de Emprestimo que não são exclusivos de uso do método capital() (note que não estou falando dos métodos do código anterior e sim de métodos como duracao(), por exemplo).

Como agora temos uma referência a Emprestimo dentro de CapitalStrategy, podemos mover esses métodos específicos para os cálculos de capital() para CapitalStrategy e então acessar os atributos de Emprestimo por meio dessa referência passada como parâmetro.

Em nossa classe CapitalStrategy vamos adicionar os métodos duracao(), pesoDuracaoMedia() e anosPara().

Além das constantes utilizadas em anosPara() conforme código abaixo:

public class CapitalStrategy {

private static final int MILISSEGUNDOS_POR_DIA = 86400000;
private static final int DIAS_POR_ANO = 365;

...
public double duracao( Emprestimo emp ){

if( emp.getExpiracao() == null && emp.getMaturidade() != null ){ /* TEMPO LIMITE */

return pesoDuracaoMedia( emp );
}
else if( emp.getExpiracao() != null && emp.getMaturidade() == null ){ /* RECORRENTE E LINHA SUGERIDA */

return anosPara( emp.getExpiracao(), emp );
}
return 0.0;
}

private double pesoDuracaoMedia( Emprestimo emp ){

double duracao = 0.0;
double pesoMedio = 0.0;
double somaPagamentos = 0.0;
Iterator pagamentosEmprestimo = emp.getPagamentos().iterator();

while( pagamentosEmprestimo.hasNext() ){

Pagamento pagamento = (Pagamento) pagamentosEmprestimo.next();
somaPagamentos += pagamento.quantidade();
pesoMedio += anosPara( pagamento.data(), emp ) * pagamento.quantidade();
}

if( emp.getComprometimento() != 0.0 ){
duracao = pesoMedio / somaPagamentos;
}
return duracao;
}

private double anosPara( Date dataFinal, Emprestimo emp ){

Date dataInicio = (emp.getHoje() == null ? emp.getInicio() : emp.getHoje());

return ((dataFinal.getTime() - dataInicio.getTime()) / MILISSEGUNDOS_POR_DIA) / DIAS_POR_ANO;
}
}

 

Podemos modificar nossa classe CapitalStrategy para utilizar o método duracao() local.

Se voltarmos ao código de Emprestimo, no início do exemplo é possível notar que o método duracao() apesar de ser utilizado somente pelo método capital() ele tem acesso public.

Logo não podemos movê-lo de Emprestimo para CapitalStrategy e sim copiá-lo.

Pois Emprestimo ainda terá um método de acesso público que permitirá que o código cliente acesse de forma indireta o método duracao() de CapitalStrategy.

Depois dessa refatoração nossa classe Emprestimo terá código duplicado em capital() e em duracao(), pois ambos utilizam o trecho new CapitalStrategy().

Para remover essa duplicação vamos instanciar nosso CapitalStrategy no construtor de Emprestimo e atribuir essa instância a uma variável nomeada capitalStrategy.

Conforme código a seguir:

public class Emprestimo {

private CapitalStrategy capitalStrategy;

private Emprestimo(
double comprometimento,
double proeminente,
Date inicio,
Date expiracao,
Date maturidade,
int classificacaoRisco ){

capitalStrategy = new CapitalStrategy();
...
}

public double capital(){
return capitalStrategy.capital( this );
}

public double duracao(){
return capitalStrategy.duracao( this );
}
...
}

 

Nosso terceiro passo é fazer com que a variável capitalStrategy em Emprestimo receba dados via parâmetro.

Esse passo é importante para que no próximo e último passo seja possível criar e utilizar classes especificas de Strategy e a consequente eliminação da lógica condicional que ainda existe nos métodos capital() e duracao().

Segue classe Emprestimo com os criadores de instâncias definindo o valor de capitalStrategy via parâmetro do construtor principal:

public class Emprestimo {

private CapitalStrategy capitalStrategy;

private Emprestimo(
double comprometimento,
double proeminente,
Date inicio,
Date expiracao,
Date maturidade,
int classificacaoRisco,
CapitalStrategy capitalStrategy ){

this.capitalStrategy = capitalStrategy;
...
}

public static Emprestimo criarTempoLimitado(
double comprometimento,
Date inicio,
Date maturidade,
int classificacaoRisco ){

return new Emprestimo(
comprometimento,
0,
inicio,
null,
maturidade,
classificacaoRisco,
new CapitalStrategy() );
}

public static Emprestimo criarRecorrente(
double comprometimento,
Date inicio,
Date expiracao,
int classificacaoRisco ){

return new Emprestimo(
comprometimento,
0,
inicio,
expiracao,
null,
classificacaoRisco,
new CapitalStrategy() );
}

public static Emprestimo criarLinhaSugerida(
double comprometimento,
Date inicio,
Date expiracao,
int classificacaoRisco ){

if( classificacaoRisco > 3 ){
return null;
}

Emprestimo linhaSugerida = new Emprestimo(
comprometimento,
0,
inicio,
expiracao,
null,
classificacaoRisco,
new CapitalStrategy() );

linhaSugerida.setPorcentagemNaoUtilizada( 0.1 );

return linhaSugerida;
}
...
}

 

Nosso quarto e último passo é criar as classes que vão herdar de CapitalStrategy e consequentemente passarão a ser as ConcreteStrategy que representarão os cálculos dos condicionais de capital().

Logo depois algumas modificações serão feitas em CapitalStrategy e Emprestimo.

Segue classe CapitalStrategyTempoLimitado:

public class CapitalStrategyTempoLimitado extends CapitalStrategy {

public double capital( Emprestimo emp ){
return emp.getComprometimento() * duracao( emp ) * fatorRisco( emp );
}

public double duracao( Emprestimo emp ){
return pesoDuracaoMedia( emp );
}

private double pesoDuracaoMedia( Emprestimo emp ){

double duracao = 0.0;
double pesoMedio = 0.0;
double somaPagamentos = 0.0;
Iterator pagamentosEmprestimo = emp.getPagamentos().iterator();

while( pagamentosEmprestimo.hasNext() ){

Pagamento pagamento = (Pagamento) pagamentosEmprestimo.next();
somaPagamentos += pagamento.quantidade();
pesoMedio += anosPara( pagamento.data(), emp ) * pagamento.quantidade();
}

if( emp.getComprometimento() != 0.0 ){
duracao = pesoMedio / somaPagamentos;
}

return duracao;
}
}

 

Agora a classe CapitalStrategyLinhaSugerida:

public class CapitalStrategyLinhaSugerida extends CapitalStrategy {

public double capital( Emprestimo emp ){

return(
emp.getComprometimento() *
emp.getPorcentagemNaoUtilizada() *
duracao( emp ) *
fatorRisco( emp )
);
}
}

 

E então a classe CapitalStrategyRecorrente:

public class CapitalStrategyRecorrente extends CapitalStrategy {

public double capital( Emprestimo emp ){

return(
(emp.proeminenteQuantidadeRisco() * duracao( emp ) * fatorRisco( emp ))
+
(emp.quantidadeRiscoNaoUtilizado() * duracao( emp ) * fatorRiscoNaoUtilizado( emp ))
);
}
}

 

Agora nossa classe CapitalStartegy passa a ser a entidade Strategy apresentada no diagrama e modelo desse padrão.

Podemos então realizar algumas mudanças.

Ela passa a ser abstrata e alguns métodos agora com visibilidade protected, além da remoção de código de alguns desses métodos.

Segue nova configuração da classe:

public abstract class CapitalStrategy {

private static final int MILISSEGUNDOS_POR_DIA = 86400000;
private static final int DIAS_POR_ANO = 365;

public abstract double capital( Emprestimo emp );

protected double fatorRisco( Emprestimo emp ){

return FatorRisco
.getFatores()
.paraClassificacao( emp.getClassificacaoRisco() );
}

protected double fatorRiscoNaoUtilizado( Emprestimo emp ){

return FatorRiscoNaoUtilizado
.getFatores()
.paraClassificacao( emp.getClassificacaoRisco() );
}

public double duracao( Emprestimo emp ){
return anosPara( emp.getExpiracao(), emp );
}

protected double anosPara( Date dataFinal, Emprestimo emp ){

Date dataInicio = emp.getHoje() == null ? emp.getInicio() : emp.getHoje();

return ((dataFinal.getTime() - dataInicio.getTime()) / MILISSEGUNDOS_POR_DIA) / DIAS_POR_ANO;
}
}

 

Note que o método pesoDuracaoMedia() é necessário somente para CapitalStrategyTempoLimitado, logo removemos ele de CapitalStrategy e colocamos apenas na classe de referente a tempo limitado.

Agora devemos modificar os métodos de criação em Emprestimo para trabalhar com classes ConcreteStrategy especificas.

Segue:

public class Emprestimo {

private CapitalStrategy capitalStrategy;

private Emprestimo(
double comprometimento,
double proeminente,
Date inicio,
Date expiracao,
Date maturidade,
int classificacaoRisco,
CapitalStrategy capitalStrategy ){

this.capitalStrategy = capitalStrategy;
...
}

public static Emprestimo criarTempoLimitado(
double comprometimento,
Date inicio,
Date maturidade,
int classificacaoRisco ){

return new Emprestimo(
comprometimento,
0,
inicio,
null,
maturidade,
classificacaoRisco,
new CapitalStrategyTempoLimitado() );
}

public static Emprestimo criarRecorrente(
double comprometimento,
Date inicio,
Date expiracao,
int classificacaoRisco ){

return new Emprestimo(
comprometimento,
0,
inicio,
expiracao,
null,
classificacaoRisco,
new CapitalStrategyRecorrente() );
}

public static Emprestimo criarLinhaSugerida(
double comprometimento,
Date inicio,
Date expiracao,
int classificacaoRisco ){

if( classificacaoRisco > 3 ){
return null;
}

Emprestimo linhaSugerida = new Emprestimo(
comprometimento,
0,
inicio,
expiracao,
null,
classificacaoRisco,
new CapitalStrategyLinhaSugerida() );

linhaSugerida.setPorcentagemNaoUtilizada( 0.1 );

return linhaSugerida;
}
...
}

 

Com isso concluímos a implementação do padrão Strategy por meio do método de refatoração Substituir Lógica Condicional por Strategy.

Agora os cálculos de capital() que incluem os métodos capital() e duracao() são realizados por meio de classes de estratégia (ou ConcreteStrategy) e sem lógica condicional complexa para escolha de algoritmo.

Conclusão

O padrão Strategy alivia em muito o código do projeto quando o trabalho com herança ou com Interface nas classes de domínio do problema não ajudam como esperado.

Assim conseguimos além de manter o código mais dinâmico devido a composição, a possibilidade de reuso de código ainda mais intensificada.

Pois os comportamentos que se tornaram classes de estratégia são fracamente acoplados com os códigos clientes.

Porém fique atento que caso tenha vários métodos com condicionais complexas, ao invés de criar uma nova família de classes Strategy estude a possibilidade de utilizar polimorfismo por meio de herança.

Caso contrário a sobrecarga de classes pode começar a vir devido a implementação do padrão Strategy em demasia.

Então é isso.

Por fim, não deixe de se inscrever na 📩 lista de e-mails do Blog para receber os conteúdos de desenvolvimento e codificação limpa exclusivos, em primeira mão e também...

... na versão em PDF (versão liberada somente para os inscritos da lista de e-mails).

Abraço.

Outros artigos da série

Abaixo listo os artigos já liberados dos métodos de refatoração desta série do Blog sobre "Codificação Limpa":

Fontes

Refatoração para Padrões

Use a Cabeça! Padrões de Projetos

Investir em Você é Barra de Ouro a R$ 2,00. Cadastre-se e receba grátis conteúdos Android sem precedentes!
Email inválido

Relacionado

Código Limpo - Habilidades Práticas do Agile SoftwareCódigo Limpo - Habilidades Práticas do Agile SoftwareLivros
Padrões de Implementação - Um Catálogo de Padrões Indispensável Para o Dia a Dia do ProgramadorPadrões de Implementação - Um Catálogo de Padrões Indispensável Para o Dia a Dia do ProgramadorLivros
Utilizando BottomSheet Material Design no AndroidUtilizando BottomSheet Material Design no AndroidAndroid
Persistência Com Firebase Android - Parte 1Persistência Com Firebase Android - Parte 1Android

Compartilhar

Comentários Facebook

Comentários Blog

Para código / script, coloque entre [code] e [/code] para receber marcação especifica.
Forneça seu nome válido.
Forneça seu email válido.
Forneça o comentário.
Enviando, aguarde...