Last active
August 26, 2021 17:20
-
-
Save lsfernandes92/1cb831984fd1a2a024eb4d9cb3f0c935 to your computer and use it in GitHub Desktop.
Clean code
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
* Capítulo 13: Simultaneidade | |
- O fato de ter várias coisas fazendo | |
ao mesmo tempo, ao inves de fazer uma | |
por uma e não economizar tempo de request | |
- Não queremos que em um site de web | |
scrapper, por exemplo, não faça uma request | |
a cada vez que ele for procurar algo na | |
página | |
- Ter o código pensando de tal forma | |
ajuda a manter ele mais organizado e | |
seguindo conceitos do SRP | |
- É como separar o processamento em vários | |
computadores e não deixar um processamento | |
unico em um looping | |
- Do ponto de vista estrutural deixar a | |
aplicação mais organizada, ou seja, | |
todo parte de concorrencia é tratada | |
em algum modulo especifico. Do ponto | |
de vista de performance deixa a | |
aplicação com menos tempo de espera, | |
melhor respostas quando colocado sob | |
stress, e tals... | |
* Crenças e equívocos | |
- Mexer com problemas de concorrencia | |
pode ou não melhorar o desempenho. Considere | |
o exemplo de um aplicação que está com mt | |
tempo de resposta | |
- Melhorar problema de concorrencia | |
geralmente vai ter que ter uma reestruturação | |
do código | |
- É sempre mt dificil investigar esse | |
problema, pois são mts possibilidades de | |
caminhos que o código pode percorrer em | |
uma aplicação multi-thread | |
* Mecanismos de defesa pra/com código | |
de simultaniedade | |
- Abusar do conceito de SRP. O código | |
que trata de concorrência já tem suas | |
mais que razões pra mudar, por isso | |
seria legal separa-lo. Recomendação: | |
Separe seu código de concorrencia sempre | |
* Thread-safe ref: | |
- https://pt.wikipedia.org/wiki/Thread_safety | |
- https://www.devmedia.com.br/thread-safe-java-entendendo-o-conceito-e-usando-em-sua-aplicacao/28858 | |
* Thread safe | |
- Conceito que faz com que uma thread utilize de | |
forma compartilhada os seus dados sem interferir, ou | |
deixar inconsistencias em outras threads em andamento | |
* Continuação capítulo 13 sobre | |
simultaniedade(mecanismos de defesa) | |
- Ter consciencia e fazer com que as thread sejam | |
organizadas e executadas de maneira unica sem | |
atrapalhar outras thread ou deixar inconsistencias | |
- Conhecer suas bibliotecas. Ou seja saber usar | |
as mesmas que usam de conceitos de thread-safe | |
- Conceitos básicos para entender programação simultanea: | |
1. Exclusão mutua: Quando uma thread não interfere | |
na execução de outra thread | |
1. Starvation: Acontece quando uma thread que é considerada | |
mais rápida para executar é colocada na frente | |
na fila por motivos óbvios e, posteriormente, | |
essas mesmas threads demorar a executar. Em seguida threads | |
longas que esperam respostas dessas threads curtas | |
são interrompidas pois já esperavam a resposta dessa | |
threads curtas. | |
1. Livelock: Quando uma thread em andamento entra | |
em conflito com outra thread que tb está em andamento | |
1. Deadlock: Quando duas threads dependem uma da outra | |
para prosseguir. Basicamente oq acontece é essa | |
espera eterna entre as duas threads | |
- Modelos usado em programação concorrente | |
1. Produtor-consumidor: acontece quando existe um ou vários | |
produtores que assim que processam alguma coisa, coloca isso | |
em alguma fila ou buffer, notifica essa ação para que com | |
isso os consumidores fiquem cientes das notificações e | |
processem isso de maneira ordenada. Assim que os consumidores | |
fizerem isso eles tb lançam uma notificação avisando. | |
Esse tipo de comunicação por notificações é o pilar desse | |
tipo de programação. | |
2. Escritores-leitores: se baseia numa relação de leitura/escrita | |
onde oq deveria acontecer, ou de certa forma ser minimizada/balanceada, | |
é que quando alguém está lendo, que essa ação não seja interrompida | |
e vice versa para o caso da escrita. Esse tipo de progração pode | |
causar contra efeitos de deadlock ou livelock. | |
3. Jantar de filósofos: o exemplo é de: imagine uma mesa rodeada | |
de filósofos. A esquerda deles existem um garfo, eles estão | |
sentado em volta de uma mesa e no centro dela existe um bowl | |
com macarrão. A proposta é que eles devem refletir até que | |
sintam fome. Se sentirem fome eles devem comer somente com dois | |
garfos, porém se o filósofo do lado estiver usando o garfo | |
esse que iria comer deve esperar. No exemplo os filósofos | |
são substituidos por threads e o garfo por recursos. | |
- ESTEJE atento com o uso dos métodos sincronizados | |
e se possível usar somente em um lugar do objeto | |
que precisa dessa palavra chave | |
Caso não possível recorra a uma das três estratégias. São elas: | |
Client-Based Locking, Server-Based Locking ou Adapted Server. | |
- Utilize pouco do "synchronized" nos metódos. Aqui ele da o exemplo | |
de utilizar pouco dessa possibilidade encontrada na linguagem java | |
que é de utilizar da palavra "synchronized" para métodos que | |
queremos que tenha uma ação mais minusciosa e sem threads extras. | |
Porém o uso desse artefato deve ser bem pensado e não ser usado | |
de maneira absurda pois isso causa a degradação do throughput | |
do sistema. Recomendação: mantenha os métodos sincronizados pequenos | |
- ESTEJE atento para o correto momento de "desligar" partes | |
do sistema. A dica é: tenha em mente que isso é um tarefa | |
dificil, então pense nessa parte antecipadamente pq isso | |
provavelmente levará mais tempo que o necessário. | |
- Testando código que usam threads | |
Não ignorar testes que falham somente de vez em quando. | |
E algumas estratégias são: | |
- Manter os teste plugaveis, ou seja rodar em diversas | |
variações e configurações | |
- Resolver os bugs antes de qualquer coisa. Fazer com que | |
o código esteja funcionando adequado primeiramente antes | |
de partirmos para preocupações com threads | |
- Manter os testes "tunaveis", tentar arranjar uma | |
maneira com que vc consiga manipular as threads, | |
processadores, e tals... | |
- Rodar mais threads do que processadores | |
- Rodar o teste em várias plataformas, não mt a dizer, mas | |
diferentes plataformas tem suas diferentes formas de | |
tratar threads | |
- Forçar o código com métodos .sleep(), .wait() por exemplo. | |
Isso fará com que vc force seu código a aparecer com o erro. | |
Problemas: vc tem que saber exatamente a parte do código que | |
usará esse métodos, | |
* Capítulo 17 - Cheiros de código | |
O intuito aqui é só nomear alguns dos code smells apresentados. | |
Faz parte da minha maneira de tentar fixar algo que | |
estou estudando. | |
* Comentários: | |
1. Comentários inapropriados: que não diz respeito a coisas | |
técnicas ou de valor pra uma comentário. Não se preocupe | |
com isso pois o sistema de controle de versão está ali | |
pra isso | |
2. Comentário redundante: que simplesmente diz que aquela | |
parte do código é uma variavel ou simplesmente replica | |
o nome da variavel como comentário | |
3. Código comentado: é uma abominação! Se ver isso apague | |
e, novamente, deixe que o sistema de controle de versão | |
cuide disso. Se isso for realmente necessário já teria sido | |
descomentado | |
4. Comentário obsoleto: a dica novamente é: apague! | |
Comentários ficam obsoletos mt rápidos se não forem | |
implementados. Esse tipo de comentário é muito ruim, | |
pois pode levar a uma perda de tempo enorme rumando | |
vc que está tentando entender o código a uma direção | |
errada e atrapalhando seu conhecimento. | |
* Funções: | |
1. Função morta: uma função que não está sendo usada | |
é só apagar :) | |
2. Função com flag: muito ruim pois isso diz | |
claramente que aquela função está fazendo mais | |
de uma coisa. Partindo do principio que uma | |
função deveria fazer apenas uma coisa, isso | |
não deveria acontecer. Refatore para outra | |
função independente. | |
3. Função com muitos parametros: Função boa é | |
aquela com nenhum parametro. Nos demais casos tente | |
manter um número não superior a no máximo 3 parametros | |
passados para uma função. No demais refatore e tente | |
deixar aquilo aquela função mais coesa | |
* Gerais: | |
1. Comportamento óbvio não implementado: Isso faz | |
o leitor perder a confiançã no que ele espera | |
lendo uma função | |
2. Código de várias linguagens dentro de um unico | |
arquivo: tente evitar com que isso aconteça separandos | |
os arquivos | |
3. Duplication: tente sempre usar o conceito de DRY | |
por onde passe, pois isso deixa o código mais organizado, | |
menos propenso a erros e a abstração pode facilitar a vida | |
do amiguinho. Existe o claro exemplo de um código | |
duplicado, mas temos tb casos não tão óbvios, mas que | |
tb chamam a atenção, tipo: classes/módulos que fazem | |
coisas semelhantes e/ou if's ou switch's que sempre | |
aparecem em partes do código. | |
4. Inconsistencias: se vc começou a escrever o código | |
de uma forma tente usar o mesmo template nas linhas | |
seguintes. Por exemplo: nomeie variaveis de forma | |
semelhante. Coisas assim que deixam o código mais | |
fácil e melhor de ser lido | |
5. Separação vertical: mantenha códigos relacionados | |
próximos. Por exemploe: uma função privata loga abaixo | |
da função que está usando ela e variáveis locais no | |
começo de um método | |
6. Código morto: apague né, mores?! | |
7. Clutter: basicamente fala que não faz sentido ter | |
coisas que não estão sendo usadas, exemplo: métodos, | |
comentários, classes, etc... | |
8. Feature Envy: quando operações em um objeto | |
é feita dentro de outro objeto, deixando claro assim | |
que esse outro objeto não está devidamente encapsulado | |
9. Selector argument: Uma outra forma de dizer que | |
argumento flagueados não são uma boa idéia e nada mais | |
que uma maneira preguiçosa de dividir os métodos | |
10. Obscure intent: fala principalmente de nomes de | |
variaveis usando siglas, ou usando a conotação hungariana, | |
etc... | |
11. Artificial coupling: quandos dois objetos fazem | |
interações, mas que não fazem mt sentido esses dois | |
terem uma relação entre si, ou seja, parece uma forma | |
preguiçosa de ligar as coisas | |
12. Nomes de funções tem que expor oq elas fazer. | |
De nada adianta ter uma função de nome `Date.add(6)` | |
se não sabemos oq esse add está fazendo. Ela está | |
adicionando dias? Está adicionando horas? Está adicionando | |
minutos? Está criando uma nova insntancia de data ou | |
está somando com a data atual? Esse tipo de pergunta | |
devemos fazer ao olhar o nome de uma função | |
13. Escolher bem onde colocar as responsabilidades: | |
Acontece que muitas vezes entramos em um paradóxo | |
de tentar achar o melho lugar para colocar certas coisas. | |
14. Usar nomes de variaveis auto explanatórias: sem siglas e | |
sem abreviações | |
15. Entenda o código: o simples fato de usar if já demonstra | |
a força bruta que teve ao programar. Não há nada de errado | |
em usar if's, porém posteriormente tente entender e fazer | |
as abstrações corretas | |
16. Use polimorfia em vez de if/switch: | |
17. Use constantes para números mágicos: não todos, mas tente | |
ser crítico e nomear números soltos pelo código | |
18. Siga convenções do time: não importa se irá usar espaços ou | |
tabs para formatar seu código, contanto que vc concorde com o | |
que o time já usa em prática | |
19. Use dependencias fisicas e não lógicas: como por exemplo, | |
um número fixado para gerar páginas de relatórios. Esse tipo | |
de variavel deveria ser obtido apartir de um classe de "Reporter" | |
ou ao do tipo. Apenas de forma mais dinamica e não hard-coded | |
20. Seja preciso: tente escolher bem as coisas e ter uma lógica | |
do pq feito daquele jeito | |
21. Encapsular lógicas de if: pelo simples fato de if demandarem | |
um mapa mental na hora de ler o código | |
22. Tente não usar if negados: pelo simples fato de if demandarem | |
um mapa mental na hora de ler o código | |
23. Métodos devem fazer apenas uma coisa: SRP feelings | |
24. Tente expressar bem a ordem de chamar os métodos: se funções | |
devem ser chamadas em determinada ordem faça com isso seja | |
frisado de certa forma. Exemplo: | |
``` | |
Gradient gradient = saturateGradient(); | |
List<Spline> splines = reticulateSplines(gradient); | |
diveForMoog(splines, reason); | |
``` | |
25. Encapsular condições de limite: coisa do tipo `level + 1` | |
deveria ser jogada em uma variável do tipo `next_level = level + 1` | |
26. Não misture níveis de abstrações | |
27. Mantenha constantes usado pelo sistema em um lugar só | |
28. Lei do Demeter: Faça com que um objeto não "converse" | |
com estranhos. Exemplo: uma chamada do tipo `a.getB().getC()` | |
dificulta mt a mudança em uma sistema pq qualquer mudança no | |
meio do caminho nesses objetos, dificultaria a mudanças em | |
lugares do sistema que usa esse tipo de acesso | |
* Nomes: | |
1. Use nomes descritivos: o caso aqui é não usar siglas | |
ou palavra abreviadas. Use nome descritivos que explique | |
bem oque aquela variavel ou nome de função está fazendo | |
2. Não use nomes equivocadamente: nomeie algo que realmente | |
diga oq ele ta fazendo. Não tente omitir parte do que uma | |
função está fazendo na sua internalidade. | |
3. Use nome padrões quando der: exemplos disso é quando | |
se é usado uma pattern, exemplo: ImageFactory, OrderController, | |
e etc... Outro exemplo disso é quando o seu time no qual | |
está trabalhando usa certas nomenclaturas no código. Tente | |
usar isso ao máximo tb pq quanto mais lugar isso aparecer | |
no código, melhor o leitor irá se acostumar com o que isso | |
representa | |
4. Escolha nomes no mesmo nível de abstração: não tente | |
especializar muito quando nomeia alguma coisa (?). Tente | |
por exemplo abstrair aquele nome e não deixar com um nome | |
a tão baixo nível | |
5. Não esconta efeitos colaterais de uma coisa nomeadada: | |
Por exemplo uma função que retornar cria alguma coisa chamada | |
"oos" e retorna esse mesmo "oos" o nome dessa função deveria | |
se chamar `create_or_return_oos` e não somente `return_oos` | |
6. Quando maior o escopo maior o nome da váriavel: por exemplo: | |
tudo bem o nome de uma variavel chamar "j" ou "i" dentro | |
de um looping(principalmente em Java). Porém, o nome de | |
um método ou classe deveria ser mais descritivo que isso | |
7. Não use notações: não use os chamados encoding, por exemplo, | |
prefixos do tipo "m_", "f", "stringNomeVariavel", | |
"booleanNomeVariavel", etc... Isso hj em dia não é preciso | |
se preocupar principalmente com linguagen não tipadas. | |
* Testes: | |
1. Teste o suficiente: Se alguma coisa pode possivelmente | |
quebrar ou retornar algo inesperado, teste! Não deixe | |
de cobrir esses casos | |
2. Use alguma ferramente de cobertura de testes: eles | |
podem ajudar a vc encontrar testes de paths que não | |
foram pensados ou passaram despercebidos | |
3. Teste bem os limites | |
4. Não deixe de fazer os teste triviais: eles são importantes | |
e custam pouco pra fazer e de muito valor serve sua | |
documentação | |
5. Um teste ignorado pode ser uma questão que não está | |
esclarecida mt bem pelos requisitos da funcionalidade | |
6. Testes excessivamente em partes que existem bugs: | |
geralmente mais bugs são descobertos ao fazer esse | |
simples fato | |
7. Teste são na maioria das vezes reveladores de | |
problemas. Por exemplo, quando algum bug ou algo | |
acontece de errado o teste pode servir de um guia | |
mt bom para uma análise inicial | |
8. Looking at the code that is or is not executed | |
by the passing tests gives clues to why the | |
failing tests fail. | |
9. Mantenha a execução dos teste rápida |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment