Abstrair (mas em pontos estratégicos)

Um erro comum quando nós programadores iniciamos com orientação a objetos é a tentativa de projetar um software 100% “à prova de futuro”. Em outras palavras, não é sabido que determinado comportamento irá variar e já criamos interfaces e classes abstratas por toda parte.

Normalmente isso ocorre por inexperiência, quando programadores aplicam certos conceitos sem entendê-los totalmente. Neste caso, levam ao pé-da-letra “programar para interfaces” ou “devemos estar preparados para mudança” e criam diversas abstrações que nunca serão usadas.

QUAL O PROBLEMA?

A extração de interfaces pura e indiscriminadamente gera complexidade desnecessária (AKA “over-engineering” ou “over-design”). Esse tipo de bad smell acaba atrapalhando a entrega do software, pois leva tempo tanto para ser implementado como para ser posteriormente compreendido pelos demais programadores.

Lembre-se que há alguém esperando pelo software e devemos entregar o mais rápido possível, com o mínimo de esforço, sem comprometer a qualidade.

ENTÃO, QUANDO?

Podemos seguir algumas dicas para identificar pontos de extensão no software:

– Nas palavras do Uncle Bob, “leve o primeiro tiro“. Isso quer dizer: espere a primeira mudança acontecer e só depois implemente as devidas abstrações para proteger o código de outras mudanças do mesmo tipo. Ou seja, não é preciso implementar de início o padrão Strategy para cálculo de impostos se o que você tem de antemão é que só existe uma forma de cálculo.

– Pratique TDD. Escrevendo testes antes, você acaba identificando abstrações que permitem que o software seja testável. De quebra, o software acaba protegido contra outras mudanças.

– Obtenha feedback do cliente o quanto antes. Entregando software aos poucos, iteração após iteração, e obtendo feedback do cliente, você acaba descobrindo quais são as mudanças mais prováveis de acontecer o mais rápido possível, podendo, então, refatorar o código para suportar as devidas abstrações. Ou seja, conversar com o cliente é fundamental!

– Procure ajuda com outros programadores que já tenham trabalhado no software e já o viram evoluir. Com certeza, eles saberão dizer quais pontos sofreram mais mudanças (mas não deixe de lado o cliente!!).

PORTANTO…

Devemos, com bom senso, identificar abstrações para partes do software com maior probabilidade de mudança. Procurar e implementar abstrações por todo o software é algo custoso tanto no processo de desenvolvimento como em manutenção.

Era isso.

Comentem, critiquem, sugiram!

Até a próxima!

Anúncios

14 comentários em “Abstrair (mas em pontos estratégicos)

  1. Acho que as vezes o pepessoal perde o foco. Na minha visão, o foco é o uso do cliente para resolver aquele problema. Se o problema do cliente foi atendido, entao o meio para atingir isto está suficiente. Quando lançaram o Win Vista, o XP tinha tanto erro e gambiarra, que precisaram abandonar a programação antiga e fazer uma nova. O resultado foi o sucesso. De repente é mais viavel pensar em solucionar o problema do cliente e deixar pra “melhorar a programação” quando este for o problema.

    Agora não leve isso pra sua vida, não espere “a bomba estourar” pra resolver aquele problema com seu amigo ou familiar. Maquinas não se magoam, pessoas sim 🙂

  2. Concordo totalmente, Robson. Claro que nossa ideia é deixar o software sempre o mais preparado possível para as mudanças, mas como você diz, isso nem sempre vale a pena de início, pois nem sempre será necessário.
    Abracos!

  3. Boa tarde, bom dia, boa noite, acompanho o seu blog já faz um tempo e gosto muito dos seus posts, alguns deles são muito úteis e faz agente pensar naquilo que faz, gostaria de pedir alguma direção, pois confesso que estou confuso;

    Lembro-me desse post aqui -> https://robsoncastilho.wordpress.com/2012/07/22/se-nao-esta-quebrado-nao-conserte-certeza/

    Será que você poderia explicar a relação “Se não está quebrado, não conserte. Certeza?”, com “Abstrair (mas em pontos estratégicos)”?

    Avaliando a superfície esses dois posts parecem “opostos”, afinal devemos ou não mudar algo que já funciona?

    Desde já, agradeço.

    1. Olá, João!

      Primeiramente, obrigado pelo feedback. É muito legal saber o que as pessoas estão achando do blog. 🙂

      Vamos lá:
      No primeiro post “Se está quebrado…” o contexto é refatoração. Nele o objetivo é reforçar a importância de zelar pelo código, de estar cuidando mesmo depois de pronto, senão o software acaba se degradando muito rápido. Já ouviu falar na teoria das janelas quebradas?
      (A mudança aqui, portanto, é refactoring, ou seja, mudança na estrutura interna do código sem mudar o seu propósito.)

      No segundo “Abstrair..” o objetivo é alertar sobre over-design, ou seja, não criar de início algo muito complexo, tentando criar algo 100% extensível – coisa que não existe. (A mudança aqui está mais ligada à alterações de requisitos, ou tentar prevê-las sem que existam.)

      Portanto, respondendo sua pergunta, mudança (refactoring) deve ser algo rotineiro. Deve fazer parte do dia-a-dia do programador aplicar técnicas que melhorem aquele pedacinho meio feio de código. Fazendo isso num passo constante você não precisará de grandes refatorações, estará sempre fazendo mudanças pequenas.
      Mudanças também são bem-vindas quando os devs entendem melhor algum conceito de negócio. Então eles vão no código e fazem as alterações para refletir esse novo entendimento e deixar o software mais condizente com o negócio.

      E é claro, existem também as mudanças por alterações de requisitos (sim, o cliente VAI pedir alterações, não adianta chorar). Devemos encara-las de frente, e aqui, entram algumas dicas do segundo post, que é identificar lugares onde estão tendo mais alterações e torna-los mais extensíveis, para que o sofrimento seja menor (ou nenhum) da próxima vez.

      No meio disso tudo, entra “bom senso”, “experiência” e “alinhamento com o cliente”. É preciso saber quanto é “bom o bastante” e praticar o desapego, afinal nem sempre vem fácil uma solução genial para aquele bloco “estranho” de código.

      Infelizmente, não existe uma fórmula mágica para definir “bom o bastante”. Quanto mais experiência for adquirindo, melhor você vai ficando para identificar este ponto.

      Ufa..acho que escrevi demais e não sei se consegui ser claro o bastante hehehe.

      Mas estamos aí. É só entrar em contato.

      []s

      1. Muito obrigado. Acho que entendi… Minha dúvida era exatamente essa, estava me perdendo no contexto em que se encontravam os dois posts,
        Confesso que me debato muito com essa ideia de “mudanças são bem vindas”, talvez por falta de conhecimento.

        De qualquer forma, acho que preciso estudar Refactoring, talvez isso me ajude a entender, em qual tipo de código que mudanças são bem vindas, ou então o que fazer para que meu “código antigo” se transforme em um “código novo” onde mudanças são bem vindas.

        Fiquei meio chocado de inicio pois esse post é muito fora da minha realidade num sentido de que aqui, não há abstração demais, mas sim de menos…

        Mas tá tudo OK! Não podemos é perder o foco por conta disso e sair abstraindo tudo.

        Mais uma vez obrigado!

      2. De nada, João.

        Recomendo o clássico “Refactoring” do Martin Fowler. O livro é um catálogo com dezenas de técnicas de refactoring.
        Porém, antes da técnica, é preciso entender seu propósito e ter vontade de aplicá-la..é preciso QUERER.
        É o que tenho tentado mostrar com esses posts.

        Estamos aí.
        []s!

  4. Just in time Implementation. Antes eu tentava resolver os problemas futuros já deixando o código “preparado” para alterações e, na maioria das vezes, essa alteração não acontecia, seja porque faz parte de outro negócio parecido ou o cliente simplesmente não precisava disso.

    Usando TDD eu consegui avançar muito nesse contexto criando apenas o que é necessário para os testes passarem, ao invés de sair codificando loucuras. Abstraio a medida que novas funcionalidades semelhantes aparecem.

    Ainda é muito difícil ter 100% de certeza de quando um código precisa ser extensível ou apenas uma funcionalidade única.

    Ótimo post. Veio confirmar algumas das coisas que venho questionando na minha forma de desenvolver software.

    1. Valeu, Higor!
      Exatamente isso!
      Temos que focar no simples (e fazer o simples é dificil), ir ‘percebendo’ o software e tendo a boa vontade/coragem de evoluir o design enquanto vamos aprendendo mais sobre ele.
      []s

  5. Muito bom artigo, uma outra frase que o unclebob fala sobre esse needless complexity é aquela “Fool me once, shame on you; fool me twice, shame on me”. Lembrando a gente que somente devemos aplicar algumas práticas (design patterns, abstrações) quando tivermos fortes indícios da necessidade.

    1. Muito bom comentário, Guilherme. Eu estava para abstrair por abstrair. Hahahaha. Mas essa frase me fez repensar a necessidade.

Participe! Vamos trocar uma ideia sobre desenvolvimento de software!

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s