Logo Tech Writers

Tech writers

Esse é o nosso blog para apaixonados por tecnologia! Aqui, softplayers e outros especialistas compartilham conhecimentos fundamentais para o desenvolvimento dessa comunidade.

SEJA UM TECH WRITER
Padrão de Projeto Composite: O que é, prós e contras e como implementar?
Tech Writers Julho 04, 2023

Padrão de Projeto Composite: O que é, prós e contras e como implementar?

Se você atua com projetos de software e já teve a necessidade de tratar objetos individuais e coleções de objetos de forma uniforme, o padrão de projeto Composite vai te ajudar. Descubra a seguir como o padrão Composite auxilia na criação de interfaces de usuário mais intuitivas e no processamento de árvores de objetos de forma eficiente. Neste artigo, convidamos você a explorar os benefícios desse padrão, que simplifica estruturas hierárquicas e oferece maior flexibilidade na manipulação de elementos. Confira abaixo o que é o Composite, quais suas vantagens e desvantagens e veja um exemplo prático da sua implementação. O que é o Composite? O Composite é um padrão de projeto estrutural que permite tratar de maneira uniforme os objetos individuais e composições de objetos, formando uma estrutura hierárquica. Ele é o quarto padrão desta categoria apresentado pela "Gang of Four" (GoF). Como os próprios autores colocam, a intenção oficial deste padrão é “compor objetos em estruturas de árvore para representar hierarquias partes-todo". Com o Composite, um objeto individual e um grupo de objetos são tratados da mesma maneira, pois ambos implementam uma interface comum. Como funciona o padrão de projeto Composite? Dentro do padrão Composite, encontramos uma classe abstrata conhecida como "Componente", que estabelece uma interface compartilhada para objetos individuais e grupos de objetos. Os objetos individuais são representados por uma classe concreta que implementa o Componente, enquanto os grupos de objetos são representados por uma classe composta que também implementa o Componente. A estrutura hierárquica é criada através da composição, na qual um grupo de objetos pode incluir outros objetos individuais ou grupos de objetos. Essa estrutura permite a realização de interações recursivas, e dessa forma possibilita a aplicação de operações a todos os objetos na hierarquia. O padrão Composite é ideal para quando há a necessidade de tratar objetos individuais e coleções de objetos de forma homogênea, simplificando o código e conferindo maior flexibilidade. Seu uso é comum em interfaces de usuário, processamento de árvores e outras estruturas hierárquicas. Como é a implementação do Composite? Para entender melhor a implementação do Composite, vamos analisar o exemplo a seguir: Em um supermercado, você possui duas formas de comprar um refrigerante: É possível comprar a unidade Ou comprar um fardo com 12 unidades Aqui, nós temos um Composite: a noção de que o fardo (estrutura) se comporta como um produto, e que ele pode dizer seu preço delegando o seu valor, somando assim os custos das unidades filhas e utilizando como seu próprio. Claro, o cenário acima só faz sentido se o fardo não possuir um valor fixo, e sim que seu valor se resume no total de unidades que há dentro do mesmo. Vejamos um código do cenário descrito (no caso, utilizando Java para exemplificar): No exemplo acima, definimos uma interface Produto, que será implementada tanto pela unidade de “refrigerante”, quanto pelo fardo. O método em comum que será implementado por eles, no nosso caso, é o getValor(). O refrigerante, por sua vez, possui o valor e um nome. A implementação do getValor(), por ser uma única unidade, apenas retorna o seu próprio valor. Acima temos o fardo de refrigerantes, atuando como Composite, seu “valor” é delegado para as unidades que há dentro dele. Ou seja, se houver 5 unidades de refrigerante, cada uma com um valor “5”, o valor do fardo será de 25. O interessante neste design pattern é que a complexidade desse tipo de estrutura não acaba por aí. Como a classe FardoDeRefrigerante possui uma lista dentro de si do tipo Produto, ela é capaz de suportar até mesmo outros fardos dentro de si mesma. Exemplo da Estrutura de um Composite Apesar de o “fardo de refrigerante” não ser o melhor exemplo nesse caso, podemos imaginar uma caixa dentro de outra caixa, e cada uma delas com produtos de diferentes valores dentro de si, as caixas internas totalizaram o valor dos produtos internos, e a caixa externa totalizaria o valor das caixas internas, parecendo muito com a estrutura abaixo: Exemplo de como a estrutura de um composite pode ficar. Fonte: “Padrões de Projetos: Soluções Reutilizáveis de Software Orientados a Objetos” Normalmente utiliza-se o padrão de projeto Composite, por exemplo, para rodar uma bateria de validações em cima de um objeto. Enquanto o Decorator serve para estender funcionalidades dentro de uma classe já existente, sem alterar a classe original e preservando os princípios SOLID. A forma de implementação pode variar bastante dependendo de como que você utiliza, mas o importante é conhecer o padrão e saber quando encaixá-lo no seu sistema. Não siga à risca os diagramas propostos pela GoF, ou os exemplos citados, adeque-os de acordo com suas necessidades e situações. Quando usar o padrão de projeto Composite? Aplica-se o padrão de projeto Composite nas situações em que há uma estrutura hierárquica de objetos e quando se deseja tratar objetos individuais e grupos de objetos de forma uniforme, simplificando o código e fornecendo maior flexibilidade. Aqui estão algumas situações de exemplo do uso do padrão Composite: Estruturas Hierárquicas:  O padrão Composite é ideal para lidar com estruturas hierárquicas, como árvores ou grafos, onde os nós podem ser objetos individuais ou grupos de objetos. Modelagem de Interface de Usuário:  É comum utilizar o padrão Composite na construção de interfaces de usuário, especialmente quando há elementos que podem conter outros elementos, como menus, botões e painéis. Processamento de Documentos: O Composite pode ser útil para tratar elementos como documentos com seções, parágrafos, listas, etc, de forma uniforme. Manipulação de Gráficos: Se você precisa lidar com elementos gráficos, como formas, linhas e grupos de formas, o Composite permite tratá-los de maneira uniforme e facilita a aplicação de operações a todos os elementos. Implementação de Estruturas de Dados: Também é possível aplicar o Composite na implementação de estruturas de dados como arrays, listas e matrizes, em que tratam-se os elementos individuais e os grupos de elementos de forma semelhante. Quais os prós e contras de usar o Composite? Confira os principais prós e contras do Composite: PrósContrasSimplifica a estrutura hierárquicaPode ter impacto na eficiência em estruturas muito grandesOferece flexibilidade na manipulação de objetos e operações recursivasPode exigir maior esforço de design e implementação inicialPromove reuso do códigoRequer uma interface comum bem definida No entanto, é importante lembrar que os prós e contras do Composite podem variar dependendo do contexto e dos requisitos específicos do projeto. Portanto, é essencial considerar cuidadosamente esses aspectos antes de decidir utilizar o design pattern Composite. E você já sabia como implementar o Composite? Aproveite e confira outros conteúdos de tecnologia no Tech Writers.

IHC: Saiba o que é e os focos de estudo da Interação Humano-Computador
Tech Writers Maio 25, 2023

IHC: Saiba o que é e os focos de estudo da Interação Humano-Computador

Com o aumento exponencial do uso de aparelhos e engenhocas eletrônicas na nossa rotina, a importância da Interação Humano-Computador, também conhecida como IHC, têm aumentado cada vez mais na transformação da sociedade, impactando diretamente o cotidiano da vida de todos. Especialmente para pessoas desenvolvedoras de software e profissionais do design das interfaces, é fundamental entender os princípios da IHC para elaborar produtos bem-sucedidos, que atendam às expectativas das pessoas usuárias. Se você quer saber mais sobre o assunto, descubra a seguir o que é o IHC. Também abordaremos quais são os principais pilares de estudo desta área para entender melhor este conceito. O que é o IHC? A transformação digital ocorre com mais fluidez com o bom uso de boas interfaces, que devem ser cuidadosamente projetadas para permitir uma comunicação eficaz entre as pessoas e as máquinas. O foco é proporcionar uma experiência agradável e satisfatória para a pessoa usuária, em que ela consiga realizar sua tarefa e resolver sua “dor” de forma eficiente e sem frustrações. É aí que entra a IHC. A Interação Humano-Computador (IHC) é uma área multidisciplinar da tecnologia dedicada ao estudo e à melhoria da interação entre seres humanos e sistemas computacionais. Seu objetivo é criar interfaces da pessoa usuária que sejam intuitivas, eficientes e agradáveis de se usar.  A IHC abrange diversos aspectos do design de interfaces, como a usabilidade, a acessibilidade, a experiência do usuário e a ergonomia. Sendo assim, a área utiliza métodos e técnicas de origens diversas, como a psicologia, a engenharia de software, a ciência da computação e o design. Quais são os 3 focos de estudo de IHC? Os três focos principais de estudo da IHC (Interação Humano-Computador) são: 1. A pessoa usuária (e sua tarefa): A IHC foca primeiramente em entender as necessidades, habilidades e limitações das pessoas usuárias, visando projetar sistemas e interfaces intuitivas e otimizadas para as ações pretendidas. Para isso, a área utiliza técnicas de pesquisa, como entrevistas quantitativas e qualitativas, observação do modelo mental, mapeamento da jornada do usuário e testes de usabilidade. 2. O sistema: Outro foco da área é o sistema em si, isto é, entender como os sistemas computacionais funcionam e como projetá-los de forma otimizada e segura levando em consideração diversos fatores, como limitações de hardware e software, por exemplo. Na escalada desse conhecimento, é necessário o aprofundamento nas áreas da arquitetura de software, tecnologias de interação, usabilidade e design de interfaces. 3. O contexto de uso: Por último, outro foco de estudo da área é o contexto de uso dos sistemas. Por exemplo, as condições ambientais, as restrições de tempo, as habilidades ou possíveis limitações físicas da pessoa usuária, além de seus desejos, necessidades e sua cultura — digital, ou não. Todos esses elementos moldam a resposta às necessidades de quem está usando o sistema. Assim, é possível garantir que o sistema seja projetado levando em conta as expectativas de ação e reação da pessoa usuária em um grande espectro de situações. Feedback é vida A exemplo disso, o feedback que o usuário precisa receber do sistema computacional deve ser explicitamente planejado e programado. Isso é essencial para garantir que o usuário entenda claramente o que está acontecendo internamente no computador e possa interagir com ele de forma mais assertiva. Imagine a seguinte situação: você aciona a vinda de um elevador e não recebe resposta alguma do sistema, nenhum botão aceso, nenhum contador de andares, nenhuma seta para cima ou para baixo, e desse ponto em diante a sua interação com o sistema passa a ser baseada na fé – de que o elevador vai chegar em algum momento… Jakob Nielsen, o Yoda da usabilidade, não se contenta com designs bonitos; ele nos convida a pensar no usuário em primeiro lugar. Eficiência de uso e satisfação do usuário são como seu mantra do design. É mais do que criar algo bonito; é criar algo que funcione com maestria e faça o usuário “sorrir” enquanto usa. E aí entram as heurísticas de Nielsen, o mestre dos magos do pragmatismo funcional. Esses princípios não são apenas diretrizes acolhidas pelos designers; são como os próprios 10 mandamentos do design de interfaces. "Faça o status do sistema visível!" ele proclama. "Mantenha uma correspondência com as coisas no mundo real e de controle ao usuário!" Essas regras são como bússolas que guiam os designers pelos mares da experiência do usuário. Portanto, deixe de usá-las e navegue sem rumo à sua própria sorte. Podemos elencar 10 heurísticas principais e uma delas, comentada acima, é justamente a primeira de todas: Visibilidade do status do sistema. Para fechar o combo temos mais 9 heurísticas — que serão gradativamente abordadas nos próximos posts: Correspondência entre o sistema e o mundo real Controle e liberdade do usuário Consistência e padrões Prevenção de erros Reconhecimento em vez de memorização Flexibilidade e eficiência de uso Estética e design minimalista Reconhecimento, diagnóstico e recuperação de erros Ajuda e documentação Origem da IHC e Linha do Tempo Anteriormente, na aurora dos tempos das interfaces podemos apontar com segurança o Lisa, como o "papai forno" das interfaces. Lançado em 1983, pela Apple, o primeiro computador comercial que possuía uma Interface Gráfica de Usuário (UI). Essa tecnologia permitiu a utilização de computadores por pessoas sem nenhum treinamento especial, tornando-os acessíveis a todos. No entanto, a Apple já estava trabalhando em uma versão mais acessível e de menor custo. Um ano depois, a empresa lançou o Macintosh, o primeiro computador com uma interface gráfica realmente acessível. Vinha com um monitor, teclado e mouse com botão, e possuía uma organização maior que os computadores anteriores. As opções eram ordenadas em menus e havia ícones que podiam ser clicados para operar um programa. O foco aqui é perceber que o maior legado dessa movimentação disruptiva foi a metáfora da área de trabalho (Desktop folders metaphor), utilizada comercialmente pela primeira vez pela Apple no Lisa OS, o que alavancou também o uso de Interfaces Gráficas (Graphical User Interface, ou GUI) por outras empresas. Essa metáfora da área de trabalho representava uma mesa de escritório com vários papéis em cima, simbolizando os arquivos do computador, assim como outras representações do mundo real, como a lixeira, o calendário, o relógio, os arquivos, planilhas, o bloco de notas, a calculadora, etc. Nessa época os primeiros usuários e entusiastas dos computadores eram pessoas que trabalhavam em escritórios, com datilografia, máquinas de calcular, pastas de arquivos, etc. Por isso, percebeu-se que ao simular o ambiente físico de escritório em uma interface no computador, os usuários compreenderiam com mais facilidade o armazenamento das informações no Desktop. Esse era o modelo mental. Após esse rolê no passado, olhemos agora para o presente. Não podemos ignorar o burburinho da inteligência artificial (IA). Agora, a coisa está ficando real, com comandos de fala prestes a entrar em cena. Não estamos apenas clicando e arrastando; estamos falando com nossas máquinas. É tipo ter um assistente pessoal que não apenas entende o que você diz, mas também pode auxiliar ou executar qual tarefa você realmente precisa realizar, ao melhor estilo J.A.R.V.I.S., do Tony Stark. No entanto, com grandes poderes vêm grandes responsabilidades. À medida que a IA se torna onipresente, começamos a questionar a privacidade, a segurança e até mesmo a confiabilidade dessas interações. É como se estivéssemos flertando com uma nova era de conversas digitais, mas não sabemos ao certo todas as regras do jogo. É digno reparar também que mesmo com uma ajudinha de sua assistente pessoal falante, o menino Tony ainda faz amplo uso de interfaces gráficas. Conclusão Em suma, chamamos de Interação Humano-Computador o estudo, projeto e implementação de softwares para o uso direto com usuários. Tais sistemas apresentam Interfaces do Usuário (UI). É através delas que uma pessoa irá interagir com um computador. Dessa forma, foi através das interfaces que o computador se tornou no que conhecemos. Gostou de saber mais sobre a Interação Humano-Computador? Caso tenha alguma dúvida, deixe seu comentário e confira outros artigos da Tech Writers.

Observabilidade: O que é, vantagens, pilares e qual a diferença para o monitoramento!
Tech Writers Maio 11, 2023

Observabilidade: O que é, vantagens, pilares e qual a diferença para o monitoramento!

Nos últimos anos, percebemos um aumento da complexidade dos sistemas de software, o surgimento de SaaS e apps híbridos. Isso consequentemente aumenta os riscos de bugs, além de uma maior exposição dos sistemas à invasão e vazamento de dados. Neste novo contexto, a observabilidade pode ajudar a identificar problemas de forma mais rápida, otimizando o trabalho da equipe de desenvolvimento e melhorando a qualidade dos sistemas. Se você ainda não conhece este conceito, confira a seguir mais informações sobre uma das principais tendências em engenharia de software e descubra o que é a observabilidade, seus pilares, vantagens e como implementar! O que é observabilidade em TI? A observabilidade em TI é a aplicação de um sistema de constante monitoramento, rastreamento, análises e diagnósticos de um sistema, fazendo uso de algumas ferramentas de software. A observabilidade permite investigar e entender de maneira mais aprofundada como um sistema comporta, principalmente em arquiteturas cloud. A partir das ferramentas de observabilidade, é possível coletar e analisar um grande espectro de dados, detectar problemas, entender as causas dos problemas identificados e traçar um plano de ação para aprimorar o funcionamento dos sistemas. Dessa forma, a observabilidade ajuda a resolver problemas antes que eles afetem os KPIs da empresa. Além disso, transformam um problema incompreensível em algo mais detectável, visível e investigável. Este conceito é bastante aplicado por times DevOps, infraestrutura e desenvolvimento, pois já é difundido na Engenharia de Software que ele beneficia o software e facilita a solução de problemas. O ideal é adotar a implementação da observabilidade de software principalmente quando o foco do seu negócio for a experiência do cliente ou para otimizar o trabalho das pessoas desenvolvedoras da sua equipe. Aproveite para conferir também nosso artigo que aborda um pouco mais sobre a observabilidade orientada ao domínio, uma metodologia de implementação da observabilidade.  Quais as vantagens de implementar a Observabilidade em TI? Algumas vantagens de implementar a observabilidade são: Disponibilidade, pois facilita a identificação e correção de erros, minimizando o tempo de inatividade e o impacto nos usuários finais; Confiabilidade, pois, quando usada de forma preventiva, a observabilidade é capaz de mitigar problemas de escalabilidade ou performance de uma aplicação antecipadamente; Rastreabilidade do uso de funcionalidades, de forma a se obter insumos para decisões estratégicas que podem ser tomadas no âmbito do negócio; Produtividade, pois a observabilidade permite acompanhar mudanças em tempo real, aumentando a capacidade produtiva do seu time na hora de suprir as demandas diárias, auxiliando as equipes de DevOps, infraestrutura, ou outras; Custo menor, pois uma vez que a observabilidade previne problemas de segurança, a empresa gasta menos com manutenções inesperadas; Previsibilidade, pois quando a cultura do time está focada em rastrear e monitorar os sistemas em tempo real, a empresa consegue prever mais facilmente alguns dos problemas futuros. Entre essas vantagens, a rastreabilidade é a que mais impacta o negócio, pois é ela que define o sucesso da sua aplicação. As também chamadas “métricas de alto nível”, por serem intrinsecamente ligadas ao negócio, são as que mais entregam valor.  Através da rastreabilidade do uso das funcionalidades de um sistema é que conseguimos entender se ele está performando conforme os objetivos de um produto. Quais são os 3 pilares da observabilidade em TI? A eficácia na implementação da observabilidade de software só é possível a partir do uso de dados de telemetria, que são os pilares que reúnem todas as informações sobre o sistema investigado. No conceito de observabilidade, temos 3 pilares: logs de evento, métricas e rastreamento. Veja a seguir uma explicação dos 3 pilares da observabilidade em TI: Logs de evento: É um registro imutável que apresenta hora e data dos eventos. É possível captá-lo através de texto, binário ou estruturado. Métricas: As métricas são valores definidos de acordo com o objetivo. Elas são usadas para investigar o comportamento de um evento em um intervalo de tempo específico e fornecem dados como data, nome, hora e KPIs. Rastreamento: É o pilar que detalha todas as operações, desde seu início até o fim. Isso acontece com o monitoramento da jornada completa para entender se o sistema está em normalidade ou corre algum risco. Qual é a diferença entre monitoramento e observabilidade? A estratégia de observabilidade não é exatamente diferente do monitoramento, pois o monitoramento trata os problemas de forma mais reativa e não é capaz de lidar com problemas de alta complexidade. Isso porque desde a incorporação da arquitetura de microsserviços para os apps web, houve maior escalabilidade na criação de componentes de sistema sendo implementados de forma individual nas plataformas. Neste cenário em que novos problemas desconhecidos podem surgir, somente o monitoramento já não consegue ser tão eficiente. Por outro lado, a observabilidade é um grande conjunto de monitoramento focado na arquitetura de microsserviços na camada de aplicação e contêineres na área de infra. Além disso, ela faz uma correlação dos dados de telemetria coletados com o objetivo de criar soluções mais eficazes.  Assim, a observação constante consegue trazer dados que auxiliam o monitoramento, facilitando a identificação dos problemas e suas causas. Ou seja, o monitoramento garante que uma aplicação se torne observável, sendo assim, a observabilidade é uma evolução do conceito de monitoramento. Através da observabilidade, é possível ter um melhor monitoramento do sistema, sendo quase sinônimos nesse sentido. Como implementar a observabilidade? Para implementar a observabilidade de maneira adequada, você precisa, primeiramente, definir suas metas. Ou seja, identificar os principais indicadores de desempenho (KPIs), seus objetivos e listar os pontos críticos monitoráveis. Em seguida, instrumente seu código com métricas e registros. Algumas ferramentas podem te ajudar nessa tarefa, como o Prometheus para métricas e o Fluentd para registros. Você também pode utilizar ferramentas de monitoramento para analisar os dados gerados na aplicação. Por exemplo, o Grafana para visualizar métricas e o Kibana para analisar os registros. Além destes pontos, é importante ter alertas que notifiquem o time sempre que um evento crítico ocorrer. Para entender como as solicitações estão se comportando dentro do sistema, você pode usar o rastreamento de transações para rastrear o fluxo de solicitações através dos diferentes componentes. Seguindo estes passos e mantendo um processo contínuo, atualize suas metas e ajuste sua implementação conforme as necessidades forem mudando. Ainda tem alguma dúvida sobre observabilidade? Deixe seu comentário!

Observabilidade: O que é, pilares e como implementar a observabilidade orientada ao domínio
Tech Writers Março 16, 2023

Observabilidade: O que é, pilares e como implementar a observabilidade orientada ao domínio

Recentemente estamos vendo uma grande expansão dos sistemas web, o surgimento de aplicações híbridas e aplicações que utilizam cada vez mais os softwares como serviço (SaaS). Este crescimento traz um novo desafio aos times de DevOps, infra e desenvolvimento: somente o monitoramento de redes não é mais capaz de garantir a segurança dos dados. É aí que entra a observabilidade. A observabilidade auxilia no rastreamento e identificação de problemas a partir de ferramentas de software. E hoje, vamos te ensinar a implementar a observabilidade usando o método de Observabilidade Orientada ao Domínio. Assim, você vai tornar as diversas chamadas para serviços de log e frameworks de análises em seus sistemas menos técnicas e prolixas. Confira! O que é observabilidade em TI? A observabilidade em TI (também chamada de observability) é a capacidade de monitorar, rastrear, analisar e diagnosticar um sistema, a partir do uso de ferramentas de software. Com ela, é possível criar um sistema de constante monitoramento e observação sobre um sistema com o objetivo de compreender melhor como ele se comporta, principalmente em arquiteturas cloud. Este conceito é bastante aplicado por times DevOps, infraestrutura e desenvolvimento, pois já é difundido na Engenharia de Software que ele beneficia o software e facilita a solução de problemas. Observabilidade orientada ao domínio na prática: Valores Grandes aplicações voltadas para análises de métricas de alto nível, como Mixpanel, acreditam no conceito de “Momentos de valor” (value moments), que indica quais eventos de determinado produto são importantes para se instrumentar. Estes momentos de valor variam de acordo com o produto, por exemplo, um software voltado para soluções de assinatura eletrônica, como a 1Doc, pode considerar que a assinatura de um contrato é um “momento de valor”. Porém, o momento de valor que faz sentido para o seu negócio, não necessariamente faz sentido para os usuários. Isso porque o valor do seu negócio é composto do equilíbrio entre duas forças: a intenção e a expectativa. Se a intenção é facilitar o processo de assinatura de um contrato, e a expectativa dos seus usuários é exatamente essa, você alcançou o equilíbrio. Contudo, o desencontro dessas duas forças é uma perda de oportunidade, e consequentemente, de valor. Graças às métricas de alto nível, este desencontro não é uma causa perdida. Com elas é possível recuperar e manter o valor do seu negócio de acordo com os momentos de valor identificados pelo seu time de analistas de produto. A partir daqui, seu papel como pessoa desenvolvedora passa a envolver a verificação da viabilidade técnica e a implementação da captura dessas métricas para que o “time de negócio” consiga lidar com os dados. Como implementar a observabilidade orientada ao domínio? A partir de agora vamos para a parte prática aprender a implementar a observabilidade orientada ao domínio. Para entender melhor esta implementação, vamos imaginar um pequeno sistema de gerenciamento de tarefas. Este sistema cadastra tarefas agendadas e as executa de acordo com o agendamento. Porém, devido a uma necessidade dos usuários, em certos momentos, pode ser necessário adiantar a execução de uma dessas tarefas de forma manual. Para atender a esta necessidade de “execução adiantada”, a estrutura abaixo foi feita: GerenciadorTarefas: Classe responsável pela execução de uma determinada tarefa baseada em seu próprio código ─ é a classe de “caso de uso”; RecuperadorTarefas: Classe responsável pela abstração da recuperação das tarefas do banco de dados e retorno dos objetos de domínio ─ é a classe “repositório”. Tarefa: Classe que representa uma “tarefa” no sistema ─ é a “entidade de domínio”. Veja o exemplo abaixo: public class GerenciadorTarefas { private static boolean TAREFA_PROCESSADA = true; private static boolean TAREFA_NAO_PROCESSADA = false; private RecuperadorTarefas recuperadorTarefas; public GerenciadorTarefas(RecuperadorTarefas recuperadorTarefas) { this.recuperadorTarefas = recuperadorTarefas; } public boolean executaTarefaPeloCodigo(Integer codigoTarefa) { Tarefa tarefa = recuperadorTarefas.recuperaPeloCodigo(codigoTarefa); if (tarefa == null) { return TAREFA_NAO_PROCESSADA; } try { tarefa.iniciaProcesso(); return TAREFA_PROCESSADA; } catch (TarefaInterrompidaException e) { return TAREFA_NAO_PROCESSADA; } } } O código acima pode não ser o melhor exemplo, mas expressa bem a sua lógica de domínio. Agora, vamos aplicar a observabilidade no nosso método executaTarefaPeloCodigo. Para isto, vamos imaginar duas bibliotecas em nosso projeto: Log: É uma biblioteca genérica de logs, útil para atividades de throubleshooting por parte das pessoas desenvolvedoras. Analytics: É uma biblioteca genérica de eventos que metrifica interações de um usuário a uma determinada funcionalidade. public boolean executaTarefaPeloCodigo(Integer codigoTarefa) { Tarefa tarefa = recuperadorTarefas.recuperaPeloCodigo(codigoTarefa); if (tarefa == null) { Log.warn("A tarefa %d não existe, portanto, seu processo não foi iniciado.", codigoTarefa); return TAREFA_NAO_PROCESSADA; } try { Log.info("Processo da tarefa %d foi iniciado.", codigoTarefa); Analytics.registraEvento("tarefa_iniciada", tarefa); tarefa.iniciaProcesso(); Log.info("Processo da tarefa %d foi finalizado.", codigoTarefa); Analytics.registraEvento("tarefa_finalizada", tarefa); return TAREFA_PROCESSADA; } catch (TarefaInterrompidaException e) { Log.error(e, String.format("Processo da tarefa %d foi interrompido.", codigoTarefa)); Analytics.registraEvento("tarefa_interrompida", tarefa); return TAREFA_NAO_PROCESSADA; } } Agora, além da execução da regra de negócio previamente expressa pelo código, também estamos lidando com diversas chamadas de logs e análises sobre o uso desta funcionalidade. Analisando, não do ponto de vista da instrumentação da observabilidade, mas tecnicamente, com certeza, a manutenibilidade deste código caiu. Primeiro que se essa implementação for crucial para o negócio, ela deveria ser garantida com testes unitários. Além disso, a regra de negócio, que antes era claramente expressa, agora, está ofuscada com o uso dessas bibliotecas. Cenários como este são comuns de se ver nos mais diversos sistemas e, geralmente, não parece soar muito bem um “código voltado à observabilidade” e um “código voltado ao domínio”, juntos. Então, existe solução? Vamos entender melhor a seguir. Solução para o Case de Observabilidade Pensando na legibilidade do código escrito, instintivamente, acabamos pensando na criação de pequenos métodos que abstraiam esse conteúdo confuso de dentro do executaTarefaPeloCodigo, isolando o código voltado ao domínio do código voltado às análises. Porém, neste caso, a observabilidade introduzida é um requisito do negócio, portanto, mesmo sendo um “código voltado às análises”, ele continua sendo um “código voltado ao domínio”. Entenda melhor na imagem abaixo: Ou seja, nem todo código voltado ao domínio é voltado à observabilidade e nem todo código voltado à observabilidade é voltado ao domínio, mas há, em alguns casos, uma intersecção entre estes, como no nosso case apresentado. Por fim, também recomendamos fortemente a extração das Strings “mágicas”, pois torna a leitura mais agradável e mais fácil de entender o que cada uma representa. Talvez a introdução de alguns ENUMs também seja válida para abstrair o que seria os “trackings de eventos”, como tarefa_iniciada e tarefa_finalizada, mas não vamos nos aprofundar neste assunto, pois não é o foco. public boolean executaTarefaPeloCodigo(Integer codigoTarefa) { Tarefa tarefa = recuperadorTarefas.recuperaPeloCodigo(codigoTarefa); if (tarefa == null) { metrificaQueTarefaNaoExiste(codigoTarefa); return TAREFA_NAO_PROCESSADA; } try { metrificaQueTarefaFoiIniciada(tarefa); tarefa.iniciaProcesso(); metrificaQueTarefaFoiFinalizada(tarefa); return TAREFA_PROCESSADA; } catch (TarefaInterrompidaException e) { metrificaQueTarefaFoiInterrompida(tarefa); return TAREFA_NAO_PROCESSADA; } } private void metrificaQueTarefaNaoExiste(Integer codigoTarefa) { Log.warn(MENSAGEM_TAREFA_INEXISTENTE, codigoTarefa); } private void metrificaQueTarefaFoiIniciada(Tarefa tarefa) { Log.info(MENSAGEM_TAREFA_INICIADA, tarefa.getCodigo()); Analytics.registraEvento(TAREFA_INICIADA, tarefa);} private void metrificaQueTarefaFoiFinalizada(Tarefa tarefa) { Log.info(MENSAGEM_TAREFA_FINALIZADA, codigoTarefa); Analytics.registraEvento(TAREFA_FINALIZADA, tarefa);} private void metrificaQueTarefaFoiInterrompida(Tarefa tarefa) { Log.error(e, String.format(MENSAGEM_TAREFA_INTERROMPIDA, codigoTarefa)); Analytics.registraEvento(TAREFA_INTERROMPIDA, tarefa);} Este é um bom começo, com o código de domínio voltando a ser bem escrito ─ isso, claro, se você considerar que seu “código de domínio” é apenas o método executaTarefaPeloCodigo. Observando nossa classe, não leva muito tempo para notarmos que fizemos uma troca. Se extrairmos de dentro do método original vários outros métodos de metrificação os quais não se encaixam com o objetivo principal da classe GerenciadorTarefas, estamos apenas “jogando o problema para debaixo do tapete”. Quando algo assim acontece, geralmente nos indica que uma nova classe está querendo emergir. Portanto, talvez, a mais simples solução seja a segregação dessa classe em duas: uma para lidar com as métricas e outra para o processamento das tarefas. Ou seja, nossa proposta é a criação de uma nova classe responsável especificamente pelas análises e logs da aplicação, assim como demonstrado no desenho abaixo. Esta também é uma boa solução pois a segregação das responsabilidades originais e o encapsulamento das funções de métricas em uma nova classe, somado à possível injeção de dependências introduzida, favorece o design para testabilidade do GerenciadorTarefas, que é detentor das nossas regras de domínio. Podemos reforçar ainda mais essa ideia pensando no fato de que Java é uma linguagem orientada a objetos (POO) e a testabilidade de uma classe que utiliza de métodos estáticos é reduzida caso o método modifique um estado externo a si, e, geralmente, bibliotecas de logs atendem a este requisito. Desta forma, o resultado do nosso GerenciadorTarefas seria o seguinte: public class GerenciadorTarefas { private static boolean TAREFA_PROCESSADA = true; private static boolean TAREFA_NAO_PROCESSADA = false; private RecuperadorTarefas recuperador; private MetificadorTarefas metrificador; public GerenciadorTarefas(RecuperadorTarefas recuperador, MetificadorTarefas metrificador) { this.recuperador = recuperador; this.metrificador = metrificador; } public boolean executaTarefaPeloCodigo(Integer codigoTarefa) { Tarefa tarefa = recuperador.recuperaPeloCodigo(codigoTarefa); if (tarefa == null) { metrificador.metrificaQueTarefaNaoExiste(codigoTarefa); return TAREFA_NAO_PROCESSADA; } try { metrificador.metrificaQueTarefaFoiIniciada(tarefa); tarefa.iniciaProcesso(); metrificador.metrificaQueTarefaFoiFinalizada(tarefa); return TAREFA_PROCESSADA; } catch (TarefaInterrompidaException e) { metrificador.metrificaQueTarefaFoiInterrompida(tarefa); return TAREFA_NAO_PROCESSADA; } }} O processo de segregação da classe GerenciadorTarefas e o encapsulamento das métricas é chamado de Observabilidade Orientada ao Domínio, e a nova classe gerada é o nosso tão cobiçado Domain Probe. O nome deste padrão de projetos, “Domain Probe”, remete à “Sonda de Domínio”. Este nome não poderia ser mais adequado visto que nossa classe literalmente age como uma “sonda”, em uma classe que anteriormente carecia do levantamento de métricas. Como testar a observabilidade orientada a domínio? Antes de testar a observabilidade de fato, vamos retomar a primeira versão da nossa classe, e tentar imaginar um cenário de teste. public class GerenciadorTarefas { private static boolean TAREFA_PROCESSADA = true; private static boolean TAREFA_NAO_PROCESSADA = false; private RecuperadorTarefas recuperador; public GerenciadorTarefas(RecuperadorTarefas recuperador) { this.recuperador = recuperador; } public boolean executaTarefaPeloCodigo(Integer codigoTarefa) { Tarefa tarefa = recuperador.recuperaPeloCodigo(codigoTarefa); if (tarefa == null) { return TAREFA_NAO_PROCESSADA; } try { tarefa.iniciaProcesso(); return TAREFA_PROCESSADA; } catch (TarefaInterrompidaException e) { return TAREFA_NAO_PROCESSADA; } }} Se você está acostumado a fazer este tipo de análise, vai perceber alguns cenários: Ou não existe tarefa com o código informado, retornando FALSE; Ou existe tarefa e seu processamento é concluído, retornando TRUE; Ou existe tarefa e seu processamento é interrompido, retornando FALSE; Para simplificar, vamos utilizar apenas o terceiro cenário como exemplo. Abaixo, podemos observar como seria a implementação desta classe de testes. public class GerenciadorTarefasTest { private static final Integer CODIGO_TAREFA = 1; private GerenciadorTarefas gerenciadorTarefas; private RecuperadorTarefas recuperador; @BeforeEach public void setUp() { this.recuperador = Mockito.mock(RecuperadorTarefas.class); this.gerenciadorTarefas = new GerenciadorTarefas(recuperador); } @Test public void deveRetornarFalso_casoOcorraErroDeProcessamento_quandoExistirTarefaComCodigoInformado() throws TarefaInterrompidaException { doReturn(criaTarefaComExcecaoEmbutida()).when(recuperador).recuperaPeloCodigo(eq(CODIGO_TAREFA)); Boolean foiExecutado = gerenciadorTarefas.executaTarefaPeloCodigo(CODIGO_TAREFA); assertFalse(foiExecutado); } private Tarefa criaTarefaComExcecaoEmbutida() throws TarefaInterrompidaException { Tarefa tarefa = Mockito.spy(new Tarefa(CODIGO_TAREFA)); doThrow(new TarefaInterrompidaException()).when(tarefa).iniciaProcesso(); return tarefa; } } Seguindo o padrão GWT de nomenclatura (Given - When - Then), podemos expressar nossa regra de negócio no teste. Porém, vale mencionar que aqui estamos traduzindo e “abrasileirando” a escrita da GWT (Given - When - Then), transformando em “DCQ” (Deve ─ Caso ─ Quando). Dessa forma, usamos o DCQ significa: “Deve retornar falso”, que é equivalente à “Then returns false”; “Caso ocorra erro de processamento”, que equivale à expressão “When a processing error occurs”; “Quando existir tarefa com o código informado”, que representa o mesmo que “Given an existing task with the informed code”. A partir disso, quando reimplementamos nossa observabilidade, nossa classe GerenciadorTarefas volta a ser assim: public class GerenciadorTarefas { private static boolean TAREFA_PROCESSADA = true; private static boolean TAREFA_NAO_PROCESSADA = false; private RecuperadorTarefas recuperador; private MetificadorTarefas metrificador; public GerenciadorTarefas(RecuperadorTarefas recuperador, MetificadorTarefas metrificador) { this.recuperador = recuperador; this.metrificador = metrificador; } public boolean executaTarefaPeloCodigo(Integer codigoTarefa) { Tarefa tarefa = recuperador.recuperaPeloCodigo(codigoTarefa); if (tarefa == null) { metrificador.metrificaQueTarefaNaoExiste(codigoTarefa); return TAREFA_NAO_PROCESSADA; } try { metrificador.metrificaQueTarefaFoiIniciada(tarefa); tarefa.iniciaProcesso(); metrificador.metrificaQueTarefaFoiFinalizada(tarefa); return TAREFA_PROCESSADA; } catch (TarefaInterrompidaException e) { metrificador.metrificaQueTarefaFoiInterrompida(tarefa); return TAREFA_NAO_PROCESSADA; } }} É importante lembrarmos aqui que nenhum comportamento foi alterado com o incremento da observabilidade. Portanto, o teste feito anteriormente continua cumprindo seu papel mesmo estando desatualizado. No máximo, o que ocorreria neste caso é um erro de compilação, que já serviria de aviso aos testes que esta classe agora possui uma nova dependência. Sendo um incremento da nossa regra de negócio original, nada mais justo do que incrementar os testes garantindo as invocações corretas de nosso instrumentador. Veja o exemplo a seguir: public class GerenciadorTarefasTest { private static final Integer CODIGO_TAREFA = 1; private GerenciadorTarefas gerenciadorTarefas; private RecuperadorTarefas recuperador; private MetificadorTarefas metrificador; @BeforeEach public void setUp() { this.recuperador = Mockito.mock(RecuperadorTarefas.class); this.metrificador = Mockito.mock(MetificadorTarefas.class); this.gerenciadorTarefas = new GerenciadorTarefas(recuperador, metrificador); } @Test public void deveRetornarFalso_casoOcorraErroDeProcessamento_quandoExistirTarefaComCodigoInformado() throws TarefaInterrompidaException { doReturn(criaTarefaComExcecaoEmbutida()).when(recuperador).recuperaPeloCodigo(eq(CODIGO_TAREFA)); Boolean foiExecutado = gerenciadorTarefas.executaTarefaPeloCodigo(CODIGO_TAREFA); Mockito.verify(metrificador, times(1)).metrificaQueTarefaFoiIniciada(any()); Mockito.verify(metrificador, times(1)).metrificaQueTarefaFoiInterrompida(any()); Mockito.verifyNoMoreInteractions(metrificador); assertFalse(foiExecutado); } private Tarefa criaTarefaComExcecaoEmbutida() throws TarefaInterrompidaException { Tarefa tarefa = Mockito.spy(new Tarefa(CODIGO_TAREFA)); doThrow(new TarefaInterrompidaException()).when(tarefa).iniciaProcesso(); return tarefa; } } Aproveitando a dependência de um instrumentador dentro do nosso GerenciadorTarefas, podemos ainda injetar uma classe falsa para verificar apenas o número de invocações de cada método. No teste acima, verificamos se os métodos metrificaQueTarefaFoiIniciada e metrificaQueTarefaFoiInterrompida foram invocados, e então garantimos que mais nenhuma outra interação é feita com nossa classe instrumentadora. Assim, caso uma nova métrica surja, haja refatoração ou mudança na regra de negócio, teremos testes que garantem aquilo que o negócio espera, ou esperava. Opinião do Autor Este artigo é, em grande parte, uma releitura do estudo Domain-Oriented Observability, escrito por Pete Hodgson em 2019, e também inclui a visão de diversos outros autores sobre o assunto, inclusive a opinião pessoal do autor, Felipe Luan Cipriani, tech writer convidado pelo grupo Softplan.. Quando li o artigo de referência “Domain-Oriented Observability” pela primeira vez, não me surpreendi com algo revelador, pois já conhecia o método. Porém, depois de algumas conversas com colegas próximos e mais algumas tentativas de compreender a totalidade do artigo, percebi como o subestimei. Domain Probe não aborda encapsulamento, segregação ou injeção de dependência ─ embora estes sejam todos elementos que o compõem ─, mas sim a importância das métricas, e sua relevância para o negócio. E embora o padrão de projeto Domain Probe tenha semelhanças com um Facade, ele se preocupa com a essência de todo sistema: o domínio. Por isso, ele tem seu valor. Este é um padrão de projetos essencial de se conhecer e aplicar onde quer que haja instrumentos de métricas em um domínio que não tenha sido feito ou pensado para ser fácil de ler, interpretar, ou dar manutenção. Afinal, desenvolvedores passam mais tempo lendo códigos do que escrevendo. Além disso, este é um padrão de projetos com extrema flexibilidade no quesito de granularidade. Ou seja, você pode criar desde um Domain Probe para cada classe de domínio, sendo esta abordagem mais “específica”, a até mesmo um Domain Probe “genérico”. Não existe uma abordagem errada, apenas diferentes abordagens. Outro tipo de implementação de uma Observabilidade Orientada ao Domínio é através de eventos. Neste cenário, o padrão de projetos da vez é o Observer, e sua abordagem é igualmente interessante, valendo a pena um artigo dedicado somente a ele. Por fim, agradeço a você, caro(a) leitor(a), pelo seu tempo e interesse. Recomendo que leia os artigos dos links presentes no decorrer deste artigo e, se você gostou do conteúdo, tem alguma dúvida ou deseja iniciar uma discussão sobre a temática, deixe seu comentário abaixo!

Caching: o que é e como funciona
Tech Writers Fevereiro 27, 2023

Caching: o que é e como funciona

Atualmente, quando utilizamos sistemas para gerenciar informações, necessitamos cada vez mais de dados precisos e rápidos, e com isso criamos um paradoxo entre quantidade x velocidade.  Os usuários de sistemas buscam por informações mais rápidas para otimizar melhor o tempo de seus processos. No entanto, associa-se a velocidade também à quantidade de informações e estas duas necessidades acabam conflitando.   Isso porque quanto maior a quantidade de informações requeridas, a velocidade de processamento ou disponibilidade destas informações diminuem consideravelmente.  Diante deste cenário, como poderíamos conciliar tais distintas e acopladas demandas?  O que é caching?  Caching é uma técnica de armazenamento intermediário de dados da aplicação, feitos através de hardware ou software. Ela serve para prover um acesso mais rápido a determinadas informações do que acessar diretamente a base de dados da aplicação.  Enquanto uma base de dados é focada em gerir as informações, o cache tem como direcionamento a leitura destes dados, não se preocupando com demais operações, pois esta tarefa já está sendo atribuída.  Com isso temos um acesso mais rápido e direto, ganhando em tempo e performance do acesso a estes dados.  Caching é uma importante feature para as aplicações, pois ganha em velocidade e performance na obtenção dos dados. Entretanto existe um grande “depende” nesta solução, pois, necessariamente nem todas as aplicações realmente necessitam do uso de caching. Antes de aplicarmos tal conceito devemos sempre analisar a aplicação e a real necessidade perante o uso de caching.  Devo utilizar caching na minha aplicação?  Sempre é importante fazer esse questionamento para evitar trabalho desnecessário. Veja algumas questões importantes a considerar:  Eu realmente preciso melhorar a performance da minha aplicação?  Os meus usuários estão insatisfeitos com a performance?  Seria possível alcançar a performance que desejo de outra maneira? Por exemplo, otimizando consultas, criando índices no banco e alterando estrutura dos dados.  Estas e outras questões podem nos ajudar a validar se realmente temos a necessidade de utilizar caching em nossa aplicação.  Onde posso utilizar caching?  1 - Sistemas com foco na leitura de dados  Consiste em sistemas que a quantidade de leitura dos dados é significativamente   maior do que a quantidade de escrita. Desse modo, o uso de caching pode ser uma solução para escalar tal aplicação.  2 - Tolerância do estado do dado  Sistemas que contém dados que não precisam apresentar a sua versão atual e que possam ser atualizados na base e na aplicação, além de não precisarem de atualização por determinado tempo. Nestes casos, o cache pode ser uma solução para armazenar um valor determinado.  3 - Dados que não se alteram frequentemente  Para sistemas que os dados não se atualizam com frequência, o caching pode ser utilizado armazenar por um determinado tempo e consultar sempre de acordo com a necessidade da aplicação.  Eventos de caching  Podemos classificar o cache tendo dois tipos de eventos: Hit e Miss.  Hit  O dado buscado se encontra no cache quando a aplicação efetua a consulta, obtendo uma resposta mais rápida e leve.  Miss  O dado buscado pela aplicação não se encontra no cache, fazendo com que a aplicação tenha que buscá-lo diretamente na base de dados efetuando uma chamada adicional.  Principais estratégias de caching  Existem algumas estratégias de caching que podem ser utilizadas para efetuar o processo de caching. As mais comuns são:  Cache-aside Pattern  Esta estratégia de leitura consiste na aplicação com acesso a ambas as bases: cache e database. Ela se baseia na aplicação buscando o dado no cache e retornando para a aplicação. Porém se este dado não for encontrado no cache, a aplicação vai buscar diretamente da base dados e retornar para a aplicação, e posteriormente inserir na base de cache.  Read through / Lazy Loading  Esta estratégia de leitura consiste na aplicação que não tem acesso a base de dados, apenas a base de cache. Ela solicita o dado ao cache e, caso encontre, prossegue retornando-o para a aplicação. Caso não consiga encontrar a informação, o próprio cache vai até a base, encontra o dado solicitado e o insere na base de cache, e só então retorna-o para a aplicação.  Read-Through é uma estratégia muito semelhante a Cache-aside, mas a diferença é que nesta estratégia a aplicação sempre irá buscar da base de cache.  Write through  Esta estratégia de escrita consiste no cache que consegue armazenar todos os dados da base, que sempre devem ser atuais.  Toda vez que a aplicação escreve algum dado, primeiramente ele armazena no cache e depois armazena no banco de dados. Dessa forma, o cache sempre tem a versão mais recente da informação sendo uma réplica da base de dados. Esta aplicação sempre lê apenas da base de cache.  Write through é voltada para sistemas onde a leitura não pode ser em hipótese alguma obsoleta. Entretanto, podem existir dados armazenados e não lidos já que ele acaba armazenando tudo.  Write-back (Write-behind)  Nesta estratégia de escrita, o dado não é escrito na base imediatamente, pois a aplicação segue escrevendo no cache e depois de um certo tempo sincroniza na base dados, atuando em lotes de informações a serem inseridas.  Um dos problemas desta estratégia é que se o cache tiver algum problema, os dados que ainda não foram sincronizados serão perdidos. Além disso, se houver algum tipo de operação direta no banco de dados esta operação pode não utilizar a versão atualizada dos dados.  Caching implemetation  Para aplicarmos as estratégias de cache apresentadas anteriormente, devemos escolher uma implementação de caching. Existem várias alternativas e desde que o local de armazenamento do cache seja mais rápido do que o acesso ao banco, já é de grande valor.  Quando estamos falando de cache, geralmente o seu armazenamento é feito através de “chave/valor”.  Abaixo apresentaremos 3 tipos comuns de implementação de caching.  In-Memory  In Memory caching consiste no armazenamento de dados de caching na própria memória do serviço. Este formato é o mais rápido, pois trabalha com um acesso direto, assim como uma simples variável da aplicação.  Apesar de ser o mais rápido e fácil de implementar, também traz alguns problemas. Por exemplo, por armazenar na memória do serviço se o mesmo acabar caindo, os dados de cache serão perdidos também.  Esta implementação é recomendada quando lidamos com serviços únicos ou menores, e que tenham poucos dados a serem armazenados no cache.  Remote  Nesta implementação os dados de caching são armazenados em um serviço externo, como o Redis ou Memcached, e não vinculado ao serviço de aplicação.  Neste formato, o dado se torna resiliente a queda do serviço de aplicação, pois é desacoplado do mesmo e tem seu próprio serviço.  Este modelo de implementação se faz robusto e recomendado para quando se tem dados oriundos de vários serviços distintos ou em grande.  Remote Distributed  Ambos os modelos de implementações citados acima sofrem quando o assunto é escalabilidade. A quantia de dados que podem ser armazenados em cada implementação é limitada, e isso acontece porque ambos dependem apenas de um único servidor, seja ele local ou externo.  Porém, quando necessitamos gerenciar maiores quantidades de dados, podemos usar o modelo de implementação externo e distribuído, onde distribui-se o cache entre múltiplas instâncias do servidor de cache.  Se a quantidade atual for insuficiente, então é possível adicionar novos cluster e com isso ter meios de escalar a quantidade de dados possíveis a serem armazenados, facilitando a escalabilidade deste serviço de caching.  Conclusão  Caching é um conceito fácil de compreender, sua implementação também é simples e os resultados aparecem já com pequenas aplicações, independente da estratégia e do modelo utilizado.  Mas nem sempre será o salvador de uma aplicação e necessariamente não são todas que devem utilizar desta estratégia. Porém, se este for o caso, é de grande ajuda utilizá-la.  Referências  https://kislayverma.com/software-architecture/architecture-patterns-caching-part-1/ https://blog.devgenius.io/caching-strategy-101-3bc974d2a6cd https://levelup.gitconnected.com/avoid-using-cache-in-your-application-or-do-it-right-9650214797bc https://dev-abhishek-gautam.medium.com/the-definitive-guide-to-caching-f7441f6932b7

Entenda o Hackathon: O que é e qual é a sua importância
Tech Writers Fevereiro 14, 2023

Entenda o Hackathon: O que é e qual é a sua importância

Tanto para pessoas que estão buscando desafios no mercado, quanto para empresas que precisam de alternativas fora da caixa, o Hackathon é um ótimo caminho.  O Hackathon é capaz de contribuir com soluções inovadoras, pois promove ricas discussões e muito desenvolvimento entre profissionais. Se você ainda não sabe do que se trata um Hacksthon, fique comigo até o fim deste artigo.  O que é um Hackathon?    A origem do termo Hackathon se deu pela combinação das palavras programar e maratona.  Hack (programar)    Marathon (maratona)    Os Hackathons são eventos que reúnem pessoas interessadas em trabalhar questões específicas desenvolvendo soluções de forma rápida e única.    Embora a palavra Hackathon tenha origem na palavra programar, não são eventos focados apenas em programadores (pelo menos não mais). Atualmente, contam com a contribuição de outros profissionais, principalmente os especialistas em inovação, gestores, designers, desenvolvedores e usuários.    Nos Hackathons são discutidas ideias e projetos a serem desenvolvidos, considerando sempre as opiniões, os recursos e também os conhecimentos dos profissionais participantes.    De forma sintetizada, podemos dizer que a importância desses eventos se dá por todas as suas capacidades, dentre as quais destaco três:    O incentivo da produção e do trabalho coletivo;   A integração de várias frentes no desenvolvimento do projeto;   Soluções inovadoras.    Por esses e outros motivos, um Hackathon é uma excelente forma de fomentar a inovação nas empresas.     Quem pode participar dos Hackathons?    Geralmente o evento reúne profissionais que possuem relação com tecnologia, inovação e desenvolvimento de novas soluções, mas não há restrições com relação aos participantes, já que estes eventos são propícios para grandes aprendizados.    Curiosidade sobre o Hackathon:    É bastante comum a participação interna e externa, ou seja, profissionais de dentro e de fora das empresas, sendo essa característica muito positiva para reunir conhecimento e gerar bons resultados. Aliás, os bons resultados dos Hackathons são os motivos pelos quais profissionais de áreas como o Recursos Humanos usam-os como forma de treinamento e desenvolvimento dos colaboradores de todos os setores das organizações.    O planejamento de um Hackathon    Não há um padrão no planejamento de um Hackathon. As diretrizes do planejamento ficam a critério de cada empresa ou projeto. Lembrando somente que tudo deve estar alinhado com os objetivos.    No entanto, vale ressaltar a existência de alguns pilares de planejamento. Vejamos:      Identificação do problema/dor  A identificação do problema/dor é o primeiro passo para planejar um Hackathon, pois, com isso, é possível definir o objetivo esperado do evento.   Formato do evento   Além do modelo de evento corporativo, ele também pode acontecer no formato de competição entre as equipes.   Regras e orientações    Para que o planejamento aconteça de forma correta, é importante definir as regras para participação e desenvolvimento ainda no começo.    Público, data e local   Outro ponto importante é a definição dos convidados, do momento e do local de realização do Hackathon.   Intervalos e descansos    Para que um planejamento e desenvolvimento seja efetivo, é preciso prever descansos e intervalos para toda a equipe.    Comunicação e divulgação   Fazer um bom plano para divulgar o Hackathon é fundamental para atrair os melhores profissionais do mercado e alcançar os objetivos.   Agora que você já sabe o que é um Hackathon, deixe um comentário sobre como este artigo te ajudou e compartilhe com colegas que também possam se interessar por ele.