[LIVRO] The Pragmatic Programmer - Capítulos 5 e 6
Dando sequência aos posts sobre o livro "The Pragmatic Programmer: from journeyman to master” (Andrew Hunt e David Thomas) ou em português “O Programador Pragmático: de Aprendiz a Mestre”, onde estou publicando minhas anotações do livro aqui no TabNews para compartilhar o conhecimento de forma mútua.
Link dos posts anteriores:
P.S: Ressalto que eu li a 1a Edição de 1999 em inglês. São minhas anotações pessoais, com tradução de termos e ideias próprias, logo poderão ter informações que na tradução em português oficial estejam diferentes (ou até erradas). A ideia não é ser, necessariamente, um resumo/resenha do livro, mas de pontuar algumas ideias que eu entendi serem interessantes a compartilhar.
P.S2: Nesse post, o meu intuito era usar algumas imagens, para facilitar a compreensão de alguns conceitos, mas não consegui de nenhum jeito publicar imagens aqui. Desculpem-me por isso.
Capítulo 5 - Bend, or Break (Dobre ou quebre)
A vida não permanece a mesma, da mesma forma o código também não é o mesmo. Devemos ser capazes de poder tomar decisões reversíveis diante de um mundo tão incerteiro.
- Acoplamentos e desacoplamentos ⇒ Dependências em módulos de código
- Escrever pouco código ⇒ Mudanças de código deixam em aberto introduzir novos bugs
Decoupling and the Law of Demeter (Desacoplamento e a Lei de Deméter)
- Shy code ⇒ Não se revelar a outros e não interagir com muitas coisas
- Minimize o acoplamento ⇒ Tenha cuidado com a quantidade de módulos que você está se acoplando
- Terceirize as ações ⇒ No seu lado só faça aquilo que realmente precisar
- A Lei de Demeter para funções
- Seu módulo deve delegar e gerenciar qualquer e todos subcontratantes diretamente, sem envolver seus clientes no seu módulo
- Você vai escrever uma grande escala de métodos que irão simplesmente repassar a requisição para uma delegação.
Metaprogramming (Metaprogramação)
- Detalhes bagunçam nosso código ⇒ Fora com os detalhes!
- Nosso sistema deve ser altamente configurável ⇒ Configure, não integre
- Use metadata para descrever opções de configurações para uma aplicação.
- Metadata: dado sobre dado ⇒ Você deve ser capaz de acessar e manipular essa informação da mesma forma que você manipularia qualquer outro dado da base de dados
- Coloque abstrações no código, detalhes no metadata
- Drivar a aplicação via metadata o quanto for possível
- Programas dinâmicos e adaptáveis
- Lógica de Negócio
- Não escreva Dodo-Code ⇒ Dodos não adaptaram na presença de humanos e rapidamente foram extintos
Temporal Coupling (Acoplamentos temporais)
- Sobre tempo ⇒ Muitas vezes ignorado nas arquiteturas de software
- Método A deve ser sempre chamado antes do B
- Só pode executar um report de cada vez
- Deve esperar a tela recarregar depois que um botão for clicado
- Etc
- Workflow ⇒ O que pode ocorrer ao mesmo tempo, e o que deve seguir uma ordem específica.
- Analise workflow para aplicar concorrência
- Há coisas que podem acontecer em paralelo. Há outras que devem estar em alguma sequência.
- Design Using Services
- Design for Concurrency ⇒ Objetos precisam estar em um estado válido quando chamados, e eles podem ser chamados na maior parte do tempo. Devemos garantir que o objeto esteja em um estado válido na maior parte do tempo em qualquer tempo.
- Cleaner Interfaces ⇒ Projete sempre interfaces claras para uso, sem implementação desnecessária para terceiros
It’s Just a View (É apenas um view)
-
Quando se separa um programa em diferentes módulos baseados em responsabilidades, você terá um novo problema ⇒ Como eles irão se comunicar?
-
Eventos ⇒ Algo interessante aconteceu
- Usar eventos minimiza acoplamentos entre objetos que não deveriam sequer se comunicar.
- Cada objeto é responsável por interpretar o evento e mudar seu estado
-
Publish/Subscribe
-
Separe Views de Models
- Model: representação dos dados de forma abstrata. Não tem nenhum conhecimento das views e dos controllers
- View: uma forma de interpretar o modelo. Subscreve a mudanças do model e eventos lógicos do controller
- Controller: Uma forma de controlar a view e provisionar um modelo com novas informações. Publica eventos tanto para a view quanto para a model
Blackboards (Quadros negros)
- Você normalmente não associa elegancia com detetivas policiais, mas olhe como detetives usam os quadro negros para solucionar um caso de assassinato.
- Nenhum detetive precisa saber da existência de outro detetive, apenas das informações do quadro
- Os detetives podem ter qualificações diferentes, mas possuem apenas o mesmo desejo de resolver o caso.
- Os detetives podem colocar ou modificar informações de forma livre
- Use blackboards para coordenar informações ⇒ Um quadro negro, em combinação com regras, que encapsulem requerimentos legais é uma solução elegante para uma quantidade de informações massivas que poderão chegar.
Capítulo 6 - While You Are Coding (Enquanto você está codando)
A sabedoria convencional diz que uma vez que o projeto esteja na fase de codificação, a grande parte do trabalho é mecânica, transcrevendo o design em expressões executáveis. Nós achamos que essa atitude é a grande razão para muitos programas serem feios, ineficientes, mal estruturados, difícil de dar manutenção e com muitos erros.
- Codar não é algo mecânico ⇒ Há decisões a serem feitas a cada minuto, o que requer pensamentos cuidados
- Programadores que não pensam sobre o seu código, programam por coincidência. Seu código pode até funcionar, mas não há razão para isso.
- Programadores pragmáticos pensam criticamente sobre odo o código, incluindo o seu próprio.
Programming by Coincidence (Programando por coincidência)
- Em filmes antigos vemos soldados andando em um terreno minado, sem saber onde estão as minas, sem ter nenhuma proteção. Enquanto avançam nenhuma delas explode, até que ao final ele se sentem aliviados. Quando dão mais um passo. BOOM! Eles são explodidos ⇒ A preocupação inicial pelas minas não revelou nada, foi apenas sorte.
- Como desenvolvedores trabalhamos diariamente em campos minados.
- Há muitos programadores que apenas fazem código, e aparentemente está tudo ok, ele prossegue até que em algum momento o código dá problema e ele não sabe o que está acontecendo.
- Acidentes de implementação ⇒ Acontecem pela forma a qual o código foi escrito (podem haver problemas de contextos, fluxo, ordem de chamada de funções, etc.)
- Acidentes de contexto
- Suposições implicitas ⇒ Não suponha algo com falsas causalidades. Prove algo, mostre algo, execute algo.
- Como programar deliberadamente
- Sempre esteja atento com o que você está fazendo
- Não code de forma cega
- Execute a partir de um plano
- Confie em coisas confiáveis, não dependa de acidentes e suposições
- Documente suas suposições
- Não apenas teste seu código, tete suas suposições. Não ache, tente!
- Priorize esforços
- Não seja escravo da história, não deixe que código legado dite o futuro do código
Algorithm Speed (Velocidade de algorísmos)
Como seu programa executa com 1000 registros? Ele consegue escalar para 1000000 registros? Há algo no código que precisa de otimizações?
- A maioria dos algorítimos não são lineares
- Muitos são abaixo da linha
- Mas há outros algorítmos que são piores do que os lineares
- Big O Notation ⇒ Lidando com aproximações
- Big O é a Ordem de algo
- O termo de maior ordem irá dominar o valor do N, isso pode permitir que algorítmos de mesma ordem tenham tempos de execução diferentes
- O(n²/2 + 3n) → O(n²/2) → O(n²)
- Loops simples ⇒ O(n)
- Loops aninhados ⇒ O(m x n) → O(n²)
- Corte binário ⇒ O(lg(n))
- Divida e conquista ⇒ O(n lg(n))
- Algorítimos que particionem seus inputs, trabalhem em duas metades independentes e depois combine os resultados
- Combinatório
- Normalmente envolvendo permutações
- Na grande parte das vezes nós teremos um código O(n²) e tentaremos aproximá-lo para O(n lg(n)), mas isso também depende da aplicabilidade, muitas vezes um O(n²) pode atender melhor do que um complexo O(n lg(n)) ⇒ Teste suas estimativas
- O melhor nem sempre é o melhor ⇒ Atente para otimizações prematuras
Refactoring (Refatoração)
Todos os programas evoluem, e assim se torna necessário repensar decisões antigas e refazer porções do código. Esse processo é perfeitamente natual. Muitas pessoas usam uma construção como metáfora para desenvolvimento de software, mas softwares não são assim. Códigos são mais orgânicos do que concretos.
- Softwares são mais parecidos com jardinagem
- Quando se deve refatorar
- Duplicações ⇒ violações do DRY
- Design não ortogonal ⇒ coisas que não deveriam se interferir estão se interferindo
- Conhecimento ultrapassado
- Performance
- Complicações do mundo real
- Muitas vezes tentamos falar ao nosso chefe que precisamos refatorar um código, que está funcionando, e que iremos gastar tempo nisso.
- Tempo é investimento, e uma refatoração é um tempo sendo usado e a resolução do problema não será vista de imediato e até mesmo a curto prazo. É necessário explicar os motivos da necessidade de refatoração para que o projeto não seja prejudicado no futuro e precise de uma intervenção muito grande e drástica
- Como você refatora?
- Não tente refatorar e adicionar novas funcionalidades ao mesmo tempo
- Tenha certeza de que você possui bons testes antes de refatorar. Execute os testes sempre que possível para verificar se nada foi quebrado.
- Faça de forma curta, pense os passos
Code That’s Easy to Test (Código que é fácil de testar)
Chips foram feitos para serem testados, não somente quando estão sendo fabricados, mas assim que eles são instalados e quando são entregues em campo. Muitos deles possuem mecanismos de diagnósticos internos ou mecanismos de acesso de testes.
- Nós podemos fazer exatamente a mesma coisa em um software, mas podemos fazer algo parecido para nos precaver.
- Testes unitários ⇒ testes isolados em módulos para verificar algum comportamento
- Um teste unitário de software é um teste que exercita um módulo através de um ambiente artificial.
- Testando contra o contrato ⇒ Nós queremos testar casos que nos dê certea de que uma unidade honra o seu contrato. Nós tentamos testar contra aquilo que era para acontecer.
- Testes unitários ⇒ testes isolados em módulos para verificar algum comportamento
- Cultura de testes ⇒ Teste seu software, ou usuários irão testar
Evil Wizards (Wizards/Instaladores maus)
- Aplicações estão ficando cada vez mais difíceis, complexas e sofisticadas
- Mas cuidado com instaladores/wizards que pretendem resolver todos os problemas com apenas alguns cliques e respostas.
- Há uma certa utilidade para automatizar alguns processos de escrita de código
- Mas os Wizards não tornam um desenvolvedor expert.
- Não use Wizard Codes que você não entenda
E aí pessoal, o que vocês acharam? Toda contribuição é bem vinda!