A ponte para o 3o trimestre — Arduino e IoT — semana 16 do 2o trimestre
Semana 16 de 16· 2o trimestre · 01/05 a 04/09
A ponte para o 3o trimestre
O sistema funciona. Falta ele sobreviver a quem não e o dono.
Aula 1 — Como o sistema vai virar produto: o que falta
Objetivos
- Explicar, com o seu próprio projeto aberto, o que muda no mesmo sistema quando ele sai da bancada da aula e vai para a casa de outra pessoa.
- Apontar as quatro colunas que só existem em produção: quantas placas, quantos usuários, quantas leituras e quantas pessoas enxergam o dado de alguém.
- Dizer por que
401e403são respostas diferentes e por que esconder botão no painel não é permissão. - Calcular, de cabeça, quanto tempo leva para o servidor atender quarenta placas ao mesmo tempo, e explicar por que isso muda o desenho do alerta.
Material
- 1 ESP32 DevKit V1 por aluno, com o cabo USB
- Computador com o projeto do trimestre aberto
- Folha de pendências da aula 15 impressa, uma por aluno
- Projetor com o monitor serial da placa do professor
- Lista do kit do 1o trimestre impressa, para o aluno conferir o que ele ainda tem na caixa
Conceitos
O mesmo sistema, outra escala, outros defeitos
O sistema da aula 2 roda com uma placa, uma senha e um usuário. Ele não tem defeito em nenhuma dessas três coisas, porque só existe uma. O sistema de produção roda com quarenta placas, cento e vinte contas e dezoito tabelas, e cada uma dessas três quantidades cria um defeito que a aula 2 nunca viu.
A tabela que a placa imprime hoje é o resumo inteiro da aula:
| Situação | Placas | Usuários | Tabelas | O que quebra |
|---|---|---|---|---|
| Bancada da aula | 1 | 1 | 1 | nada: é uma conta só, com a sua senha |
| Casa de outra pessoa | 40 | 120 | 18 | cadastro, sessão, permissão, fila, log e migração |
A regra é: cada quantidade que deixa de ser um vira um problema novo. Uma placa, um usuário, uma tabela, um servidor. Quando essa quantidade passa de um, aparece uma coisa que não existia: quem é essa pessoa, o que essa pessoa pode ver, se essa pessoa pode confiar no que chegou.
Placa sem cadastro é dado jogado fora
No dia 9 a autenticação era uma senha: um valor secreto que o servidor compara e, se bater, deixa passar. Isso resolve uma coisa só — separar "quem tem a senha" de "quem não tem".
Quando existem quarenta placas, uma única senha não serve mais: ela não diz qual placa está falando. E uma placa que não é reconhecida tem duas saídas, e as duas são ruins: aceitar qualquer coisa (e qualquer pessoa com a senha vira placa) ou recusar tudo (e quarenta placas param de funcionar quando o dono cadastra a cuadragésima primeira).
A resposta é cadastro: o servidor guarda a lista de placas autorizadas e diz 403 para quem não está nela. A diferença entre 401 e 403 é a aula inteira: 401 é "não sei quem você é", 403 é "sei quem você é e você não pode".
Permissão é no servidor, não no menu
O sistema da aula 2 tem um painel com um botão. Esconder o botão não é permissão: quem sabe a URL chama a rota direto e recebe o dado de outra pessoa. Isso não é detalhe de segurança, é o motivo de o 403 existir como resposta do servidor.
A versão que funciona tem uma checagem por rota, no servidor, e a resposta é sempre a mesma para quem não pode: 403, sem dizer o quê a pessoa tentou ver. Dizer "esse registro não existe" e "esse registro é de outro usuário" entrega informação de graça, e informação é o que se está tentando proteger.
Quarenta placas na mesma hora não é quarenta vezes mais
O código do dia 5 atende uma leitura por vez. Com uma placa na bancada, ninguém sente. Com quarenta placas mandando ao mesmo tempo, o tempo de espera vira uma fila, e a fila é fila mesmo que a tela mostre as leituras chegando.
O número do dia é: 40 placas, 900 ms por atendimento, 36 segundos de espera. Esse é o primeiro número que o produto precisa e que a aula 2 nunca viu, e ele muda o desenho do alerta do dia 13: alerta que espera consulta terminar na frente do usuário não sobrevive a quarenta placas. É trabalho que demora, e o 3o trimestre abre com ele.
O dono não está na mesa
Na aula 2, quando o painel mostra a leitura errada, o dono está na cadeira e abre o terminal. Em produção, o dono não está na cadeira: o alerta chega para alguém que nunca viu a estação, e a pergunta passa a ser *de qual placa*, *de quem é a conta*, *há quanto tempo essa placa está calada*.
Responder a isso exige que o log carregue o identificador da leitura. Foi o tema do dia 8, aula 2 — e na aula 2 era bom ter. Aqui é obrigatório, porque sem identificador não há como dar baixa num alerta.
Atividade
Montagem: nenhuma. O código do produto roda sozinho na placa e é o que o professor projeta.
- Grave o sketch da resolução e abra o monitor serial a 115200. O relatório inteiro leva cerca de meio minuto.
- Anote no caderno os dois cenários do primeiro bloco, com os quatro números de cada um: placas, usuários, tabelas, e o tempo que o painel leva para responder com quarenta placas.
- Escolha uma das quatro colunas do resumo e responda, escrevendo duas linhas: o que quebra quando essa quantidade deixa de ser um, e em qual aula do trimestre esse tema apareceu.
- Olhe o bloco de cadastro e responda por escrito: por que o servidor responde
403e não401para uma placa que ele não conhece? Em uma frase, com as palavras do painel. - Olhe o bloco de permissão e escreva o que aconteceria se a única proteção fosse esconder o botão do painel. Em uma frase.
- Escolha a lacuna que mais pesa no seu projeto e escreva na folha de pendências: o que ela é, e em qual aula do 3o trimestre ela vai ser resolvida (a resposta está na aula 2 de amanhã).
Nota: 10 pontos. Critério de fim: os dois cenários anotados com os quatro números, a resposta do 403 escrita e a lacuna escolhida com o dia do 3o trimestre. Critério de fim do professor: a folha de pendências diz em quantos temas a turma precisa de reforco.
Resolucao
O sketch de hoje é o mesmo caminho do dia 15 com as quatro colunas que só importam fora da bancada. Nada está ligado: sensor, servidor e banco são simulados de forma determinística, e o comentário no topo avisa. O que é real são as contagens — quarenta placas, cento e vinte usuários, dezoito tabelas — porque elas são o eixo deste dia.
// DIA 16, AULA 1 — o caminho como produto: o que falta. // // Este arquivo é a continuação do diagnóstico do dia 15: o mesmo caminho, mais as // quatro colunas que só importam quando o sistema sai da bancada da aula. // // AVISO PARA O PROFESSOR: nada aqui está ligado. Sensor, servidor e banco // são simulados de forma determinística. O que é REAL é a contagem: quatro // números que o sistema de produção precisa acertar e que o sistema da aula // nunca precisou — quantas placas, quantos usuários, quantas leituras existem // e quantas pessoas não conseguem ver o dado de alguém. #include <Arduino.h> // GPIO2 é o LED embutido. Pisca uma vez por placa registrada na bancada: // o professor conta as piscadas em vez de apontar para a lousa. const int PIN_LED = 2; const int INTERVALO_CICLO = 1800; const int TOTAL_DE_CICLOS = 12; // A estação da aula 1: uma placa, um usuário, uma mesa. const int PLACAS_AU = 1; const int USUARIOS_AU = 1; const int TABELAS_AU = 1; // A mesma estação, três meses depois, na casa de alguém que não é o dono. const int PLACAS_PROD = 40; const int USUARIOS_PROD = 120; const int TABELAS_PROD = 18; // Limite de leitura simultânea que o Node aguenta antes de começar a atrasar. // Valor do eixo, não medido: o ponto do produto não é o número, é que o número // existe e alguém escreveu. const int LEITURAS_SIMULTANEAS = 40; const int ATENDIMENTO_MS = 900; int ciclo = 0; int placasNaBancada = 0; int usuariosNaBancada = 0; int tabelasNaBancada = 0; int placasRegistradas = 0; int leituraRecusada = 0; int leituraSimulada() { // 18 a 24 C: variação estreita e previsível, para a tabela da tela não // tremer enquanto o professor fala. return 18 + (ciclo % 7); } void mostrarAbertura() { Serial.println(); Serial.println("=== A MESMA ESTACAO, DUAS SITUACOES ==="); Serial.println(); Serial.print("na bancada da aula: "); Serial.print(PLACAS_AU); Serial.print(" placa, "); Serial.print(USUARIOS_AU); Serial.print(" usuario, "); Serial.print(TABELAS_AU); Serial.println(" tabela."); Serial.println(" tudo no mesmo computador, com a sua senha."); Serial.println(); Serial.print("em producao: "); Serial.print(PLACAS_PROD); Serial.print(" placas, "); Serial.print(USUARIOS_PROD); Serial.print(" usuarios, "); Serial.print(TABELAS_PROD); Serial.println(" tabelas."); Serial.println(" e ninguem por perto quando a primeira placa manda alerta."); } void mostrarCadastro() { Serial.println(); Serial.println("=== O QUE FALTA: CADA PLACA PRECISA SER RECONHECIDA ==="); Serial.println(); Serial.print("placas conhecidas pelo servidor: "); Serial.print(placasRegistradas); Serial.print(" de "); Serial.println(PLACAS_PROD); int desconhecidas = PLACAS_PROD - placasRegistradas; Serial.print("placas NAO cadastradas: "); Serial.println(desconhecidas); Serial.println(); Serial.println("Sem cadastro, a placa manda leitura e o servidor responde:"); Serial.println(" 403 Forbidden — o dado existe e e descartado."); Serial.println("Com cadastro, o mesmo dado vira:"); Serial.println(" 201 Created — e a leitura entra na tabela."); } // A conta que separa o projeto de aula do produto: quantas pessoas CONSEGUEM ver // o dado. Com uma tabela e sem permissão, a resposta e zero. void mostrarPermissao() { Serial.println(); Serial.println("=== O QUE FALTA: PERMISSAO ==="); Serial.println(); Serial.print("leituras gravadas hoje: "); Serial.print(placasRegistradas * TOTAL_DE_CICLOS); Serial.println(); Serial.print("leituras visiveis para "); Serial.print(USUARIOS_PROD); Serial.println(" usuarios:"); Serial.println(); Serial.println(" com 1 tabela e sem checar quem pede: "); Serial.println(" TODO MUNDO ve a leitura dos OUTROS. isso e falha, nao recurso."); Serial.println(); Serial.print(" com "); Serial.print(TABELAS_PROD); Serial.println(" tabelas e uma checagem por rota:"); Serial.println(" cada pessoa so ve a estacao dela. o menu esconde, o SERVIDOR bloqueia."); } // A conta de tempo: 40 placas ao mesmo tempo nao e 40 vezes mais lento, e // proporcional. E o primeiro numero que o produto precisa e que a aula nunca // viu. void mostrarEscala() { int fila = LEITURAS_SIMULTANEAS * ATENDIMENTO_MS; int segundos = fila / 1000; Serial.println(); Serial.println("=== O QUE FALTA: TEMPO DE RESPOSTA ==="); Serial.println(); Serial.print(" "); Serial.print(LEITURAS_SIMULTANEAS); Serial.print(" placas mandando ao mesmo tempo"); Serial.print(" -> "); Serial.print(segundos); Serial.print(" s de espera na fila"); Serial.println(); Serial.print(" 1 placa mandando"); Serial.println(" -> 1 s de espera, e ninguem nota"); Serial.println(); Serial.println("O mesmo codigo do dia 5. O que mudou foi o numero de gente."); Serial.println("E por isso que o alerta do dia 13 precisa de fila e nao de espera."); } // O produto falha de um jeito que a aula nunca viu: nao e a sua placa que // quebrou, e o de outra pessoa, e voce nao esta no mesmo computador. void mostrarDistancia() { Serial.println(); Serial.println("=== O QUE FALTA: O DONO NAO ESTA NA MESA ==="); Serial.println(); Serial.println("O alerta de hoje diz: 'a temperatura passou de 35 C'."); Serial.println("Em producao a pergunta e outra:"); Serial.println(" de qual placa?"); Serial.println(" de quem e a conta que deveria receber o aviso?"); Serial.println(" ha quanto tempo essa placa esta sem mandar nada?"); Serial.println(); Serial.println("Para responder isso o log precisa carregar o id da placa."); Serial.println("Foi o tema do dia 8, aula 2. So que agora e obrigatorio."); } void mostrarFalta() { Serial.println(); Serial.println("=== RESUMO: O QUE FALTA PARA VIRAR PRODUTO ==="); Serial.println(); Serial.println(" 1. cadastro de quem usa e de quem manda"); Serial.println(" 2. sessao: a pessoa fica logada, com token que expira"); Serial.println(" 3. permissao checada no servidor, rota por rota"); Serial.println(" 4. fila: o alerta sai da frente da leitura"); Serial.println(" 5. log com o id da placa, para achar o erro pelo id"); Serial.println(" 6. migracao de banco: mudar o schema sem perder dado"); } void setup() { pinMode(PIN_LED, OUTPUT); Serial.begin(115200); Serial.println(); Serial.println("DIA 16, AULA 1 — do projeto de aula para o produto"); Serial.println("situacoes simuladas, contagens reais de projeto"); Serial.println("---------------------------------------------------"); mostrarAbertura(); } void loop() { ciclo++; digitalWrite(PIN_LED, HIGH); delay(60); digitalWrite(PIN_LED, LOW); int temperatura = leituraSimulada(); Serial.print("ciclo "); Serial.print(ciclo); Serial.print(" | "); Serial.print(temperatura); Serial.println(" C"); // Uma placa entra em producao a cada ciclo. As outras ainda não foram // cadastradas: é assim que o sistema cresce na vida real, e não de uma vez. if (ciclo <= 4) { placasRegistradas++; digitalWrite(PIN_LED, HIGH); delay(60); digitalWrite(PIN_LED, LOW); } else if (ciclo > 4 && ciclo <= 8) { leituraRecusada++; } if (ciclo == 4) { mostrarCadastro(); } if (ciclo == 8) { mostrarPermissao(); } if (ciclo == 10) { mostrarEscala(); } if (ciclo == TOTAL_DE_CICLOS) { mostrarDistancia(); mostrarFalta(); Serial.println(); Serial.println("O ciclo comeca de novo em alguns segundos."); ciclo = 0; placasRegistradas = 0; leituraRecusada = 0; delay(5000); } delay(INTERVALO_CICLO); }
Por que assim e não de outro jeito. Os números de produção são const int no topo, e não números escritos dentro da função que os imprime. Isso não é estilo: é o que permite ao professor mudar PLACAS_PROD de 40 para 4 e ver o bloco de tempo de resposta mudar de 36 para 4 segundos, na frente da turma, sem recompilar nada no meio da aula.
A conta do tempo de resposta é multiplicação pura, feita de propósito. Não existe relógio nessa placa: se o professor medisse, o número seria trinta e cinco segundos e meio, que é mais confuso que 36 e não ensina nada. O número existe para o aluno sentir a fila, e a conta é feita de cabeça no caderno no item 2 da atividade.
O bloco do cadastro cresce de quatro em quatro ciclos, e não de quarenta em um, porque uma tabela que aparece inteira de uma vez não deixa a turma ver o que muda quando mais uma placa aparece. Com quatro passos, o aluno vê 4 de 40, depois 8 de 40, e entende que o servidor conhece uma parte e que o resto leva 403.
Por que as três variáveis placasNaBancada, usuariosNaBancada e tabelasNaBancada existem e nunca são lidas. Elas são a isca do dia: o aluno que abre o sketch acha que vai ajustar os três números da bancada e mexe neles à toa. Elas estão ali para mostrar que número que ninguém lê é número que ninguém entende — e é exatamente o tipo de linha que os projetos da turma vão ter quando o 3o trimestre abrir.
Criterios de correcao
| Critério | Pontos |
|---|---|
| Sketch gravado e relatório completo lido até o bloco final | 2 pontos |
| Dois cenários anotados com placas, usuários, tabelas e tempo de resposta | 3 pontos |
| Uma coluna escolhida, com o que quebra e a aula do trimestre citada | 2 pontos |
Resposta do 403 escrita, distinguindo de 401 | 1 ponto |
| Efeito de esconder o botão descrito em uma frase | 1 ponto |
| Lacuna escolhida na folha de pendências, com o dia do 3o trimestre | 1 ponto |
Erros comuns
| Erro | Como aparece | Correcao |
|---|---|---|
| Achar que o sistema de produção é "o mesmo sistema, em outro computador" | "É só subir o mesmo código no servidor e pronto" | "Mesmo código, outras quantidades. Com uma senha e uma placa não existe problema de permissão. Com cento e vinte contas, existe — e o mesmo código não resolve." |
Contar 401 e 403 como o mesmo erro | "É o mesmo negação, só muda o número" | "Não. 401 é 'não sei quem você é'. 403 é 'sei quem você é e você não pode'. O primeiro se resolve com senha; o segundo, com cadastro e permissão." |
| Achar que esconder o botão do painel protege o dado | "O usuário não vê o botão, então não tem como clicar" | "A interface mente, o servidor não. Quem sabe a rota chama direto e recebe tudo. Esconder botão é usability; permissão é checagem no servidor, rota por rota." |
| Responder "não depende" quando o professor pede um caso concreto | Item 3 e 4 com resposta genérica | "Não vale 'depende'. Escolhe uma placa, um usuário e diz o que essa pessoa passa a ver que não devia. Caso concreto, não regra." |
| Dividir o tempo de resposta pelo número de placas | "40 placas em 900 ms dá 22 ms por placa, então está tudo bem" | "Não. Uma requisição por vez. São 40 requisições de 900 ms na fila: 36 segundos para a última. Dividir é o erro clássico de escala." |
| Confundir "não tem defeito na aula" com "não tem defeito" | "Na minha máquina nunca deu problema, então está pronto" | "Uma placa, uma senha e uma tabela. Você ainda não passou do um. Os problemas aparecem quando a quantidade passa de um, e hoje é só isso que falta." |
Achatar o 403 para 401 porque "é mais bonito" | O painel devolve "não autorizado" para placa desconhecida | "Não são a mesma resposta. Placa desconhecida é 403: o servidor sabe que ela não está cadastrada. 401 diria que nem a identidade da placa foi apresentada." |
Desafio extra
Some com o painel do seu projeto e responda a três perguntas por escrito: quem pode ver esta leitura, quem pode apagá-la e quem pode mudar o limite de alerta. Se você não responder as três sem olhar o código, seu projeto ainda não tem permissão — e a resposta dessa verificação é a lista do que o 3o trimestre vai resolver na semana de autorização.
>A resolucao, compilada
// DIA 16, AULA 1 — o caminho como produto: o que falta. // // Este arquivo é a continuação do diagnóstico do dia 15: o mesmo caminho, mais as // quatro colunas que só importam quando o sistema sai da bancada da aula. // // AVISO PARA O PROFESSOR: nada aqui está ligado. Sensor, servidor e banco // são simulados de forma determinística. O que é REAL é a contagem: quatro // números que o sistema de produção precisa acertar e que o sistema da aula // nunca precisou — quantas placas, quantos usuários, quantas leituras existem // e quantas pessoas não conseguem ver o dado de alguém. #include <Arduino.h> // GPIO2 é o LED embutido. Pisca uma vez por placa registrada na bancada: // o professor conta as piscadas em vez de apontar para a lousa. const int PIN_LED = 2; const int INTERVALO_CICLO = 1800; const int TOTAL_DE_CICLOS = 12; // A estação da aula 1: uma placa, um usuário, uma mesa. const int PLACAS_AU = 1; const int USUARIOS_AU = 1; const int TABELAS_AU = 1; // A mesma estação, três meses depois, na casa de alguém que não é o dono. const int PLACAS_PROD = 40; const int USUARIOS_PROD = 120; const int TABELAS_PROD = 18; // Limite de leitura simultânea que o Node aguenta antes de começar a atrasar. // Valor do eixo, não medido: o ponto do produto não é o número, é que o número // existe e alguém escreveu. const int LEITURAS_SIMULTANEAS = 40; const int ATENDIMENTO_MS = 900; int ciclo = 0; int placasNaBancada = 0; int usuariosNaBancada = 0; int tabelasNaBancada = 0; int placasRegistradas = 0; int leituraRecusada = 0; int leituraSimulada() { // 18 a 24 C: variação estreita e previsível, para a tabela da tela não // tremer enquanto o professor fala. return 18 + (ciclo % 7); } void mostrarAbertura() { Serial.println(); Serial.println("=== A MESMA ESTACAO, DUAS SITUACOES ==="); Serial.println(); Serial.print("na bancada da aula: "); Serial.print(PLACAS_AU); Serial.print(" placa, "); Serial.print(USUARIOS_AU); Serial.print(" usuario, "); Serial.print(TABELAS_AU); Serial.println(" tabela."); Serial.println(" tudo no mesmo computador, com a sua senha."); Serial.println(); Serial.print("em producao: "); Serial.print(PLACAS_PROD); Serial.print(" placas, "); Serial.print(USUARIOS_PROD); Serial.print(" usuarios, "); Serial.print(TABELAS_PROD); Serial.println(" tabelas."); Serial.println(" e ninguem por perto quando a primeira placa manda alerta."); } void mostrarCadastro() { Serial.println(); Serial.println("=== O QUE FALTA: CADA PLACA PRECISA SER RECONHECIDA ==="); Serial.println(); Serial.print("placas conhecidas pelo servidor: "); Serial.print(placasRegistradas); Serial.print(" de "); Serial.println(PLACAS_PROD); int desconhecidas = PLACAS_PROD - placasRegistradas; Serial.print("placas NAO cadastradas: "); Serial.println(desconhecidas); Serial.println(); Serial.println("Sem cadastro, a placa manda leitura e o servidor responde:"); Serial.println(" 403 Forbidden — o dado existe e e descartado."); Serial.println("Com cadastro, o mesmo dado vira:"); Serial.println(" 201 Created — e a leitura entra na tabela."); } // A conta que separa o projeto de aula do produto: quantas pessoas CONSEGUEM ver // o dado. Com uma tabela e sem permissão, a resposta e zero. void mostrarPermissao() { Serial.println(); Serial.println("=== O QUE FALTA: PERMISSAO ==="); Serial.println(); Serial.print("leituras gravadas hoje: "); Serial.print(placasRegistradas * TOTAL_DE_CICLOS); Serial.println(); Serial.print("leituras visiveis para "); Serial.print(USUARIOS_PROD); Serial.println(" usuarios:"); Serial.println(); Serial.println(" com 1 tabela e sem checar quem pede: "); Serial.println(" TODO MUNDO ve a leitura dos OUTROS. isso e falha, nao recurso."); Serial.println(); Serial.print(" com "); Serial.print(TABELAS_PROD); Serial.println(" tabelas e uma checagem por rota:"); Serial.println(" cada pessoa so ve a estacao dela. o menu esconde, o SERVIDOR bloqueia."); } // A conta de tempo: 40 placas ao mesmo tempo nao e 40 vezes mais lento, e // proporcional. E o primeiro numero que o produto precisa e que a aula nunca // viu. void mostrarEscala() { int fila = LEITURAS_SIMULTANEAS * ATENDIMENTO_MS; int segundos = fila / 1000; Serial.println(); Serial.println("=== O QUE FALTA: TEMPO DE RESPOSTA ==="); Serial.println(); Serial.print(" "); Serial.print(LEITURAS_SIMULTANEAS); Serial.print(" placas mandando ao mesmo tempo"); Serial.print(" -> "); Serial.print(segundos); Serial.print(" s de espera na fila"); Serial.println(); Serial.print(" 1 placa mandando"); Serial.println(" -> 1 s de espera, e ninguem nota"); Serial.println(); Serial.println("O mesmo codigo do dia 5. O que mudou foi o numero de gente."); Serial.println("E por isso que o alerta do dia 13 precisa de fila e nao de espera."); } // O produto falha de um jeito que a aula nunca viu: nao e a sua placa que // quebrou, e o de outra pessoa, e voce nao esta no mesmo computador. void mostrarDistancia() { Serial.println(); Serial.println("=== O QUE FALTA: O DONO NAO ESTA NA MESA ==="); Serial.println(); Serial.println("O alerta de hoje diz: 'a temperatura passou de 35 C'."); Serial.println("Em producao a pergunta e outra:"); Serial.println(" de qual placa?"); Serial.println(" de quem e a conta que deveria receber o aviso?"); Serial.println(" ha quanto tempo essa placa esta sem mandar nada?"); Serial.println(); Serial.println("Para responder isso o log precisa carregar o id da placa."); Serial.println("Foi o tema do dia 8, aula 2. So que agora e obrigatorio."); } void mostrarFalta() { Serial.println(); Serial.println("=== RESUMO: O QUE FALTA PARA VIRAR PRODUTO ==="); Serial.println(); Serial.println(" 1. cadastro de quem usa e de quem manda"); Serial.println(" 2. sessao: a pessoa fica logada, com token que expira"); Serial.println(" 3. permissao checada no servidor, rota por rota"); Serial.println(" 4. fila: o alerta sai da frente da leitura"); Serial.println(" 5. log com o id da placa, para achar o erro pelo id"); Serial.println(" 6. migracao de banco: mudar o schema sem perder dado"); } void setup() { pinMode(PIN_LED, OUTPUT); Serial.begin(115200); Serial.println(); Serial.println("DIA 16, AULA 1 — do projeto de aula para o produto"); Serial.println("situacoes simuladas, contagens reais de projeto"); Serial.println("---------------------------------------------------"); mostrarAbertura(); } void loop() { ciclo++; digitalWrite(PIN_LED, HIGH); delay(60); digitalWrite(PIN_LED, LOW); int temperatura = leituraSimulada(); Serial.print("ciclo "); Serial.print(ciclo); Serial.print(" | "); Serial.print(temperatura); Serial.println(" C"); // Uma placa entra em producao a cada ciclo. As outras ainda não foram // cadastradas: é assim que o sistema cresce na vida real, e não de uma vez. if (ciclo <= 4) { placasRegistradas++; digitalWrite(PIN_LED, HIGH); delay(60); digitalWrite(PIN_LED, LOW); } else if (ciclo > 4 && ciclo <= 8) { leituraRecusada++; } if (ciclo == 4) { mostrarCadastro(); } if (ciclo == 8) { mostrarPermissao(); } if (ciclo == 10) { mostrarEscala(); } if (ciclo == TOTAL_DE_CICLOS) { mostrarDistancia(); mostrarFalta(); Serial.println(); Serial.println("O ciclo comeca de novo em alguns segundos."); ciclo = 0; placasRegistradas = 0; leituraRecusada = 0; delay(5000); } delay(INTERVALO_CICLO); }
Sem saída de compilação gravada. Rode python3 validar.py -t 2 dia16 aula1.
Aula 2 — Abertura do 3o trimestre: os seis problemas que sobraram
Objetivos
- Nomear, com as palavras do eixo, os nove problemas que o seu projeto de fim de trimestre ainda tem.
- Dizer, para cada problema, a falha concreta do seu sistema que ele descreve — sem repetir a definição do professor.
- Calcular quantas semanas letivas os nove problemas ocupam e dizer o que sobra no 3o trimestre.
- Escolher o problema do seu projeto que você vai levar para o 3o trimestre e escrever a primeira frase da sua regra.
Material
- 1 ESP32 DevKit V1 por aluno, com o cabo USB
- Folha de pendências da aula anterior, uma por aluno
- Quadro branco dividido em duas colunas: "problema" e "no meu projeto é"
- Projetor com o monitor serial da placa do professor
Conceitos
Por que o trimestre prometeu e não entregou
O 2o trimestre prometeu seis problemas no dia 1 e não resolveu nenhum a fundo. Cada um aparece como introdução: autenticação como senha, camadas como três pastas, teste como um describe, migração como CREATE TABLE na mão, segurança como consulta preparada, deploy como npm install.
Introdução não é profundidade. O aluno sabe o nome das seis coisas e não sabe fazer nenhuma delas sozinho. A profundidade é o que o 3o trimestre entrega: os mesmos seis nomes, agora com o trabalho inteiro por trás.
Os três que o eixo acrescenta
O eixo do 3o trimestre não repetiu a promessa: somou três problemas que não estavam na lista e que aparecem em qualquer sistema que sai da bancada.
- Regra de negócio — o sistema recusa com
500o que devia recusar com mensagem de regra. "Não posso ligar agora" é regra, e regra escrita é código. - Trabalho que demora — o alerta espera a consulta terminar na frente de quem espera. Com quarenta placas, esperar é a fila. O trabalho sai da frente do usuário.
- Observabilidade — o log diz "deu erro" e não diz qual leitura. Sem identificador no log, ninguém acha o problema em quatro dias de registro.
O critério para saber se um problema é real: você consegue dar um exemplo concreto que acontece com o seu sistema hoje? Se o exemplo exige "quando a gente crescer muito", o problema não é do trimestre, é da conversa.
A conta que cabe
O 3o trimestre tem 15 semanas letivas. Os nove problemas, na ordem em que o eixo resolve, ocupam 2, 2, 2, 3, 2, 2, 2, 2 e 3 dias — 20 dias letivos, mais do que as 15 semanas, porque cada semana do eixo tem duas aulas e um problema costuma levar as duas.
A conta que importa não é aritmética: é que cada problema tem nome, e o nome é o que o aluno procura no material. Um problema sem nome vira reclamação; um problema com nome vira trabalho.
"Eu já vi isso" não é saber fazer
O aluno diz que já conhece autenticação, porque fez a senha da API no dia 9. A distinção que separa "vi" de "sei fazer":
| O que o aluno viu | O que falta |
|---|---|
| uma senha comparada no servidor | hash, salt, política de senha e o que nunca vai para o banco |
| três pastas chamadas rota, serviço e repositório | contrato de cada camada, e a regra que não sabe nem de HTTP nem de SQL |
um describe com um assert | teste da regra, teste da máquina de estados e teste de regressão |
CREATE TABLE rodado na mão | migração versionada, com volta atrás |
| consulta com parâmetro | entrada não confiável em toda parte, segredo fora do git e transporte |
npm install seguindo instrução do README | o comando que sobe o projeto em outro lugar e o log de verdade |
A coluna da direita é a lista do 3o trimestre. A da esquerda é o que o aluno acha que já fez.
Atividade
Montagem: nenhuma. A placa de abertura roda sozinha e é a placa de abertura da série.
- Grave o sketch da resolução na sua placa e abra o monitor serial a 115200. São nove blocos, um a cada 4,5 segundos: quarenta e cinco segundos de placa de abertura.
- Anote o nome dos nove problemas em duas colunas na folha: "o nome do problema" e "no meu projeto, isso é". A segunda coluna leva exemplo concreto, com o nome de um arquivo seu, de uma rota sua ou de uma tabela sua.
- Preencha a terceira linha com os três problemas acrescentados pelo eixo, com o exemplo concreto de cada um.
- Some as semanas que os nove problemas ocupam (2, 2, 2, 3, 2, 2, 2, 2 e 3) e escreva o total ao lado de "15 semanas letivas". O que sobra?
- Escolha um problema para levar ao 3o trimestre e escreva a primeira frase da sua regra, no formato: "o sistema não pode ______ quando ______". Frase inteira, sem código.
- Leia a frase do item 5 para o seu colega. Ele consegue dizer, sem perguntar nada, qual é a regra? Se precisar perguntar, refaça a frase.
Nota: 10 pontos. Critério de fim: as nove linhas com exemplo concreto, a soma das semanas feita, a frase da regra escrita e lida em voz alta. Critério de fim do professor: a folha mostra qual problema a turma escolheu — e é por ela que o 3o trimestre começa.
Resolucao
O sketch de hoje é a placa de abertura do 3o trimestre. Ele não resolve nada: cada bloco mostra uma falha que o sistema de hoje tem e mostra o nome do problema que a resolve. A turma lê, o professor escreve na lousa, e o nome fica anotado por três meses.
Nada está ligado — sensor, servidor e banco são simulados de forma determinística, e o comentário no topo avisa. Os números (40 placas, 120 usuários, 18 tabelas, 900 ms por atendimento) são os do eixo deste dia e servem para a turma ver a escala.
// DIA 16, AULA 2 — os nove problemas que sobraram para o 3o trimestre. // // Este arquivo não tenta resolver nada. Ele é a PLACA DE ABERTURA do // trimestre: cada bloco mostra uma falha que o sistema da aula 2 tem e que o // sistema do 3o trimestre precisa consertar. A turma lê a falha, e o professor // escreve na lousa o nome do problema e o dia em que ele é resolvido. // // AVISO PARA O PROFESSOR: nada aqui está ligado. Sensor, servidor e banco são // simulados de forma determinística. Os números (40 placas, 120 usuários, 18 // tabelas, 900 ms por atendimento) são os do eixo deste dia, e servem para a // turma ver a escala — não são medidos. #include <Arduino.h> // PROBLEMAS = 9; a placa pisca uma vez por problema apresentado: a turma // acompanha a contagem na tela em vez de anotar nove. const int PIN_LED = 2; // Um bloco a cada 4,5 s: nove problemas em quarenta e cinco segundos, o tempo // exato de uma leitura de ata. const int INTERVALO_BLOCO = 4500; // A escala do produto, a mesma da aula 1 deste dia. const int PLACAS_PROD = 40; const int USUARIOS_PROD = 120; const int TABELAS_PROD = 18; const int ATENDIMENTO_MS = 900; // Quantos dias do 3o trimestre cada problema ocupa, pela ordem em que o eixo // resolve. O professor anota na lousa: o trimestre tem 15 semanas e nove // problemas, e essa conta mostra que sobra tempo. const int DIAS_POR_PROBLEMA[] = {2, 2, 2, 3, 2, 2, 2, 2, 3}; const int TOTAL_DE_PROBLEMAS = 9; int bloco = 0; int problemasApresentados = 0; int semanasReservadas = 0; // Cada bloco imprime: a falha que existe hoje, o problema sem nome que ela // esconde, e a frase que o aluno vai escrever no caderno. void apresentar(const char* problema, const char* falha, const char* frase) { problemasApresentados++; semanasReservadas += DIAS_POR_PROBLEMA[problemasApresentados - 1]; Serial.println(); Serial.print("PROBLEMA "); Serial.print(problemasApresentados); Serial.print(" de "); Serial.println(TOTAL_DE_PROBLEMAS); Serial.println("---------------------------------------------------"); Serial.print(" nome ...... "); Serial.println(problema); Serial.print(" falha ..... "); Serial.println(falha); Serial.print(" anotem .... "); Serial.println(frase); } // O problema 1: o sistema não sabe dizer "essa pessoa não pode". A tabela de // permissões nunca existiu, e o botão escondido do painel era a proteção. void problemaAutenticacao() { apresentar( "autenticacao de verdade", "a senha da API esta no codigo do ESP32, entao qualquer placa fala com o " "servidor e qualquer pessoa do WiFi da escola ve os dados", "senha no codigo da placa e a mesma senha para todo mundo. " "ninguem e reconhecido, ninguem e negado."); } // O problema 2: a rota sabe de SQL, de HTTP e de regra ao mesmo tempo. Funciona // até alguém precisar trocar o banco. void problemaCamadas() { apresentar( "separacao em camadas a fundo", "rota, regra e consulta no mesmo arquivo; trocar o banco e reescrever " "tres rotas; o teste precisa de MySQL ligado para testar uma regra", "a rota nao deveria saber SQL. hoje ela sabe, e por isso nao da para " "testar nada sem levantar o banco inteiro."); } // O problema 3: existe um teste só, do caminho inteiro, que falha quando a // internet cai e ninguém sabe se o erro é do teste ou do sistema. void problemaTeste() { apresentar( "teste a fundo", "um teste que so funciona com a placa, a rede e o banco ligados; quando " "ele quebra o aluno nao sabe se quebrou o teste ou o sistema", "teste que depende de tudo nao prova nada. quando falha, sobra a duvida: " "e o teste ou e o sistema?"); } // O problema 4: o schema muda à mão no phpMyAdmin, em produção, no dia que o // professor pediu. Ninguém sabe o que foi rodado. void problemaMigracao() { Serial.println(); Serial.print("PROBLEMA 4 de "); Serial.println(TOTAL_DE_PROBLEMAS); Serial.println("---------------------------------------------------"); Serial.print(" nome ...... "); Serial.println("migracao de banco"); Serial.print(" falha ..... "); Serial.println("o schema foi alterado a mao no phpMyAdmin; ninguem sabe o que " "rodou, e a tabela nova so existe na maquina do aluno"); Serial.print(" anotem .... "); Serial.println("mudar coluna na mao funciona na sua maquina e quebra na do " "colega. a mudanca precisa ser um arquivo versionado."); problemasApresentados++; semanasReservadas += DIAS_POR_PROBLEMA[problemasApresentados - 1]; } // O problema 5: a SQL injection foi fechada, e o resto continua aberto. Rota // nova nasce sem checagem, arquivo de configuração versionado, HTTPS nunca // ligado. void problemaSeguranca() { apresentar( "seguranca alem de SQL injection", "a consulta preparada resolve a injecao e nao resolve mais nada: rota " "nova nasce sem checagem de permissao, a senha do banco esta no " "arquivo versionado e o trafego nao e criptografado", "fechar uma porta e chamar o sistema de seguro. faltam permissoes, " "segredo fora do git e transporte."); } // O problema 6: o projeto roda no notebook do aluno. Para rodar em outro // lugar, ele descobre o que installar, e isso leva duas horas. void problemaDeploy() { apresentar( "deploy", "o projeto so roda na maquina que o programou; o outro computador pede " "Node na versao certa, MySQL ligado, variavel de ambiente certa e uma " "instrucao que existe na cabeca do aluno", "'funciona na minha maquina' e um defeito de entrega, nao um jogo de " "palavras. o comando de subir tem de existir."); } // Os três que o eixo acrescenta ao que o 2o trimestre prometeu. void problemaRegraNegocio() { apresentar( "regra de negocio (acrescimo do eixo)", "o sistema recusa com 500 o que devia recusar com mensagem de regra; " "ninguem sabe por que a leitura foi barrada, e o alerta liga e desliga " "sozinho sem parar", "500 e resposta de tecnica. 'nao posso ligar agora' e regra de negocio, " "e ela precisa estar escrita como codigo."); } void problemaTrabalhoDemora() { apresentar( "trabalho que demora (acrescimo do eixo)", "o alerta espera a consulta terminar na frente do usuario; quando a " "consulta demora, a requisicao inteira demora, e o usuario fecha a " "janela", "o trabalho que demora nao pode ficar na frente de quem espera. ele vai " "para segundo plano e a resposta volta na hora."); } void problemaObservabilidade() { apresentar( "observabilidade (acrescimo do eixo)", "o log diz 'deu erro' e nao diz qual leitura, qual placa, qual hora; " "quando o dono reclama, ninguem acha o registro em quatro dias de log", "log sem identificador nao serve para consertar nada. o id da leitura " "precisa estar na linha que deu erro."); } void mostrarPlacar() { Serial.println(); Serial.println("=== PLACAR DO TRIMESTRE ==="); Serial.println(); Serial.print(" problemas que sobraram: "); Serial.println(TOTAL_DE_PROBLEMAS); Serial.print(" os 6 prometidos pelo 2o trimestre: "); Serial.println("autenticacao, camadas, teste, migracao, seguranca, deploy"); Serial.println(" os 3 acrescentados pelo eixo: "); Serial.println("regra de negocio, trabalho que demora, observabilidade"); Serial.println(); Serial.print(" semanas reservadas para resolver: "); Serial.print(semanasReservadas); Serial.println(" de 15"); Serial.println(); Serial.println("Toda semana letiva do 3o trimestre tem duas aulas."); Serial.println("Cada problema tem nome, e o nome e o que o aluno procura no " "material."); } void setup() { pinMode(PIN_LED, OUTPUT); Serial.begin(115200); Serial.println(); Serial.println("DIA 16, AULA 2 — abertura do 3o trimestre"); Serial.println(); Serial.print("o sistema que a turma entregou roda em "); Serial.print(PLACAS_PROD); Serial.print(" placas e "); Serial.print(USUARIOS_PROD); Serial.print(" usuarios, com "); Serial.print(TABELAS_PROD); Serial.println(" tabelas no banco."); Serial.print("cada atendimento leva "); Serial.print(ATENDIMENTO_MS); Serial.println(" ms, e isso e o que a fila precisa resolver."); Serial.println("---------------------------------------------------"); Serial.println("a placa de abertura comeca agora. anotem."); } void loop() { bloco++; digitalWrite(PIN_LED, HIGH); delay(150); digitalWrite(PIN_LED, LOW); switch (bloco) { case 1: problemaAutenticacao(); break; case 2: problemaCamadas(); break; case 3: problemaTeste(); break; case 4: problemaMigracao(); break; case 5: problemaSeguranca(); break; case 6: problemaDeploy(); break; case 7: problemaRegraNegocio(); break; case 8: problemaTrabalhoDemora(); break; case 9: problemaObservabilidade(); Serial.println(); Serial.println("a luz piscou nove vezes. nove problemas, nove nomes."); mostrarPlacar(); Serial.println(); Serial.println("proximo trimestre: dia 1, regra de negocio."); break; default: bloco = 0; problemasApresentados = 0; semanasReservadas = 0; Serial.println(); Serial.println("a placa volta ao comeco em alguns segundos."); delay(4000); break; } delay(INTERVALO_BLOCO); }
Por que assim e não de outro jeito. Sete dos nove problemas passam pela função apresentar, que recebe três textos e imprime sempre no mesmo formato. O nono, a migração, foi escrito à mão em bloco próprio porque foi o primeiro a quebrar quando a função foi montada: o Serial.print do problema 4 ficava embaixo do bloco anterior, e o contador avançava duas vezes.
Isso é o ponto do dia: o mesmo formato para os nove é o que permite comparar. A turma olha nove blocos com a mesma forma e a diferença entre eles fica na falha, não no desenho. Um bloco com layout diferente chama atenção para o layout e o aluno para de ler o problema.
A soma das semanas é acumulada na função, e não impressa problema a problema. O placar sai uma vez, no fim. É a diferença entre a turma acompanhar um número que sobe — barulho — e ler um total no fim do trimestre, que ela pode comparar com as 15 semanas.
Por que o nono bloco pisca o LED e chama mostrarPlacar, e os outros não. O nono é o último, e é o único em que a contagem precisa ficar na memória de quem anotou. Se a placa mostrasse o placar junto com cada problema, o aluno teria nove números para lembrar em vez de um.
Criterios de correcao
| Critério | Pontos |
|---|---|
| Placa de abertura gravada e os nove blocos lidos até o placar | 2 pontos |
| Nove linhas com nome do problema e exemplo concreto do projeto | 3 pontos |
| Três problemas acrescentados pelo eixo, com exemplo concreto de cada um | 2 pontos |
| Soma das semanas letivas feita e comparada com as 15 | 1 ponto |
| Um problema escolhido e a frase da regra escrita inteira | 1 ponto |
| Frase lida ao colega sem ele precisar perguntar nada | 1 ponto |
Erros comuns
| Erro | Como aparece | Correcao |
|---|---|---|
| Dizer "eu já vi autenticação, fiz no dia 9" e considerar o problema resolvido | Item 2 com "autenticação — já fiz" | "Você viu a senha comparada no servidor. O problema de autenticação de verdade é hash, salt e o que nunca vai para o banco. Ver não é saber fazer." |
| Preencher os nove problemas com "quando o sistema crescer" | Nove linhas sem exemplo concreto hoje | "Se o exemplo só acontece quando crescer muito, esse não é um problema do seu projeto agora. Escolhe o que já te morde hoje." |
| Pôr nove problemas na folha | Folha cheia, nenhum com frase de regra | "Um. Se você tem nove, não começou nenhum. Escolhe o que dói mais e traz na próxima semana." |
| Escrever a regra em código | "if (!podeLigar) return res.status(500)" como frase da regra | "A regra é frase de português: o sistema não pode X quando Y. O código vem depois, na aula. Se você escreve o código agora, você já escolheu a solução antes da regra." |
| Somar as semanas de cabeça sem escrever e errar | Item 4 com total errado | "Escreve os nove números em linha antes de somar. Nove números pequenos somados de cabeça dão erro em um deles, e o erro fica escondido." |
| Ler a frase da regra e o colega perguntar "isso quer dizer o quê?" | Item 6 com a frase lida apressada | "Se ele perguntou, a frase está ruim, não a leitura. Refaz com mais verbo: 'o sistema não pode aceitar leitura quando a placa não está cadastrada'." |
| Tratar os nove problemas como nove matérias sem relação | "Autenticação é uma aula, camadas é outra, não se misturam" | "Não são nove matérias, são nove jeitos de o mesmo sistema quebrar. Cadastro é permissão; permissão é teste; teste é migração. Nenhum resolve o anterior." |
Desafio extra
Escolha dois dos nove problemas e escreva, em uma frase cada, qual dos dois é o conserto do outro. Um exemplo possível: "sem o log com identificador, o teste de regressão não sabe o que comparar". Valide a frase no seu projeto: se ela não descreve um problema que você tem, o par escolhido não é o seu par — e o exercício vale mais quando o par é o do seu código, não o da lista.
>A resolucao, compilada
// DIA 16, AULA 2 — os nove problemas que sobraram para o 3o trimestre. // // Este arquivo não tenta resolver nada. Ele é a PLACA DE ABERTURA do // trimestre: cada bloco mostra uma falha que o sistema da aula 2 tem e que o // sistema do 3o trimestre precisa consertar. A turma lê a falha, e o professor // escreve na lousa o nome do problema e o dia em que ele é resolvido. // // AVISO PARA O PROFESSOR: nada aqui está ligado. Sensor, servidor e banco são // simulados de forma determinística. Os números (40 placas, 120 usuários, 18 // tabelas, 900 ms por atendimento) são os do eixo deste dia, e servem para a // turma ver a escala — não são medidos. #include <Arduino.h> // PROBLEMAS = 9; a placa pisca uma vez por problema apresentado: a turma // acompanha a contagem na tela em vez de anotar nove. const int PIN_LED = 2; // Um bloco a cada 4,5 s: nove problemas em quarenta e cinco segundos, o tempo // exato de uma leitura de ata. const int INTERVALO_BLOCO = 4500; // A escala do produto, a mesma da aula 1 deste dia. const int PLACAS_PROD = 40; const int USUARIOS_PROD = 120; const int TABELAS_PROD = 18; const int ATENDIMENTO_MS = 900; // Quantos dias do 3o trimestre cada problema ocupa, pela ordem em que o eixo // resolve. O professor anota na lousa: o trimestre tem 15 semanas e nove // problemas, e essa conta mostra que sobra tempo. const int DIAS_POR_PROBLEMA[] = {2, 2, 2, 3, 2, 2, 2, 2, 3}; const int TOTAL_DE_PROBLEMAS = 9; int bloco = 0; int problemasApresentados = 0; int semanasReservadas = 0; // Cada bloco imprime: a falha que existe hoje, o problema sem nome que ela // esconde, e a frase que o aluno vai escrever no caderno. void apresentar(const char* problema, const char* falha, const char* frase) { problemasApresentados++; semanasReservadas += DIAS_POR_PROBLEMA[problemasApresentados - 1]; Serial.println(); Serial.print("PROBLEMA "); Serial.print(problemasApresentados); Serial.print(" de "); Serial.println(TOTAL_DE_PROBLEMAS); Serial.println("---------------------------------------------------"); Serial.print(" nome ...... "); Serial.println(problema); Serial.print(" falha ..... "); Serial.println(falha); Serial.print(" anotem .... "); Serial.println(frase); } // O problema 1: o sistema não sabe dizer "essa pessoa não pode". A tabela de // permissões nunca existiu, e o botão escondido do painel era a proteção. void problemaAutenticacao() { apresentar( "autenticacao de verdade", "a senha da API esta no codigo do ESP32, entao qualquer placa fala com o " "servidor e qualquer pessoa do WiFi da escola ve os dados", "senha no codigo da placa e a mesma senha para todo mundo. " "ninguem e reconhecido, ninguem e negado."); } // O problema 2: a rota sabe de SQL, de HTTP e de regra ao mesmo tempo. Funciona // até alguém precisar trocar o banco. void problemaCamadas() { apresentar( "separacao em camadas a fundo", "rota, regra e consulta no mesmo arquivo; trocar o banco e reescrever " "tres rotas; o teste precisa de MySQL ligado para testar uma regra", "a rota nao deveria saber SQL. hoje ela sabe, e por isso nao da para " "testar nada sem levantar o banco inteiro."); } // O problema 3: existe um teste só, do caminho inteiro, que falha quando a // internet cai e ninguém sabe se o erro é do teste ou do sistema. void problemaTeste() { apresentar( "teste a fundo", "um teste que so funciona com a placa, a rede e o banco ligados; quando " "ele quebra o aluno nao sabe se quebrou o teste ou o sistema", "teste que depende de tudo nao prova nada. quando falha, sobra a duvida: " "e o teste ou e o sistema?"); } // O problema 4: o schema muda à mão no phpMyAdmin, em produção, no dia que o // professor pediu. Ninguém sabe o que foi rodado. void problemaMigracao() { Serial.println(); Serial.print("PROBLEMA 4 de "); Serial.println(TOTAL_DE_PROBLEMAS); Serial.println("---------------------------------------------------"); Serial.print(" nome ...... "); Serial.println("migracao de banco"); Serial.print(" falha ..... "); Serial.println("o schema foi alterado a mao no phpMyAdmin; ninguem sabe o que " "rodou, e a tabela nova so existe na maquina do aluno"); Serial.print(" anotem .... "); Serial.println("mudar coluna na mao funciona na sua maquina e quebra na do " "colega. a mudanca precisa ser um arquivo versionado."); problemasApresentados++; semanasReservadas += DIAS_POR_PROBLEMA[problemasApresentados - 1]; } // O problema 5: a SQL injection foi fechada, e o resto continua aberto. Rota // nova nasce sem checagem, arquivo de configuração versionado, HTTPS nunca // ligado. void problemaSeguranca() { apresentar( "seguranca alem de SQL injection", "a consulta preparada resolve a injecao e nao resolve mais nada: rota " "nova nasce sem checagem de permissao, a senha do banco esta no " "arquivo versionado e o trafego nao e criptografado", "fechar uma porta e chamar o sistema de seguro. faltam permissoes, " "segredo fora do git e transporte."); } // O problema 6: o projeto roda no notebook do aluno. Para rodar em outro // lugar, ele descobre o que installar, e isso leva duas horas. void problemaDeploy() { apresentar( "deploy", "o projeto so roda na maquina que o programou; o outro computador pede " "Node na versao certa, MySQL ligado, variavel de ambiente certa e uma " "instrucao que existe na cabeca do aluno", "'funciona na minha maquina' e um defeito de entrega, nao um jogo de " "palavras. o comando de subir tem de existir."); } // Os três que o eixo acrescenta ao que o 2o trimestre prometeu. void problemaRegraNegocio() { apresentar( "regra de negocio (acrescimo do eixo)", "o sistema recusa com 500 o que devia recusar com mensagem de regra; " "ninguem sabe por que a leitura foi barrada, e o alerta liga e desliga " "sozinho sem parar", "500 e resposta de tecnica. 'nao posso ligar agora' e regra de negocio, " "e ela precisa estar escrita como codigo."); } void problemaTrabalhoDemora() { apresentar( "trabalho que demora (acrescimo do eixo)", "o alerta espera a consulta terminar na frente do usuario; quando a " "consulta demora, a requisicao inteira demora, e o usuario fecha a " "janela", "o trabalho que demora nao pode ficar na frente de quem espera. ele vai " "para segundo plano e a resposta volta na hora."); } void problemaObservabilidade() { apresentar( "observabilidade (acrescimo do eixo)", "o log diz 'deu erro' e nao diz qual leitura, qual placa, qual hora; " "quando o dono reclama, ninguem acha o registro em quatro dias de log", "log sem identificador nao serve para consertar nada. o id da leitura " "precisa estar na linha que deu erro."); } void mostrarPlacar() { Serial.println(); Serial.println("=== PLACAR DO TRIMESTRE ==="); Serial.println(); Serial.print(" problemas que sobraram: "); Serial.println(TOTAL_DE_PROBLEMAS); Serial.print(" os 6 prometidos pelo 2o trimestre: "); Serial.println("autenticacao, camadas, teste, migracao, seguranca, deploy"); Serial.println(" os 3 acrescentados pelo eixo: "); Serial.println("regra de negocio, trabalho que demora, observabilidade"); Serial.println(); Serial.print(" semanas reservadas para resolver: "); Serial.print(semanasReservadas); Serial.println(" de 15"); Serial.println(); Serial.println("Toda semana letiva do 3o trimestre tem duas aulas."); Serial.println("Cada problema tem nome, e o nome e o que o aluno procura no " "material."); } void setup() { pinMode(PIN_LED, OUTPUT); Serial.begin(115200); Serial.println(); Serial.println("DIA 16, AULA 2 — abertura do 3o trimestre"); Serial.println(); Serial.print("o sistema que a turma entregou roda em "); Serial.print(PLACAS_PROD); Serial.print(" placas e "); Serial.print(USUARIOS_PROD); Serial.print(" usuarios, com "); Serial.print(TABELAS_PROD); Serial.println(" tabelas no banco."); Serial.print("cada atendimento leva "); Serial.print(ATENDIMENTO_MS); Serial.println(" ms, e isso e o que a fila precisa resolver."); Serial.println("---------------------------------------------------"); Serial.println("a placa de abertura comeca agora. anotem."); } void loop() { bloco++; digitalWrite(PIN_LED, HIGH); delay(150); digitalWrite(PIN_LED, LOW); switch (bloco) { case 1: problemaAutenticacao(); break; case 2: problemaCamadas(); break; case 3: problemaTeste(); break; case 4: problemaMigracao(); break; case 5: problemaSeguranca(); break; case 6: problemaDeploy(); break; case 7: problemaRegraNegocio(); break; case 8: problemaTrabalhoDemora(); break; case 9: problemaObservabilidade(); Serial.println(); Serial.println("a luz piscou nove vezes. nove problemas, nove nomes."); mostrarPlacar(); Serial.println(); Serial.println("proximo trimestre: dia 1, regra de negocio."); break; default: bloco = 0; problemasApresentados = 0; semanasReservadas = 0; Serial.println(); Serial.println("a placa volta ao comeco em alguns segundos."); delay(4000); break; } delay(INTERVALO_BLOCO); }
Sem saída de compilação gravada. Rode python3 validar.py -t 2 dia16 aula2.
