Compare commits
19 Commits
master
...
draft/apre
Author | SHA1 | Date |
---|---|---|
Julio Biason | a4a22e8e01 | 3 years ago |
Julio Biason | 11936532fc | 3 years ago |
Julio Biason | 4a0d4b5b99 | 4 years ago |
Julio Biason | e18aac45d3 | 4 years ago |
Julio Biason | 08802f4472 | 4 years ago |
Julio Biason | 6857036ccb | 4 years ago |
Julio Biason | 2d40b9fb7e | 4 years ago |
Julio Biason | 782b6ed8d9 | 4 years ago |
Julio Biason | 536bd3fe37 | 4 years ago |
Julio Biason | 7976619f15 | 4 years ago |
Julio Biason | 78355b906c | 4 years ago |
Julio Biason | 3cd912caad | 4 years ago |
Julio Biason | d37bf85cb3 | 4 years ago |
Julio Biason | bb264408ed | 4 years ago |
Julio Biason | 632104b4d7 | 4 years ago |
Julio Biason | 87e73ed7e5 | 4 years ago |
Julio Biason | 6c1e94681f | 4 years ago |
Julio Biason | 7725a72308 | 4 years ago |
Julio Biason | aad14d2264 | 4 years ago |
111 changed files with 967 additions and 83 deletions
@ -0,0 +1,6 @@
|
||||
[book] |
||||
authors = ["Julio Biason"] |
||||
language = "pt" |
||||
multilingual = false |
||||
src = "src" |
||||
title = "Coisas Que Aprendi Na Marra (em 30 Anos de Desenvolvimento de Software)" |
@ -0,0 +1,102 @@
|
||||
# Resumo |
||||
|
||||
- [Introdução](./intro.md) |
||||
- [Avisos](./avisos.md) |
||||
- [Programação](./programacao/index.md) |
||||
- [Antes de Sair Programando](./programacao/antes.md) |
||||
- [Specs Antes, Código Depois](./programacao/antes/specs-antes.md) |
||||
- [Passos Como Comentários](./programacao/antes/passos-como-comentarios.md) |
||||
- [Gherkin É Seu Amigo para Entender Expectativas](./programacao/antes/gherkin.md) |
||||
- [Design Patterns São Usados Para Dar Nomes as Coisas, Não Para Soluções](./programacao/antes/patterns-nao-sao-solucoes.md) |
||||
- [Pensar em Fluxo de Dados Ganha de Design Patterns](./programacao/antes/fluxo-de-dados.md) |
||||
- [O Número Mágico Sete, Mais ou Menos Dois](./programacao/antes/numero-magico-sete.md) |
||||
- [Custo Cognitivo É O Assassino do Entendimento](./programacao/antes/custo-cognitivo.md) |
||||
- [Aprenda O Básico de Programação Funcional](./programacao/antes/programacao-funcional.md) |
||||
- [Atalhos São Legais, Mas Apenas a Custo Prazo](./programacao/antes/entenda-atalhos.md) |
||||
- [Debuggers São Superestimados](./programacao/antes/debuggers.md) |
||||
- [Pense Nos Usuários](./programacao/antes/usuarios.md) |
||||
- [Testes De Software](./programacao/testes.md) |
||||
- [Testes Unitários São Bons, Testes de Integração São Mais Melhores](./programacao/testes/testes-de-integracao.md) |
||||
- [Testar Toda Função Gera Código Morto](./programacao/testes/testes-codigo-morto.md) |
||||
- [Testes Geram Uma API Melhor](./programacao/testes/testes-apis.md) |
||||
- [Crie Testes Que Você Saiba Rodar Na Linha de Comando](./programacao/testes/testes-na-linha-de-comando.md) |
||||
- [Boas Linguagens Tem Testes Embutidos](./programacao/testes/linguagens-com-testes.md) |
||||
- [Documentando Seu Código](./programacao/documentacao.md) |
||||
- [Documentação É Uma Carta de Amor Ao Seu Futuro Eu](./programacao/documentacao/documente.md) |
||||
- [A Documentação de uma Função É o Seu Contrato](./programacao/documentacao/documentacao-e-contrato.md) |
||||
- [Se A Documentação de uma Função Tem "E", Está Errado](./programacao/documentacao/documentacao-com-e.md) |
||||
- [Boas Linguagens Tem Documentação Embutida](./programacao/documentacao/linguagens-com-documentacao.md) |
||||
- [Controle de Versões](./programacao/controle-de-versao.md) |
||||
- [Sempre Use Um Controle de Versão](./programacao/controle-de-versao/sempre-use-scv.md) |
||||
- [Um Commit Por Alteração](./programacao/controle-de-versao/um-commit.md) |
||||
- [Gerrit É Uma Cagada](./programacao/controle-de-versao/gerrit.md) |
||||
- [Git-Flow É o Caminho](./programacao/controle-de-versao/git-flow.md) |
||||
- [Organização de Projetos](./programacao/organizacao.md) |
||||
- [Organize Seu Código por Tipo de Dado, Não Por Função](./programacao/organizacao/organizacao-de-projetos.md) |
||||
- [Crie Bibliotecas](./programacao/organizacao/bibliotecas.md) |
||||
- [Notas em Papel São Bem Úteis](./programacao/organizacao/notas-em-papel.md) |
||||
- [Escrevendo Código](./programacao/programando.md) |
||||
- [Esteja Pronto Para Jogar Código Fora](./programacao/programando/jogar-fora.md) |
||||
- [Resolver O Futuro Gera Problemas Futuros](./programacao/programando/problemas-futuros.md) |
||||
- [Não Use Booleanos Como Parâmetros](./programacao/programando/parametros-booleanos.md) |
||||
- [Cuidado Com as Alterações de Interface](./programacao/programando/mudancas-de-interface.md) |
||||
- [É Melhor Deixar A Aplicação Explodir Do Que Fazer Nada](./programacao/programando/deixe-explodir.md) |
||||
- [Se Você Sabe Como Lidar Com O Erro, Lide](./programacao/programando/lide-com-erro.md) |
||||
- [Tipos Dizem O Que Seus Dados São](./programacao/programando/tipos-de-dados.md) |
||||
- [Se Os Seus Dados Tem Estrutura, Use Uma Estrutura](./programacao/programando/use-estruturas.md) |
||||
- [Não Mexa Em Coisas Fora do Seu Projeto](./programacao/programando/fora-do-projeto.md) |
||||
- [Resista À Tentação do Fácil](./programacao/programando/facil.md) |
||||
- [Comece de Forma Idiota](./programacao/programando/comece-idiota.md) |
||||
- [Sempre Use Timezones nas Datas](./programacao/programando/use-timezones.md) |
||||
- [Sempre Use UTF-8 nas Strings](./programacao/programando/use-utf8.md) |
||||
- [Otimização É Para Compiladores](./programacao/programando/otimizacao.md) |
||||
- [Unidades Fazem as Coisas Mais Claras](./programacao/programando/unidades.md) |
||||
- [Se Não Roda No Seu Computador, Está Errado](./programacao/programando/rode-localmente.md) |
||||
- [Nada Mais Permanente Que Uma Solução Temporária](./programacao/programando/solucao-permanente.md) |
||||
- [Fazendo As Coisas Andarem](./programacao/rodando.md) |
||||
- [O Arquivo de Config É Seu Amigo](./programacao/rodando/arquivo-de-config.md) |
||||
- [Opção de Linha de Comando São Esquisitas Mas Úteis](./programacao/rodando/opcoes-de-linha-de-comando.md) |
||||
- [Não Apenas Composição de Funções, Mas Composição de Aplicações](./programando/rodando/composicao-de-aplicacoes.md) |
||||
- [Mesmo Para Composição de Aplicações, Comece Idiota](./programacao/rodando/composicao-de-aplicacoes-idiota.md) |
||||
- [Logs São Para Eventos, Não Interface Com o Usuário](./programacao/rodando/logs-para-eventos.md) |
||||
- [Seja Transparente Com o Usuário](./programacao/rodando/transparencia.md) |
||||
- [Uma Versão para Adicionar, Uma Para Remover](./programacao/rodando/adicione-e-remova.md) |
||||
- [Aprenda a Monitorar](./programacao/rodando/monitoramento.md) |
||||
- [Comunidades e Times](./times/index.md) |
||||
- [Uma Linguagem É Mais Que Uma Linguagem](./times/linguagens-tem-mais.md) |
||||
- [Entenda e Afaste-se do "Cargo Cult"](./times/cargo-cult.md) |
||||
- ["A Ferramenta Certa" Tem Sempre Algo Por Trás](./times/a-ferramenta-certa.md) |
||||
- ["A Ferramenta Certa" É Mais Óbvia Do Que Você Pensa](./times/a-ferramenta-certa-obvia.md) |
||||
- [Revisão de Código Não É Para Validar Estilo](./times/estilos-em-revisao-de-codigo.md) |
||||
- [Formatadores de Código São Ok, Mas Nenhuma Bala de Prata](./times/formatador-de-codigo.md) |
||||
- [Estilo de Código: Siga-o!](./times/estilo-de-codigo.md) |
||||
- [... A Não Ser Que Seja o Estilo Google](./times/estilo-de-codigo-google.md) |
||||
- [Hero Projects: Você Vai Ter Que Fazer](./times/hero-projects.md) |
||||
- [Alterações Globais Devem Ser Discutidas com o Time](./times/discuta-com-o-time.md) |
||||
- [Pessoal](./pessoal/index.md) |
||||
- [Empresas Procuram por Especialistas, Mas Ficam com os Generalistas](./pessoal/especialistas.md) |
||||
- [Mantenha Uma Lista de Bugs Idiotas Que Levaram Mais de 1 Hora para Resolver](./pessoal/lista-de-bugs-idiotas.md) |
||||
- [Quando É Hora de Parar, É Hora de Parar](./pessoal/hora-de-parar.md) |
||||
- [Códigos de Conduta Protege](./pessoal/cdc.md) |
||||
- [Aprenda a Dizer Não](./pessoal/diga-nao.md) |
||||
- [Responsabilize-se Pelo Uso do Seu Código](./pessoal/responsabilize-se.md) |
||||
- [Não Diga Que Está Pronto Quando Não Estiver](./pessoal/nao-pronto.md) |
||||
- [Pessoas Se Irritam Com Arquitetura Porque Elas Se Importam](./pessoal/irritacao-com-arquitetura.md) |
||||
- [Você Vai Aprender Sobre Você Na Marra](./pessoal/aprender-sobre-voce.md) |
||||
- [Preste Atenção Como as Pessoas Reagem à Você](./pessoal/observe-reacoes.md) |
||||
- [Não Confunda "Hero Project" com "Síndrome do Herói"](./pessoal/sindrome-do-heroi.md) |
||||
- [Cuidado com Pessoas Tóxicas](./pessoal/pessoas-toxicas.md) |
||||
- [Cuidado com Micro-Agressões](./pessoal/micro-agressoes.md) |
||||
- [Pessoas Tóxicas/Agressivas Não Tem Solução -- A Menos Que Seja Você](./pessoal/solucao.md) |
||||
- [Perceba Quando For Hora de Sair](./pessoal/sair.md) |
||||
- [O Mundo da T.I. É Bem Pequeno](./pessoal/mundo-da-ti.md) |
||||
- [Escrever um Blog Sobre a Sua Solução Idiota É Melhor que o Silêncio](./pessoal/blogar.md) |
||||
- [Não Esconda Sua Solução Idiota](./pessoal/mostre-solucao-idiota.md) |
||||
- [Mantenha Uma Lista de Coisas Que Você Não Sabe](./pessoal/coisas-que-voce-nao-sabe.md) |
||||
- [Você Sempre Tem Tempo](./pessoal/tempo.md) |
||||
- [Assuma Suas Merdas](./pessoal/assuma.md) |
||||
- [Não Defenda Código Ruim](./pessoal/codigo-ruim.md) |
||||
|
||||
<!-- |
||||
vim:spelllang=pt tw=0: |
||||
--> |
@ -0,0 +1,42 @@
|
||||
# Avisos |
||||
|
||||
Existe uma coisa mágica que você precisa saber sobre esse livro: É tudo |
||||
opinião pessoal. |
||||
|
||||
Um monte de coisas que eu vou comentar pelo livro vai sair da minha |
||||
experiência pessoal em vários projetos -- sistema de aplicação, backends web, |
||||
sistemas embarcados, aplicações móveis, stream processing -- em várias |
||||
linguagens -- C, C++, Python, Java, Clojure, Rust. E, como parte de |
||||
experiência pessoal, tudo vai refletir a minhão opinião sobre os assuntos |
||||
abordados. |
||||
|
||||
Obviamente, você não precisa concordar com cada um dos pontos colocados. Mas |
||||
eu espero que pelo menos esses comentários façam você repensar esses assuntos. |
||||
|
||||
Ainda, algumas vezes eu posso mencionar algum exemplo que pessoas que me |
||||
conhecem -- porque trabalharam comigo, me ouviram reclamar de algum projeto, |
||||
herdaram um dos meus projetos, _eu_ herdei um dos projetos _deles_ -- podem |
||||
reconhecer do que eu estou falando e achar que eu estou atacando o autor |
||||
original. |
||||
|
||||
Eu não estou. |
||||
|
||||
Nós cometemos erros. Algumas vezes nós não conhecemos o assunto que estamos |
||||
atacando, algumas vezes nós não temos a especificação completa, algumas vezes |
||||
nós não temos o tempo certo para escrever as coisas da forma certa numa hora |
||||
de crise. E é por isso que algumas coisas não ficam tão bonitas quanto |
||||
deveriam. Se você acha que eu estou atacando o autor original de algum |
||||
exemplo, basta olhar as coisas que eu mesmo escrevi e você vai ver que eu fiz |
||||
coisas bem piores. |
||||
|
||||
Mas eu preciso do exemplo. Eu espero que mostrando para outras pessoas alguns |
||||
desses erros possa fazer com que as coisas melhorem. Eu quero mostrar de onde |
||||
saiu a minha opinião sobre os assuntos abordados. E, de novo, eu não estou |
||||
atacando o autor do código original. Eu posso até chamar o código de |
||||
"estúpido", mas não estou chamando o _autor_ de estúpido. |
||||
|
||||
Com isso em mente... |
||||
|
||||
<!-- |
||||
vim:spelllang=pt: |
||||
--> |
@ -0,0 +1,57 @@
|
||||
# Introdução |
||||
|
||||
"Coisas Que Eu Aprendi Na Marra (Em 30 Anos de Desenvolvimento de Software)" |
||||
começou como uma simples sequencia de toots (o mesmo que "tweets", mas no |
||||
[Mastodon](https://functional.cafe/@juliobiason) quando eu estava pensando em |
||||
escrever uma nova apresentação? |
||||
|
||||
Mas porque "uma nova apresentação"? |
||||
|
||||
Eu participo de um grupo chamado "[Tchelinux](https://tchelinux.org)" com o |
||||
qual eu atravessei o estado; nós normalmente fazemos eventos em universidades |
||||
e falamos para pessoas que estão começando a universidade, explicando coisas |
||||
sobre software livre (libre) e algumas vezes falando sobre coisas que essas |
||||
pessoas normalmente não veriam no currículo da universidade. |
||||
|
||||
Uma coisa que me incomoda é que poucas apresentações falam sobre "quando as |
||||
coisas dão errado". Todas apresentações mostram protótipos ou comentam os |
||||
pontos positivos de alguma coisa, e escondem tudo que poderia dar de |
||||
errado[^1]. Obviamente, depois de trabalhar por 30 anos com desenvolvimento de |
||||
software, eu vi uma boa quantidade de coisas que dão errado -- algumas vezes |
||||
numa montanha gigantesca de cagadas -- e por isso pensei "Talvez essa seja uma |
||||
coisa que as pessoas gostariam de ouvir". |
||||
|
||||
(E pra ser completamente honesto, algumas dessas cagadas gigantescas foram |
||||
totalmente culpa minha.) |
||||
|
||||
E foi assim que a sequencia de toots começou. Antes que eu percebesse, eu |
||||
passei praticamente o dia todo postando esse tipo de coisa (felizmente, a |
||||
minha caixa de "coisas pra fazer" estava praticamente vazia na época) e a |
||||
lista chegou a 30 pontos, mais adendos e alguns pontos com algumas |
||||
explicações. E foi assim que eu decidi transformar num post do meu blog. |
||||
|
||||
(Aliás, minto: Alguém mencionou no Functional Café que eu deveria fazer um |
||||
post no meu blog para facilitar a leitura.) |
||||
|
||||
A única coisa que eu pensei quando agrupei tudo num post era "isso vai ajudar |
||||
as pessoas a ler o conteúdo ao invés de ter que sair correndo atrás dos toots |
||||
no Mastodon". Mas aí o posto apareceu no Reddit. E no Twitter. E no |
||||
HackerNews. E no YCombination. E nenhum desses foi feito por mim. |
||||
|
||||
Mas uma coisa: Cada ponto estava limitado pelo tamanho de um toot, que são 500 |
||||
caracteres. Algumas vezes, isso não é o suficiente para expandir um ponto, |
||||
explicá-lo corretmente e adicionar alguns exemplos. |
||||
|
||||
E foi assim que esse "livro" nasceu. |
||||
|
||||
Uma coisa que você precisa ter em mente aqui: *Essas são minhas opiniões*. Eu |
||||
entendo que não é tudo "preto no branco" como eu coloco aqui, e experiencias |
||||
de outras pessoas podem não ser exatamente iguais. Ainda, você fica um pouco |
||||
cínico sobre tecnologia depois de 30 anos. Então... vá com calma, pois [Hic |
||||
sunt dracones](https://pt.wikipedia.org/wiki/Hic_sunt_dracones). |
||||
|
||||
[^1]: Sim, eu também sou culpado de fazer isso. |
||||
|
||||
<!-- |
||||
vim:spelllang=pt: |
||||
--> |
@ -0,0 +1 @@
|
||||
# Você Vai Aprender Sobre Você Na Marra |
@ -0,0 +1 @@
|
||||
# Escrever um Blog Sobre a Sua Solução Idiota É Melhor que o Silêncio |
@ -0,0 +1 @@
|
||||
# Não Defenda Código Ruim |
@ -0,0 +1 @@
|
||||
# Mantenha Uma Lista de Coisas Que Você Não Sabe |
@ -0,0 +1 @@
|
||||
# Empresas Procuram por Especialistas, Mas Ficam com os Generalistas |
@ -0,0 +1 @@
|
||||
# Quando É Hora de Parar, É Hora de Parar |
@ -0,0 +1 @@
|
||||
# Pessoas Se Irritam Com Arquitetura Porque Elas Se Importam |
@ -0,0 +1 @@
|
||||
# Mantenha Uma Lista de Bugs Idiotas Que Levaram Mais de 1 Hora para Resolver |
@ -0,0 +1 @@
|
||||
# Cuidado com Micro-Agressões |
@ -0,0 +1 @@
|
||||
# Não Esconda Sua Solução Idiota |
@ -0,0 +1 @@
|
||||
# O Mundo da T.I. É Bem Pequeno |
@ -0,0 +1 @@
|
||||
# Não Diga Que Está Pronto Quando Não Estiver |
@ -0,0 +1 @@
|
||||
# Preste Atenção Como as Pessoas Reagem à Você |
@ -0,0 +1 @@
|
||||
# Cuidado com Pessoas Tóxicas |
@ -0,0 +1 @@
|
||||
# Responsabilize-se Pelo Uso do Seu Código |
@ -0,0 +1 @@
|
||||
# Perceba Quando For Hora de Sair |
@ -0,0 +1 @@
|
||||
# Não Confunda "Hero Project" com "Síndrome do Herói" |
@ -0,0 +1 @@
|
||||
# Pessoas Tóxicas/Agressivas Não Tem Solução -- A Menos Que Seja Você |
@ -0,0 +1,8 @@
|
||||
# Antes de Sair Programando |
||||
|
||||
Antes de sentar na frente do computador e abrir o seu editor de textos/IDE para |
||||
escrever código, talvez você precise dar um passo para trás e pensar algumas coisas. |
||||
|
||||
<!-- |
||||
vim:spelllang=pt: |
||||
--> |
@ -0,0 +1,52 @@
|
||||
# Custo Cognitivo É O Assassino do Entendimento |
||||
|
||||
"[Dissonância Cognitiva](https://en.wikipedia.org/wiki/Cognitive_dissonance)" é |
||||
um nome bonito para dizer "Eu preciso lembrar duas (ou mais) coisas diferentes |
||||
e contraditórias ao mesmo tempo para entender isso". Manter essas coisas |
||||
diferentes na sua cabeça cria um custo que fica acumulando quanto mais |
||||
indiretas essas coisas são (porque você precisa manter todas elas ao mesmo |
||||
tempo). |
||||
|
||||
(Aviso: Eu gosto de usar a expressão "dissonância cognitiva" para parecer |
||||
inteligente. Eu explico depois a diferença entre "dissonância cognitiva" e |
||||
"custo cognitivo".) |
||||
|
||||
Para dar um exemplo (leve) de custo cognitivo, eu vou lhe mostrar o seguinte: |
||||
|
||||
* Você tem uma função chamada `sum()`. Ela retorna o somatório de uma lista de |
||||
números. |
||||
* O sistema está cheio de funções que começam com `is_`. Essas funções fazem um |
||||
teste e retorno um valor booleano. |
||||
* Existe uma função chamada `is_even()`. Ela recebe um número e retorna True se |
||||
o valor é par e False se o valor for ímpar. |
||||
|
||||
Bem simples, certo? Uma função faz o somatório de números e outra retorna um |
||||
booleano. |
||||
|
||||
Agora, o que você pensaria se visse isso, em Python: |
||||
|
||||
```python |
||||
sum(is_even(x) for x in my_list) |
||||
``` |
||||
|
||||
Espera aí, eu não tinha dito que `sum()` faz o somatório de números? E que |
||||
`is_even()` retorna um booleano? Como é que eu somo booleanos? Qual é o |
||||
resultado esperado de "True + True + False"? |
||||
|
||||
Infelizmente, isso funciona. Porque alguém, a muito tempo atrás, não achava que |
||||
booleanos era importantes o suficiente e usaram um inteiro no lugar. E todo |
||||
mundo que veio depois cometeu o mesmo erro. |
||||
|
||||
Mas, para você, você vai ver uma linha que diz "somando uma lista de booleanos |
||||
retorna um número". E isso são duas coisas diferentes que você tem que, de |
||||
repente, manter em mente quando estiver lendo essa linha. |
||||
|
||||
É por isso que [tipos são importantes](../programando/tipos-de-dados.md). E |
||||
custo cognitivo também está relacionado com [o número mágico |
||||
sete](./numero-magico-sete.md) porque você tem que manter duas coisas |
||||
ao mesmo tempo em mente, mas o primeiro é sobre itens relacionados, enquanto |
||||
que custo cognitivo se refere a coisas diferentes. |
||||
|
||||
<!-- |
||||
vim:spelllang=pt: |
||||
--> |
@ -0,0 +1,36 @@
|
||||
# Debuggers São Superestimados |
||||
|
||||
Volta e meia eu escuto alguém reclamando que alguns editores de código são |
||||
ruins porque é difícil usar um debugger dentro deles. Eu diria que essa visão |
||||
está errada. |
||||
|
||||
Mas vamos tirar algo do caminho antes de mais nada: Eu não estou querendo dizer |
||||
que debuggers são ruins e que você não deveria nunca usar um. Debuggers tem o |
||||
seu uso, mas toda vez que eu tentei usar um, era porque havia alguma outra |
||||
coisa faltando. |
||||
|
||||
Quando eu estava usando um framework em Java, eu tive alguns problemas com o |
||||
código que eu havia escrito. Eu esperava que [a aplicação |
||||
explodisse](../programando/deixe-explodir.md) porque eu não coloquei nada para |
||||
lidar com os problemas. O que aconteceu foi que o framework escondeu o erro e |
||||
reiniciou o processamento. Para encontrar o que estava acontecendo, eu tive que |
||||
conectar um debugger e ver o que havia de errado com os dados; se eu não |
||||
fizesse isso, eu não teria a menor ideia de onde estava o problema. |
||||
|
||||
O debugger era necessário aqui? Eu acredito que não. Se o framework mostrasse o |
||||
erro (explodisse, botasse uma textão nos logs, seja lá o que for), eu não |
||||
precisaria usar o debugger. Mas, porque havia coisas faltando, eu fui _forçado_ |
||||
a usar um debugger. |
||||
|
||||
Além disso, a longo prazo, você acaba com problemas em lugares onde você não |
||||
pode conectar um debugger -- por exemplo, no seu ambiente de produção. Você até |
||||
_pode_, mas não _deveria_. Por outro lado, se você estiver [logando |
||||
eventos](../rodando/logs-para-eventos.md), então você veria o que está |
||||
acontecendo, sem um debugger. |
||||
|
||||
De novo, não quero desmerecer debuggers, mas a longo prazo, eles se tornam |
||||
inúteis e acabam apontando para lugares onde o suporte ao redor está faltando. |
||||
|
||||
<!-- |
||||
vim:spelllang=pt: |
||||
--> |
@ -0,0 +1,34 @@
|
||||
# Atalhos São Legais, Mas Apenas a Custo Prazo |
||||
|
||||
Várias linguagens/bibliotecas/frameworks vem com alguma funcionalidade para |
||||
fazer com que você escreva menos código do que normalmente precisaria. |
||||
|
||||
Mas o uso desses atalhos uma hora não vão servir para o que você precisa e aí |
||||
você vai precisar entender o que é que o atalho faz de verdade. |
||||
|
||||
Frameworks e bibliotecas -- e até mesmo algumas linguagens -- vêm com "helpers" |
||||
para a maior parte das coisas com boilerplate. Ao invés de digitar 5 linhas de |
||||
código várias vezes, você usa uma função simples; ao invés de escrever a função |
||||
com 5 parâmetros, você ignora alguns dados e usa uma função com apenas um. Ou |
||||
você pode adicionar uma macro de expansão em cima da sua estrutura/classe e os |
||||
pontos faltantes vão ser automaticamente completados. |
||||
|
||||
Não me entenda errado, eu acho atalhos super úteis. |
||||
|
||||
Mas você precisa entender o que é que a macro/função está escondendo de você. |
||||
Porque mais cedo ou mais tarde, vai aparecer aquele caso em que o atalho não é |
||||
a solução perfeita e você precisa apenas mudar um pequeno detalhe. E aí você |
||||
vai ficar andando em círculos porque, bom, como é que diabos a macro/função faz |
||||
_aquilo_? |
||||
|
||||
Eu já me dei mal com [Spring](http://spring.io/) e [Serde](https://serde.rs/') |
||||
porque eu comecei usando os atalhos sem entender o que eles faziam. E quando eu |
||||
precisei resolver um problema que o atalho não conseguia resolver sozinho, eu |
||||
tive que me aprofundar na documentação. E como eu pulei vários passos e fui |
||||
direto pro atalho, eu levei um bom tempo para realmente _entender_ o que é que |
||||
eu precisava fazer de diferente do que o que o atalho faz para resolver meu |
||||
problema. |
||||
|
||||
<!-- |
||||
vim:spelllang=pt: |
||||
--> |
@ -0,0 +1,30 @@
|
||||
# Pensar em Fluxo de Dados Ganha de Design Patterns |
||||
|
||||
Quando você estiver tentando encontrar uma solução para o seu problema, pense |
||||
na forma como os dados irão fluir pelo seu código. |
||||
|
||||
Ao invés de focar em design patterns, uma forma melhor é pensar na forma como |
||||
o dado vão fluir -- e ser transformado -- no seu cóðigo. |
||||
|
||||
Por exemplo, o usuário irá digitar um número. Você vai pegar esse número e |
||||
encontrar o registro específico no banco de dados. Essa é uma transformação -- |
||||
não, não é "Eu vou pegar o número e receber uma coisa completamente diferente |
||||
baseado nesse número"; você está transformando o número num registro, usando o |
||||
banco de dados como transformação. |
||||
|
||||
(Sim, eu sei, não parece óbvio de cara, mas se você tem que pensar que os dois |
||||
são representações do mesmo dado.) |
||||
|
||||
A maior parte das vezes que eu fiz isso, eu consegui criar uma design mais |
||||
óbvio para minhas aplicações. Eu não pensei em quantas funções/classes seriam |
||||
necessárias para fazer essas transformações, isso foi algo que eu pensei |
||||
_depois_ de conseguir ver como os dados iriam fluir no código. |
||||
|
||||
De certa forma, essa forma de pensar deixar as coisas mais simples porque você |
||||
tem uma lista de passos de transformações que você precisa fazer, de forma que |
||||
você coloca um depois do outro, descrevendo _exatamente_ o que o seu código |
||||
faz, o que previne um monte de código ruim no futuro. |
||||
|
||||
<!-- |
||||
vim:spelllang=pt: |
||||
--> |
@ -0,0 +1,53 @@
|
||||
# Gherkin É Seu Amigo para Entender Expectativas |
||||
|
||||
Gherkin é um formato de arquivo para escrever testes de comportamento (BDD - |
||||
Behavior Driven Development). Mas também pode ser usado para dar a você |
||||
algumas dicas do que deve ser feito. |
||||
|
||||
Então, vamos falar um pouco sobre o Gherkin: |
||||
|
||||
[Gherkin](https://en.wikipedia.org/wiki/Cucumber_(software)#Gherkin_language) |
||||
é um formato de arquivo criado para o [Cucumber](https://en.wikipedia.org/wiki/Cucumber_(software)), |
||||
onde são descritos os cenários, o que há neles, quais ações o usuário/sistema |
||||
irá fazer e o qual é o resultado esperado dessas ações, em alto nível, |
||||
permitindo que pessoas sem experiência em programação possam descrever qual é |
||||
o resultado esperado de um sistema. |
||||
|
||||
Embora Gherkin tenha nascido com o Cucumber, esse formato é suportado por |
||||
várias linguagens, através de bibliotecas externas. |
||||
|
||||
Um arquivo Gherkin típico pode ser parecer com isso: |
||||
|
||||
* **Dado que** _estado inicial do sistema_ |
||||
* **Quando** _ação feita pelo usuário ou por um sistema externo_ |
||||
* **Então** _estado esperado_ |
||||
|
||||
Ou, num formato mais concreto: |
||||
|
||||
* **Dado que* o sistema está recuperando todos os tweets que o usuário deu |
||||
"like" |
||||
* **Quando** é encontrado um tweet com um anexo |
||||
* **Então** o anexo deve ser saldo junto com o texto do tweet |
||||
|
||||
Simples, não? |
||||
|
||||
E porque eu estou mencionando o Gherkin? |
||||
|
||||
Algumas vezes, as especificações não são a forma mais direta de informação |
||||
sobre o que é esperado do sistema, e você não consegue pensar em como |
||||
[escrever os passos necessários](./passos-como-comentarios.md). Se você está |
||||
confuso sobre o que deve escrever, perguntar para a pessoa responsável para |
||||
escrever algo parecido com o Gherkin pode lhe trazer mais informações do que |
||||
deve ser feito. |
||||
|
||||
Obviamente, não vai ser completo. Pessoas tendem a esquecer situações de erro |
||||
-- como preencher o campo de nome somente com números, usar letras num campo |
||||
de idade, tweets sem nenhum texto e apenas anexos -- mas pelo menos com uma |
||||
descrição do sistema em Gherkin, você pode ter uma visão melhor do todo. |
||||
|
||||
Também, você pode não gostar de escrever especificações. Tudo bem, você pode |
||||
trocar elas por Gherkin. |
||||
|
||||
<!-- |
||||
vim:spelllang=pt: |
||||
--> |
@ -0,0 +1,118 @@
|
||||
# O Número Mágico Sete, Mais ou Menos Dois |
||||
|
||||
"[The magical number](https://en.wikipedia.org/wiki/The_Magical_Number_Seven,_Plus_or_Minus_Two)" |
||||
(O Número Mágico Sete, Mais Ou Menos Dois) é um artigo sobre a psicologia do |
||||
número de coisas que nós conseguimos manter na nossa memória ao mesmo tempo. |
||||
|
||||
Pelo menos duas vezes eu vi esse tipo de construção onde uma função faz um |
||||
processamento, mais o retorno é o resultado desse processamento, mais o |
||||
resultado de uma segunda função e um processamento. Nada muito grande. Mas a |
||||
segunda função também faz um processamento e chama uma terceira função. E a |
||||
terceira função chama uma quarta. E a quarta, uma quinta. E a quinta função |
||||
chama uma sexta. |
||||
|
||||
E "processamento" não era nada pequeno, como "adicionar dois" ou "multiplicar |
||||
por si mesmo ou por um valor configurável". |
||||
|
||||
Algo do tipo: |
||||
|
||||
``` |
||||
func_1 |
||||
+-- func_2 |
||||
+-- func_3 |
||||
+-- func_4 |
||||
+-- func_5 |
||||
+-- func6 |
||||
``` |
||||
|
||||
(Se você estiver curioso sobre o verdadeiro processamento que eu vi, era uma |
||||
classe com uma função que fazia um processamento e chamava uma função de uma |
||||
classe injetada com injeção de dependências -- que é bem legal. Mas a |
||||
classe/dependência injetada tinha uma dependência injetada, e a terceira |
||||
injeção de dependência _também_ tinha uma dependência injetada e assim por |
||||
diante.) |
||||
|
||||
Agora, quando você está tentando entender esse tipo de código para encontrar |
||||
um problema, você precisa manter em mente o que a primeira, segunda, terceira, |
||||
quarta, quinta e sexta funções fazem, porque elas ficam se chamando |
||||
(internamente). |
||||
|
||||
Isso causa uma sobrecarga mental que não deveria ser necessária. |
||||
|
||||
Não apenas isso, mas imagine que você bote um log antes e depois de chamar |
||||
`func_1`: o primeiro log vai mostrar os dados antes de serem enviados para a |
||||
função e o segundo log vai mostrar o resultado da chamada. |
||||
|
||||
Aí você vai ficar com a impressão que `func_1` faz um monte de coisas, sendo |
||||
que ela faz uma transformação simples e passa adiante (novamente, |
||||
internamente). |
||||
|
||||
(Eu tive essa experiência estranha com uma função chamada `expand`, que o log |
||||
antes da chamada mostrar os dados crus, compactado, mas o resultado não era |
||||
era o resultado descompactado, mas os dados já processados depois de |
||||
compactados.) |
||||
|
||||
E qual seria a solução pra isso, você deve estar perguntando. |
||||
|
||||
Bom, se ao invés de fazer a `func_1` chamada a `func_2`, você pode fazer ela |
||||
retornar o resultado (que não necessariamente é o resultado final) e _então_ |
||||
chamar `func_2` com esse resultado. |
||||
|
||||
Algo do tipo: |
||||
|
||||
``` |
||||
result1 = func_1 |
||||
result2 = func_2(result1) |
||||
result3 = func_3(result2) |
||||
result4 = func_4(result3) |
||||
result5 = func_5(result4) |
||||
result6 = func_6(result5) |
||||
result7 = func_7(result6) |
||||
``` |
||||
|
||||
(Se voltarmos a nossa cadeira de injeção de dependências, você pode imaginar |
||||
quao invés de fazer DI7[^1] receber DI6 [que iria receber DI5 como |
||||
dependência, que iria receber DI4 como dependência, que iria receber DI3 como |
||||
dependência e assim por diante], você pode receber todas as dependências |
||||
injetadas numa única passada e aí iniciar a função que iria chamar as |
||||
dependência num só tacada, ao invés de encadear uma na outra.) |
||||
|
||||
Agora você consegue entender _exatamente_ como é que os dados são |
||||
transformados -- e as funções teriam nomes melhores, como `expand`, |
||||
`break_lines`, `name_fields` e assim por diante, de forma que você consiga ver |
||||
que os dados compactados que eu comentei anteriormente são descompactados, o |
||||
conteúdo é quebrado linha por linha, e as linhas estão sendo tratadas para |
||||
colocar os nomes nos campos e assim por diante (e alguém poderia até mesmo |
||||
dizer que as coisas ficariam mais claras se depois de `break_lines` tivesse |
||||
uma função chamada `break_fields`, o que faria a função de `name_fields` mais |
||||
óbvia -- e uma construção como essa faria com que essa alteração fosse |
||||
trivial). |
||||
|
||||
"Não isso não performa!" alguém pode gritar. Bom, talvez seja um pouco menos |
||||
performático que o original com chamadas aninhadas (porque não precisaria |
||||
criar e destruir os frames na stack, simplesmente iria empilhar os frames e |
||||
destruir tudo no final), mas otimização é para compiladores, não pessoas. O |
||||
seu trabalho é fazer com que o código seja _legível_ e _inteligível_. Se você |
||||
precisa de performance, você precisa pensar numa melhor sequência de passos |
||||
(ou um armazenamento de dados melhor), não uma solução terrível de ser |
||||
entendida. |
||||
|
||||
Só uma nota rápida: Embora o artigo acima indique o número é próximo de 7, |
||||
novas pesquisas mostram que esse número é bem mais baixo que isso, mais para 4. |
||||
Então simplesmente fazendo `func_1` chamar `func_2`, que chamaria `func_3`, |
||||
que chamaria `func_4` já seria o suficiente para sobrecarregar alguém e fazer |
||||
com que eles percam a ideia do que o código faz. |
||||
|
||||
PS: Se você conhecer um pouco de programação funcional, eu estou sugerindo |
||||
usar [composição de |
||||
funções](https://pt.wikipedia.org/wiki/Composi%C3%A7%C3%A3o_de_fun%C3%A7%C3%B5es) |
||||
ao invés de fazer chamadas aninhadas. |
||||
|
||||
--- |
||||
|
||||
[^1]: A classe no sétimo nível de injeção de dependência; a primeira classe |
||||
com dependências injetadas seria "DI1". |
||||
|
||||
<!-- |
||||
vim:spelllang=pt: |
||||
--> |
@ -0,0 +1,57 @@
|
||||
# Passos Como Comentários |
||||
|
||||
Você não ver o caminho para resolver o seu problema? Escreva os passos como |
||||
comentários no seu código. |
||||
|
||||
Você está lá, olhando para um arquivo vazio, se perguntando como é que vai |
||||
resolver o problema. Uma dica: |
||||
|
||||
Pegue as especificações que você (ou alguém) escreveu. Quebre cada ponto num |
||||
série de passos para chegar ao resultado esperado. Você pode escrever em |
||||
qualquer linguagem, se você não quiser fazer em inglês[^1]. |
||||
|
||||
A partir daí, preencha os espaços entre os comentários com código. |
||||
|
||||
Por exemplo, se você tiver uma especificação que diz "conecte ao servidor X e |
||||
recupere todos os dados. Salve o conteúdo num banco de dados. Lembre-se que a |
||||
API do servidor X permite que se passe um ID (o último ID visto) e você pode |
||||
usar isso para não ficar pedindo o mesmo conteúdo várias vezes". Fácil, né? |
||||
|
||||
Escrevendo isso comentário, com os passos que você tem que fazer, você pode |
||||
chegar a ter algo do tipo: |
||||
|
||||
``` |
||||
// conectar ao servidor X |
||||
// recuperar os dados |
||||
// mandar os dados para o banco de dados |
||||
``` |
||||
|
||||
Ah, você esqueceu a parte do ID. Sem problemas, você adiciona esse passo no |
||||
lugar certo -- no nosso exemplo, não faz sentido conectar ao servidor antes de |
||||
ter o último ID visto, por exemplo: |
||||
|
||||
``` |
||||
// abrir o arquivo de configuração |
||||
// pegar o último ID visto; se o arquivo estiver vazio, não tem último ID |
||||
// conectar ao servidor X |
||||
// recuperar os dados a partir do último ID visto |
||||
// enviar os dados para o banco. |
||||
// salvar o último ID no arquivo de configuração |
||||
``` |
||||
|
||||
Agora ficou "fácil"[^2] : Você só precisa adicionar o código. |
||||
|
||||
Se você estiver procurando por uma opção melhor, você pode transformar os |
||||
comentários em funções e, ao invés de ficar escrevendo o código entre os |
||||
comentários, você escreve a funcionalidade na função e, dessa forma, mantém |
||||
uma visão limpa do que a aplicação faz. |
||||
|
||||
--- |
||||
|
||||
[^1]: Só porque "inglês" é a lingua franca da programação. |
||||
|
||||
[^2]: Sim, eu estou sendo sarcástico. |
||||
|
||||
<!-- |
||||
vim:spelllang=pt: |
||||
--> |
@ -0,0 +1,34 @@
|
||||
# Design Patterns São Usados Para Dar Nomes as Coisas, Não Para Soluções |
||||
|
||||
Infelizmente, a maior parte das vezes que eu vi design patterns sendo |
||||
aplicados, ele foram aplicados como uma forma de achar uma solução, e acabaram |
||||
forçando o problema a ser "distorcido" para caber no pattern. |
||||
|
||||
Eu acredito que a grande maioria dos "vamos aplicar _esse_ design pattern" |
||||
antes que o problema seja entendi -- ou mesmo que se tenha tentando achar uma |
||||
solução -- vem como uma forma de [cargo cult](../../times/cargo-cult.md): "Nós |
||||
vimos que pessoas usaram esse pattern e resolveram o problema deles, então |
||||
vamos fazer o mesmo e resolver o nosso problema". Ou, pior: "Esse design |
||||
pattern foi criado por _pessoa famosa_, então vamos usar". |
||||
|
||||
Mas a verdade é que design patterns _não_ devem ser usados como uma forma de |
||||
encontrar uma solução para qualquer problema. Você pode usar alguns deles como |
||||
base para a solução, mas você deve focar no _problema_, não no _pattern_. |
||||
|
||||
"Será que o Visitor Pattern resolve isso?" é a pergunta errada. "O que devemos |
||||
usar para resolver nosso problema?" é a pergunta que realmente deve ser feita. |
||||
Uma vez que você resolveu o problema, você pode olhar e ver que é um visitor |
||||
pattern -- ou qualquer outro pattern. Se a solução não se parece com o |
||||
pattern, tudo bem, porque você _resolveu o problema_. E se o pattern |
||||
_resolveu_ seu problema... bom, parabêns, você sabe como chamar a sua |
||||
solução. |
||||
|
||||
Eu vi isso acontecer várias vezes: Pessoas tem um problema; pessoas decidem |
||||
usar um pattern; o pattern não resolve o problema (não resolve exatamente |
||||
100%, mas acima de 50%); o que acontece é que as pessoas começam a destorcer o |
||||
problema para que ele se encaixe no pattern ou, pior, começam a adicionar |
||||
camadas para transformar o problema no pattern. |
||||
|
||||
<!-- |
||||
vim:spelllang=pt: |
||||
--> |
@ -0,0 +1,65 @@
|
||||
# Aprenda O Básico de Programação Funcional |
||||
|
||||
Nessa altura do campeonato, você deve ter ouvido falar de como programação |
||||
funcional é legal. Existem vários conceitos nela, mas tenha em mente os |
||||
conceitos mais básicos dela. |
||||
|
||||
Um monte de apresentações sobre programação funcional vêm com palavras |
||||
estranhas como "functors" e "monads". Não que seja prejudicial conhecer o que |
||||
elas querem dizer (aviso: eu ainda não sei). Mas algumas coisas da programação |
||||
funcional são fáceis de entender e usar. |
||||
|
||||
Por exemplo, imutabilidade. Isso quer dizer que os seus dados não podem mudar |
||||
depois de criados. Você tem um registro de um usuário e o usuário mudou de |
||||
senha? Não, não mude o valor do campo de senha, crie um novo registro de |
||||
usuário com a senha atualizada e remova o antigo. Eu sei que isso cria uma |
||||
sequencia de "cria e destrói" que basicamente não fazem sentido (porque você |
||||
deveria alocar memória para um novo usuário, copiar todos os campos com exceção |
||||
de um, definir apenas um campo, e liberar a memória do antigo? Não faz |
||||
sentido!) mas, a longo prazo, isso previne resultados estranhos, principalmente |
||||
depois de você entender e começar a usar threads. |
||||
|
||||
(A ideia é prevenir um estado compartilhado -- memória -- entre partes do seu |
||||
código.) |
||||
|
||||
Outro conceito útil são funções puras. Funções puras são funções que, se |
||||
chamadas com os mesmos parâmetros, sempre retornam o mesmo resultado, não |
||||
importa quantas vezes você as chame. Um exemplo de função não pura é o |
||||
`random()`: cada vez que você chama `random()`, você tem como retorno um valor |
||||
diferente[^1]. Um exemplo de uma função pura seria algo parecido com isso em |
||||
Python: |
||||
|
||||
```python |
||||
def mult(x): |
||||
return x * 4 |
||||
``` |
||||
|
||||
Não importa quantas vezes você chame `mult2)`, sempre terá o 8 como resultado. |
||||
|
||||
Outro exemplo seria nossa senha imutável apresentada acima: Você pode |
||||
facilmente escrever uma função que recebe um registro de usuário e retorna um |
||||
novo registro com a senha alterada. Você pode chamar a função várias vezes e |
||||
ainda ter o mesmo resultado no final. |
||||
|
||||
Funções puras são úteis porque, principalmente, elas são fáceis de serem |
||||
testadas. |
||||
|
||||
Segundo, elas são fáceis de serem encadeadas num [fluxo de |
||||
dados](./fluxo-dedados.md): Como elas não tem estado interno (que é o |
||||
verdadeiro motivo de serem chamadas funções puras), você pode facilmente chamar |
||||
uma depois da outra e não importa quantas vezes você passe valores entre elas, |
||||
elas sempre produzem o mesmo resultado. E como cada função, dado a mesma |
||||
entrada, produz o mesmo resultado, encadeando todas elas _também_ gera o mesmo |
||||
resultado. |
||||
|
||||
Só esses dois conceitos podem fazer com que você tenha mais código (de novo, |
||||
você está criando um novo registro ao invés de simplesmente alterar apenas um |
||||
campo), mas o resultado final é que o seu código ficará mais robusto. |
||||
|
||||
[^1]: Com exceção de Haskell, mas ela requer que você envie uma semente toda |
||||
vez, fazendo com que você tenha valores baseados nessa semente, e assim a |
||||
função ainda é pura. |
||||
|
||||
<!-- |
||||
vim:spelllang=pt: |
||||
--> |
@ -0,0 +1,52 @@
|
||||
# Specs Antes, Código Depois |
||||
|
||||
"Sem requisitos ou design, programação é a arte de adicionar bugs em um |
||||
arquivo texto vazio." -- Louis Srygley |
||||
|
||||
Se você não sabe o que você está tentando resolver, você não vai saber o que |
||||
programar. |
||||
|
||||
Várias vezes nós temos essa sensação de "me deixa programar!" Mas sem entender |
||||
qual é o problema que tem que ser resolvido, você vai acabar escrevendo um |
||||
monte de coisas que não resolve nada -- ou, pelo menos, nada que _deveria_ ser |
||||
resolvido. |
||||
|
||||
Então fica a dica: Tente fazer uma especificação simples daquilo que você quer |
||||
resolver. Tenha em mente que mesmo com as especificações, você pode ter que |
||||
[jogar código fora](../programando/jogar-fora.md), porque o seu entendimento |
||||
do problema vai aumentar conforme o projeto avança. |
||||
|
||||
Sim, é um paradoxo: Você precisa saber o que escrever para saber o que |
||||
programar para evitar perder tempo resolvendo o problema errado, mas a |
||||
especificação pode estar errada, e aí você vai, _invariavelmente_, acabar |
||||
resolvendo o problema errado de qualquer forma. Então, qual o ponto de tudo |
||||
isso? O ponto é, a especificação reflete o seu entendimento do problema _num |
||||
determinado ponto_: Tudo que você (e o seu time) sabem está _lá_. |
||||
|
||||
Das vezes que eu passei mais tempo olhando para meu código, me perguntando o |
||||
que fazer na sequencia, foi quando nós não tínhamos o próximo passo definido: |
||||
Eram pontos faltantes para solução, ou nós não tínhamos as estruturas de |
||||
comunicação definidas, ou algo do tipo. Normalmente, quando isso acontecia, eu |
||||
fiquei brincando no Twitter ou no Mastodon ao invés de tentar resolver o |
||||
problema. Agora, quando você se pegar perguntando isso -- "Eu não sei o que |
||||
fazer agora, eu não sei se eu terminei de resolver o problema atual" -- então |
||||
talvez seja hora de parar um pouco e falar com outras pessoas para descobrir o |
||||
que fazer. |
||||
|
||||
Outro ponto sobre isso: Erik Deitrich escreveu um post sobre "Não Aprenda a |
||||
Programar - Aprenda a Automatizar" ([Don’t Learn to Code — Learn to |
||||
Automate](https://daedtech.com/dont-learn-to-code-learn-to-automate/)), que é |
||||
uma coisa que eu tenho que concordar porque a maior parte de nós, quando |
||||
estamos programado, pensamos "Eu preciso fazer isso, depois eu pego aquilo e |
||||
coloco lá, e de lá eu faço essa outra coisa". Basicamente, nós criamos |
||||
modelos de especificações na nossa mente, passo a passo, naquilo que nós |
||||
precisamos fazer -- basicamente, aquilo que precisamos automatizar. E, a |
||||
partir daí, tudo pode ficar até mais fácil, porque agora você pode pegar essa |
||||
especificação e fazer "Primeiro, eu como é que eu faço isso; Ok, entendi, |
||||
agora eu tenho que pegar o resultado daquilo e colocar lá" e assim por diante. |
||||
Você até tem um caminho para aprendizado, se você estiver iniciando a |
||||
programar. |
||||
|
||||
<!-- |
||||
vim:spelllang=pt: |
||||
--> |
@ -0,0 +1,33 @@
|
||||
# Pense Nos Usuários |
||||
|
||||
Pense em como os dados que você está coletando dos seus usuário será usado -- |
||||
isso é muito importante atualmente, onde "privacidade" é um serviço premium. |
||||
|
||||
Eu já tive uma discussão com um CTO sobre a coleta do número de IMEI na nossa |
||||
aplicação mobile. Basicamente, não tínhamos nenhum motivo para capturar essa |
||||
informação mas, como ele colocou na época, "Nós queremos saber se um usuário |
||||
usa dois telefones, ou se dois usuários usam o mesmo telefone" (e isso não |
||||
seria usado para melhorar o serviço em praticamente nada). Eu levantei o fato |
||||
de que não precisamos dessa informação e que sentia que basicamente estaríamos |
||||
invadindo a privacidade dos nossos usuários. E ainda assim, ele decidiu |
||||
continuar com a coleta. Minha resposta: "Ok, eu vou fazer, mas quero deixar |
||||
anotado que eu não estou feliz com essa solução". |
||||
|
||||
No final, a aplicação foi barrada no store... por estar capturando o IMEI. |
||||
|
||||
Mas há casos e casos. Se você realmente _realmente_ precisar capturar os dados |
||||
do usuário, tenha certeza que estes estão protegidos contra acessos indevidos, |
||||
seja por ações externas (alguém achou uma falha de segurança na sua aplicação) |
||||
ou internal (um funcionário infeliz resolveu levar os dados dos seus cliente |
||||
com ele). |
||||
|
||||
E tenha certeza, _haverá_ uma falha de segurança em algum ponto, é só uma |
||||
questão de tempo. Se você puder, a melhor forma de proteger os dados dos seus |
||||
usuários é nunca capturar dado algum. Quando for encontrada a falha de |
||||
segurança no seu sistema ou quando um colega sair da empresa de forma infeliz, |
||||
não haverão dados para serem expostos ao mundo, de qualquer forma. Não tem como |
||||
ser mais seguro que isso. |
||||
|
||||
<!-- |
||||
vim:spelllang=pt: |
||||
--> |
@ -0,0 +1 @@
|
||||
# Controle de Versões |
@ -0,0 +1 @@
|
||||
# Gerrit É Uma Cagada |
@ -0,0 +1 @@
|
||||
# Git-Flow É o Caminho |
@ -0,0 +1 @@
|
||||
# Sempre Use Um Controle de Versão |
@ -0,0 +1 @@
|
||||
# Um Commit Por Alteração |
@ -0,0 +1 @@
|
||||
# Documentando Seu Código |
@ -0,0 +1 @@
|
||||
# Se A Documentação de uma Função Tem "E", Está Errado |
@ -0,0 +1 @@
|
||||
# A Documentação de uma Função É o Seu Contrato |
@ -0,0 +1 @@
|
||||
# Documentação É Uma Carta de Amor Ao Seu Futuro Eu |
@ -0,0 +1 @@
|
||||
# Boas Linguagens Tem Documentação Embutida |
@ -0,0 +1,8 @@
|
||||
# Programação |
||||
|
||||
Eu sou desenvolvedor de software. Eu escrevo código. E aqui estão algumas das |
||||
coisas que eu aprendi sobre o assunto. |
||||
|
||||
<!-- |
||||
vim:spelllang=pt: |
||||
--> |
@ -0,0 +1 @@
|
||||
# Organização de Projetos |
@ -0,0 +1 @@
|
||||
# Crie Bibliotecas |
@ -0,0 +1 @@
|
||||
# Notas em Papel São Bem Úteis |
@ -0,0 +1 @@
|
||||
# Organize Seu Código por Tipo de Dado, Não Por Função |
@ -0,0 +1 @@
|
||||
# Escrevendo Código |
@ -0,0 +1 @@
|
||||
# Comece de Forma Idiota |
@ -0,0 +1 @@
|
||||
# É Melhor Deixar A Aplicação Explodir Do Que Fazer Nada |
@ -0,0 +1 @@
|
||||
# Resista À Tentação do Fácil |
@ -0,0 +1 @@
|
||||
# Não Mexa Em Coisas Fora do Seu Projeto |
@ -0,0 +1 @@
|
||||
# Esteja Pronto Para Jogar Código Fora |
@ -0,0 +1 @@
|
||||
# Se Você Sabe Como Lidar Com O Erro, Lide |
@ -0,0 +1 @@
|
||||
# Cuidado Com as Alterações de Interface |
@ -0,0 +1 @@
|
||||
# Otimização É Para Compiladores |
@ -0,0 +1 @@
|
||||
# Não Use Booleanos Como Parâmetros |
@ -0,0 +1 @@
|
||||
# Resolver O Futuro Gera Problemas Futuros |
@ -0,0 +1 @@
|
||||
# Se Não Roda No Seu Computador, Está Errado |
@ -0,0 +1 @@
|
||||
# Nada Mais Permanente Que Uma Solução Temporária |
@ -0,0 +1 @@
|
||||
# Tipos Dizem O Que Seus Dados São |
@ -0,0 +1 @@
|
||||
# Unidades Fazem as Coisas Mais Claras |
@ -0,0 +1 @@
|
||||
# Se Os Seus Dados Tem Estrutura, Use Uma Estrutura |
@ -0,0 +1 @@
|
||||
# Sempre Use Timezones nas Datas |
@ -0,0 +1 @@
|
||||
# Sempre Use UTF-8 nas Strings |
@ -0,0 +1 @@
|
||||
# Fazendo As Coisas Andarem |
@ -0,0 +1 @@
|
||||
# Uma Versão para Adicionar, Uma Para Remover |
@ -0,0 +1 @@
|
||||
# O Arquivo de Config É Seu Amigo |
@ -0,0 +1 @@
|
||||
# Mesmo Para Composição de Aplicações, Comece Idiota |
@ -0,0 +1 @@
|
||||
# Logs São Para Eventos, Não Interface Com o Usuário |
@ -0,0 +1 @@
|
||||
# Aprenda a Monitorar |
@ -0,0 +1 @@
|
||||
# Opção de Linha de Comando São Esquisitas Mas Úteis |
@ -0,0 +1 @@
|
||||
# Seja Transparente Com o Usuário |
@ -0,0 +1 @@
|
||||
# Boas Linguagens Tem Testes Embutidos |
@ -0,0 +1 @@
|
||||
# Testes Geram Uma API Melhor |
@ -0,0 +1 @@
|
||||
# Testar Toda Função Gera Código Morto |
@ -0,0 +1 @@
|
||||
# Testes Unitários São Bons, Testes de Integração São Mais Melhores |
@ -0,0 +1 @@
|
||||
# Crie Testes Que Você Saiba Rodar Na Linha de Comando |
@ -0,0 +1 @@
|
||||
# Não Apenas Composição de Funções, Mas Composição de Aplicações |
@ -0,0 +1 @@
|
||||
# "A Ferramenta Certa" É Mais Óbvia Do Que Você Pensa |
@ -0,0 +1 @@
|
||||
# "A Ferramenta Certa" Tem Sempre Algo Por Trás |
@ -0,0 +1 @@
|
||||
# Entenda e Afaste-se do "Cargo Cult" |
@ -0,0 +1 @@
|
||||
# Alterações Globais Devem Ser Discutidas com o Time |
@ -0,0 +1 @@
|
||||
# ... A Não Ser Que Seja o Estilo Google |
@ -0,0 +1 @@
|
||||
# Estilo de Código: Siga-o! |
@ -0,0 +1 @@
|
||||
# Revisão de Código Não É Para Validar Estilo |
@ -0,0 +1 @@
|
||||
# Formatadores de Código São Ok, Mas Nenhuma Bala de Prata |
@ -0,0 +1 @@
|
||||
# Hero Projects: Você Vai Ter Que Fazer |
@ -0,0 +1 @@
|
||||
# Uma Linguagem É Mais Que Uma Linguagem |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue