<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Arquivo de Software - Blog da Alice Tech</title>
	<atom:link href="https://alice.com.br/tech/software/feed/" rel="self" type="application/rss+xml" />
	<link>https://alice.com.br/tech/software/</link>
	<description>Acompanhe conteúdos sobre tecnologia, IA e inovação na saúde e descubra como a Alice transforma o cuidado diário em uma rotina mais humanizada.</description>
	<lastBuildDate>Thu, 19 Feb 2026 18:43:50 +0000</lastBuildDate>
	<language>pt-BR</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
		<item>
		<title>Cultura de IA: como a Alice inova no dia a dia</title>
		<link>https://alice.com.br/tech/como-a-alice-esta-construindo-uma-cultura-de-ia-no-seu-dia-a-dia/</link>
		
		<dc:creator><![CDATA[Bruno Federowski]]></dc:creator>
		<pubDate>Tue, 30 Jul 2024 19:45:54 +0000</pubDate>
				<category><![CDATA[Software]]></category>
		<guid isPermaLink="false">https://alice.com.br/tech/?p=194</guid>

					<description><![CDATA[<p>Todo time em uma empresa de tecnologia deveria usar AI cotidianamente. Como fazemos isso acontecer?</p>
<p>O post <a href="https://alice.com.br/tech/como-a-alice-esta-construindo-uma-cultura-de-ia-no-seu-dia-a-dia/">Cultura de IA: como a Alice inova no dia a dia</a> apareceu primeiro em <a href="https://alice.com.br/tech">Blog da Alice Tech</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>A Alice acredita que inteligência artificial (IA) deve  permear tudo que fazemos. Como garantimos que isso acontece? Essa é a parte complexa.</p>
<p>Com avanços em IA surgindo diariamente, fica cada vez mais evidente o seu impacto disruptivo. A IA vai transformar indústrias, gerar novas oportunidades, impulsionar a produtividade ao longo de todos os setores e abrir as portas para uma nova era das empresas de tecnologia.</p>
<p>Enquanto startups que têm IA em seu DNA nascem todo dia, companhias de setores tradicionais precisam se adaptar rapidamente a esse novo contexto. É um desafio análogo ao nascimento dos primeiros computadores, e realizar uma mudança cultural tão importante exige um esforço imenso.</p>
<h2><b>A Alice e IA</b></h2>
<p>A Alice é um plano de saúde para empresas que permite que os seus membros (clientes) naveguem pelo sistema de saúde de forma coordenada entre os três diferentes níveis de atenção: primária, secundária e terciária. Fazemos isso direcionando os nossos membros aos agentes mais custo-efetivos do sistema de saúde – membros com condições simples podem ser tratados por enfermeiras e médicos de família, enquanto aqueles com sintomas graves deveriam rapidamente se consultar com os especialistas.</p>
<p>Abordagens baseadas em machine learning e dados sempre foram centrais para essa missão. Quando a Alice foi fundada, isso significava modelos proprietários construídos por nosso time interno de cientistas de dados, e um grande foco em análise de dados.</p>
<p>Mas a ascensão da IA generativa mudou isso. Em vez de depender de um time específico, a nova geração de produtos permite que todo funcionário da Alice faça uso de modelos no estado da arte. Seja incorporando modelos de terceiros diretamente em nossos produtos – para, por exemplo, resumir dados médicos baseados em transcrições de consultas em áudio – ou por aplicações de dia-a-dia que nos permitem reduzir burocracia, a IA deveria ter uma presença constante em como trabalhamos.</p>
<p>Um <a href="https://static1.squarespace.com/static/5d35e72fcff15f0001b48fc2/t/668d08608a0d4574b039bdea/1720518756159/chatgpt-full.pdf">estudo recente</a> mostrou que a adoção do ChatGPT foi ampla, mas desigual. Muitos funcionários precisam de treinamento e direcionamento para aproveitar completamente os aumentos de produtividade, e muitos são prejudicados por restrições das empresas em que trabalham.</p>
<p>Não cair nessas armadilhas exige uma mudança cultural importante. Product managers (PMs) e times operacionais deveriam enxergar a IA como a primeira solução para todo problema com que se deparam. Isso também significa que o uso de IA deveria ser tão simples quanto possível e não exigir expertise técnica.</p>
<h2><b>Transformação cultural</b></h2>
<p>Para fortalecer a ideia de que recorrer à IA é simples e esperado, organizamos eventos que chamamos de &#8220;AI Day&#8221;, envolvendo toda a empresa.</p>
<p>Durante todo um dia de trabalho, times de todas as áreas se reuniram em nosso escritório e trabalharam em implementar vários protótipos de aplicações de IA. Esses protótipos poderiam ser lançados no mesmo dia, ou poderiam ser um ponto de partida para um ciclo normal de desenvolvimento. Os times contaram com o apoio de membros de nossas equipes de engenharia e dados, assim como outros funcionários da Alice que já haviam adotado IA como uma ferramenta de trabalho cotidiano.</p>
<p>Antes desses eventos, os participantes levantaram ideias para vários protótipos em uma planilha comum, a serem validados por aqueles que lideraram a iniciativa. Esses projetos variavam dos mais simples, como classificar dados de exames com base em texto não estruturado, aos mais complexos, como gerar um banco de dados com uma ferramenta de busca usando todo o histórico médico de membros.</p>
<p>Fornecemos uma conta no ChatGPT aos participantes com acesso a assistants. No fim de cada dia, eles apresentaram seus projetos a todo mundo presente no evento.</p>
<p>Tivemos três objetivos com essa iniciativa: ensinar a todos como usar IA numa base cotidiana e incorporar essa possibilidade em seu raciocínio; aumentar o ritmo de geração de novas aplicações de IA; e identificar que ferramentas nosso time de engenharia deveria desenvolver para incentivar a adoção de IA.</p>
<p>Esses esforços foram em grande parte bem-sucedidos. Vários dos protótipos desenvolvidos em nosso primeiro AI Day se tornaram projetos completos, e muitos outros foram implementados imediatamente. Temos visto times que não são tradicionalmente de tech usando IA em seu dia a dia, e geramos um novo roadmap para o time de Foundation em engenharia com entregáveis claros que vão impulsionar a produtividade daqueles que trabalham com IA.</p>
<p>Com isso, vieram aprendizados importantes:</p>
<ul>
<li>Depois que a porteira está aberta, é difícil segurar a boiada. Um dos principais fatores que levam times fora de tecnologia a relutarem em usar IA é que eles precisam adaptar seu pensamento a uma nova ferramenta. Quebrar essa barreira rapidamente leva a um uso acelerado;</li>
<li>Transicionar para um modelo em que IA é uma parte central de como trabalhamos exige quebrar dependências. Se funcionários da Alice precisam contatar os times de dado ou engenharias para usar IA, isso significa que estamos fazendo algo errado;</li>
<li>IA pode ser transformador com produtos de larga escala, sim, mas uma parte importante do valor vem da soma de muitas aplicações pequenas. Aumentar eficiência em todos os lados da companhia pode ser tão impactante quanto desenvolver um novo produto de IA.</li>
</ul>
<h2><b>IA como plataforma</b></h2>
<p>Nossa experiência com os AI Days nos fez dividir nossos esforços para facilitar o uso de IA em duas frentes: primeiro, precisávamos simplificar o teste de novas aplicações; segundo, precisávamos fazer com que lançar novos produtos de IA fosse tão fácil quanto possível, sem abrir mão de qualidade, controle de custo ou privacidade.</p>
<p>Na primeira frente, nosso time de Foundation em engenharia começou a desenvolver uma plataforma de testes que permitirá que nossos usuários cumpram várias tarefas que hoje são difíceis em um ambiente no-code:</p>
<ul>
<li>Rodar prompts de IA que são dinamicamente atrelados a dados de teste em batch. Por exemplo, um usuário pode subir um arquivo com comentários do NPS e pedir que a plataforma rode um prompt, atribuindo a cada um deles uma classificação;</li>
<li>Otimizar prompts em escala comparando o resultado de diferentes prompts sobre um conjunto de arquivos; diferentes contextos sobre um único prompt; etc.</li>
<li>Conectar diretamente a nossa camada analítica pelo Metabase, garantindo que usuários não precisam inserir manualmente dados de teste;</li>
<li>Gerar workflows de diferentes modelos de IA. Por exemplo, transcrever um áudio e em seguida enviar essa transcrição a um modelo de texto;</li>
<li>Controles de custo e acesso por meio de uma estrutura de times que atribui orçamentos específicos para cada unidade;</li>
<li>Salvar e comentar em experimentos passados, permitindo que usuários mantenham um histórico dos últimos testes de seu time;</li>
<li>Fazer uso de nossa infraestrutura de anonimização e privacidade para garantir que respeitemos nossas regras de governança.</li>
</ul>
<p>Adotamos a estratégia de lançar iterações da plataforma rapidamente e testar com usuários. Representantes de produto, operações e até nossa equipe médica foram os clientes e tiveram a responsabilidade de validar nossos planos e evangelizar seus times.</p>
<p>Enquanto isso, também precisávamos facilitar o deploy de aplicações que se conectassem diretamente a nossos produtos. Por sorte, trabalhar com a nova geração de LLMs é simples, e nos concentramos em garantir que os dados inseridos e gerados por esses modelos passem pelos mesmos processos que nossos dados em produção.</p>
<h2><b>O futuro</b></h2>
<p>A Alice acredita que IA é o futuro, e que ocupamos uma posição única que nos permite nos beneficiar de novos desenvolvimentos. Como um payvidor que atua em toda a jornada de saúde e tem acesso a dados de fontes muito diversas, produtos de dados deveriam ser tão centrais para nós quanto nossa operação médica.</p>
<p>Em uma publicação futura, vamos explorar os detalhes da arquitetura descrita nas últimas sessões. Mas já demos passos largos em adotar uma cultura que coloca IA no centro com nossos esforços institucionais para educar os times e com o desenvolvimento rápido de ferramentas para incentivar a adoção. O futuro é animador e há muito mais a ser feito, tanto em termos dos planos da própria Alice quanto do desenvolvimento de LLMs como um todo.</p>
<hr>
<h2>How Alice is building a culture of &#8216;AI as a go-to solution&#8217;</h2>
<p>Alice believes that AI should permeate every aspect of what we do. How do we make sure that this is the case? That&#8217;s the hard part.</p>
<p>As advances in AI technology pop up daily, claims of its transformative impact pile up. AI is set to disrupt established industries, foster new opportunities, drive up productivity across the board and usher in a new era for tech companies.</p>
<p>While startups that make AI as part of their DNA are born everyday, incumbents in traditional sectors have to quickly adapt to the new environment. That is a challenge analogous to the advent of the first computers, and bringing about such a major culture change requires major effort.</p>
<h3><b>Alice and AI</b></h3>
<p>Alice is a healthcare company that provides direct access to our own primary care physicians as well as third-party secondary and tertiary care. We do this by directing members to the most cost-effective agent in the healthcare chain – members with simple conditions can be treated by nurses and family doctors, while those with aggravated symptoms should be rapidly attended on by specialists.</p>
<p>Machine learning and data-based approaches have always been core to how we accomplish that mission. Back when we were founded, this meant proprietary models built by our in-house data scientists and a strong reliance on analytics.</p>
<p>But the ascent of generative AI has changed this. Instead of relying on a specific team, the new generation of products allows every single Alice employee to make use of state-of-the-art models. Whether it is by embedding third-party models directly into our products, such as by summarizing medical data based on consultation audio transcripts, or by day-to-day applications that allow us to reduce bureaucratic work, AI should play a constant role in how we work.</p>
<p>A <a href="https://static1.squarespace.com/static/5d35e72fcff15f0001b48fc2/t/668d08608a0d4574b039bdea/1720518756159/chatgpt-full.pdf">recent paper</a> showed that adoption of ChatGPT has been widespread, but has been unequal. Many workers require training and guidance to fully benefit from productivity increases, and many are hindered by company restrictions.</p>
<p>Not falling into those traps requires a major culture change. Product managers and operational teams should see AI as the number one go-to solution for every problem that arises. It also means that the use of AI should be as hassle-free as possible and does not require much technical expertise.</p>
<h3>Culture change</h3>
<p>In order to establish the idea that tapping into AI is easy and expected, we ran company-wide events known as &#8220;AI Days&#8221;.</p>
<p>For a whole working day, teams from across the company would gather in our office and work on implementing several POCs of AI applications that could either be rolled out on the same day or would kickstart a regular development cycle. They would be supported by members of the engineering and data teams, as well as other Alice employees who had already adopted AI as a day-to-day working tool.</p>
<p>Before those events, participants would brainstorm possible POCs in a common spreadsheet to be validated by those leading the initiative. These would range from the simplest, such as tagging exam data based on unstructured text, to the more complex, like generating a searchable database based on members&#8217; full medical history.</p>
<p>Participants would be provided with a ChatGPT account that granted them access to assistants. At the end of each day, they would present their accomplishments to the whole event.</p>
<p>Our objectives with this initiative were threefold: teaching employees how to work with AI on a daily basis and ingraining that possibility into their thinking; increasing the pace of generation of new AI applications; and identifying what tools our engineering team should develop to ensure that AI adoption soars.</p>
<p>Those efforts were largely successful. Several of the POCs developed on our first AI Day event went on to become full-fledged projects, and many others were implemented from the get-go. We&#8217;ve seen teams that are not traditionally tech-savvy increasingly rely on AI in their day-to-day work. They also led to a new roadmap for our Engineering Foundation team with clear deliverables that will greatly boost the productivity of those working with AI applications.</p>
<p>All in all, the AI Day events led to significant learnings:</p>
<ul>
<li>Once the floodgates are open, the water is hard to stop. One of the main issues that prevent non-tech teams from using AI is that they have to adapt their thinking to a new tool. Breaching that barrier quickly leads to accelerated use;</li>
<li>Successfully transitioning to a model where AI is a core part of how we work means breaking down dependencies. If Alice employees need to contact data or engineering to make use of AI, that means that there&#8217;s something wrong;</li>
<li>AI can be transformative through large-scale products, yes, but a large swath of its value comes from the sum of a lot of tiny, day-to-day applications. Increasing efficiency across all levels of the company can be as impactful as developing one major new AI product.</li>
</ul>
<h3><b>AI as a platform</b></h3>
<p>Our experience with AI Days led us to divide our efforts to ease use of AI in two fronts: first, we needed to facilitate testing of new applications throughout the company; second, we should make deploying new AI products as easy as possible while maintaining a high level of quality in our infrastructure, cost control and privacy policies.</p>
<p>In the first front, our Engineering Foundation team began development of a testing platform that will allow users to undertake several different tasks that are as of now hard to achieve in a no-code environment:</p>
<ul>
<li>Running AI prompts that are dynamically attached to testing data in batches. For instance, a user can upload a file with NPS comments and then request the platform run a prompt on them, asking it to classify each of the entries between a few different tags;</li>
<li>Optimizing prompts at scale by comparing the results of different prompts over a single batch of files; different contexts over a single prompt; etc.</li>
<li>Connecting directly to our analytical layer through Metabase, ensuring that users do not need to manually input testing data;</li>
<li>Setting up workflows of different AI models. For example, by transcribing an audio, then sending that transcription to a text-based model;</li>
<li>Access and cost controls through a team-based structure that carries specific budgets for each unit;</li>
<li>Saving and commenting on past experiments and allowing users to keep a history of their team&#8217;s previous attempts;</li>
<li>Using our own anonymization and privacy infrastructure to ensure that we are not breaching our rules of governance.</li>
</ul>
<p>We adopted a strategy of rolling out quick iterations of the platform and testing it with users. With representatives of product, operations and even our medical staff as stakeholders, tasked with validating our roadmap and evangelizing their teams, development is running smoothly.</p>
<p>Meanwhile, we also needed to facilitate deployment for those applications that would connect directly with our products. Fortunately, the new generation of LLMs are easy to deal with and we were able to focus on ensuring that data inputted and outputted by those models go through the same processes as those of our production data.</p>
<h3><b>The future</b></h3>
<p>Alice believes that AI is the future, and that it is uniquely positioned to take advantage of new developments. Being a payvidor that acts on the whole healthcare journey and has access to data from a wide range of sources, data products should be as core to us as our medical operations.</p>
<p>In an upcoming post, we will explore the details of the architecture described in the previous sections. But we have taken long strides already in adopting an AI-centric culture by pursuing institutional efforts to educate our teams as well as quick development of tools that boost adoption. The future is bright and there is much more to be done both in terms of Alice&#8217;s efforts and the development of LLMs as a whole.</p>
<p>O post <a href="https://alice.com.br/tech/como-a-alice-esta-construindo-uma-cultura-de-ia-no-seu-dia-a-dia/">Cultura de IA: como a Alice inova no dia a dia</a> apareceu primeiro em <a href="https://alice.com.br/tech">Blog da Alice Tech</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Plataforma: como escalar qualidade em Tech</title>
		<link>https://alice.com.br/tech/plataforma-como-escalar-qualidade-em-tech/</link>
		
		<dc:creator><![CDATA[Bruno Federowski]]></dc:creator>
		<pubDate>Sat, 20 Jul 2024 20:23:39 +0000</pubDate>
				<category><![CDATA[Software]]></category>
		<category><![CDATA[SRE]]></category>
		<guid isPermaLink="false">https://alice.com.br/tech/sem-categoria/plataforma-como-escalar-qualidade-em-tech/</guid>

					<description><![CDATA[<p>Alice é uma empresa de Tecnologia cujo o propósito é tornar o mundo mais saudável. E como tal, resolve seus principais problemas pensando primariamente em soluções baseadas em Tecn</p>
<p>O post <a href="https://alice.com.br/tech/plataforma-como-escalar-qualidade-em-tech/">Plataforma: como escalar qualidade em Tech</a> apareceu primeiro em <a href="https://alice.com.br/tech">Blog da Alice Tech</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h3>Dores de Escala</h3>
<p>Alice é uma empresa de Tecnologia cujo o propósito é tornar o mundo mais saudável. E como tal, resolve seus principais problemas pensando primariamente em soluções baseadas em Tecnologia. Desde o início, além dos sistemas que alimentam diretamente nossos produtos, construímos ferramentas que poderiam ajudar o trabalho de pessoas engenheiras no geral.</p>
<p>Por exemplo, lá nos tempos primórdios da Alice, construímos o que chamamos de <strong>Data Layer</strong>, uma camada de abstração de acesso a dados que garante privacidade e segurança para todas as aplicações. Iniciamos a resolução de questões super importantes pro nosso contexto de saúde: <a href="https://medium.com/alice-tech/construindo-uma-healthtech-que-coloca-a-privacidade-de-seus-usu%C3%A1rios-em-primeiro-lugar-84bf1ac93afb">privacidade</a> e segurança. Esse e outros projetos foram criados de forma orgânica. Nós identificávamos um problema na Engenharia, e então pessoas se juntavam organicamente pra pensar numa solução, projetavam, implementavam e colocavam no ar.</p>
<p>Entretanto, com o <strong>crescimento acelerado</strong> da empresa e com a necessidade de <a href="https://blog.alice.com.br/nossa-voz/virtudes-da-alice/">subir a barra</a> de qualidade de Engenharia no mesmo ritmo, essa estratégia começou a apresentar problemas.</p>
<ol>
<li>Percebemos que nesse modelo não havia um time para dar manutenção a esses projetos ou iterarem de acordo com novos requisitos. As iniciativas eram interpretadas na perspectiva de projetos pontuais e não de produtos internos e suas complexidades (clientes, necessidades de evolução e de negócio).</li>
<li>Além disso, alterações macro eram difíceis de serem priorizadas, já que a cada dia ficavam mais complexas e necessitavam de grande esforço de pessoas que, dentro do contexto de seus times, precisavam negociar algum tempo extra para desenvolver novos projetos <em>cross</em>.</li>
<li>Com nossa nova escala, também aumentamos a complexidade dos sistemas e o número de novas pessoas engenheiras, tornando <a href="https://en.wikipedia.org/wiki/Tribal_knowledge">“conhecimento tribal”</a> e qualidade mais difícil de se reproduzir.</li>
</ol>
<p>Diante deste cenário de crescimento rápido <a href="https://blog.alice.com.br/imprensa/rodada-investimento-series-c-alice/">pós Series C</a>, percebemos que precisávamos dar o próximo passo na nossa organização de Engenharia para atacar nossos desafios: os times de Plataforma.</p>
<h3>Como é Plataforma na Alice?</h3>
<h4>O que é um time de Plataforma?</h4>
<p>Times de Plataforma são geralmente voltados para uma missão técnica de empoderar o time de Engenharia a ser consistentemente eficaz, construindo produtos que abstraem os detalhes técnicos (<a href="https://en.wikipedia.org/wiki/Non-functional_requirement">requisitos não funcionais</a>) e que permitem o foco no negócio. Exemplos desses produtos aqui na Alice são:</p>
<ol>
<li>Data Layer: como comentado anteriormente, uma aplicação que abstrai quesitos de privacidade e segurança na persistência de dados;</li>
<li>Design Systems: um ecossistema de repositórios de estilos, componentes e padrões predefinidos e reutilizáveis que ajuda os times a criarem experiências consistentes e escaláveis com mais velocidade e fica acessível por meio de código e ferramentas de design.</li>
</ol>
<h4>Mas como Plataforma resolve o nosso problema?</h4>
<p>Com um time focado nas iniciativas <em>cross</em> Engenharia, conseguimos ter a especialização e tempo necessários para construir e evoluir produtos que potencializam os outros times de Tecnologia.</p>
<ol>
<li><strong>Somos essenciais para escalar rapidamente:</strong> sabemos que <strong>padrões</strong> e <em>frameworks</em> estabelecidos facilitam a escala de conhecimento e qualidade na Engenharia. Além disso, com um dono claro para requisitos não funcionais, que são críticas para o funcionamento de qualquer produto, conseguimos garantir que todas as equipes cumpram os mesmos requisitos consistentemente.</li>
<li><strong>Melhoramos a eficiência organizacional:</strong> reduzimos a duplicação de trabalho e ajudamos na <strong>padronização</strong> de abordagens (nos casos onde a padronização é um benefício para a organização). Além disso, como donos dos produtos, construímos software mais manutenível e escalável.</li>
<li><strong>Agilizamos a entrega de novos produtos:</strong> além de remover conflitos entre squads e fornecer serviços que agilizam o desenvolvimento, podemos ajudar quando as equipes de produto estão introduzindo uma nova tecnologia. A equipe da plataforma pode incubar essa nova tecnologia e, em seguida, ajudá-la a ser adotada por outros squads. {plataformização}</li>
</ol>
<h4>Um pouco mais sobre nós</h4>
<p>Na Alice, a visão do nosso time é <strong>ser o alicerce para a construção de soluções de Tecnologia que aceleram a entrega de saúde no mundo.</strong> Para chegarmos a esse objetivo, temos quatro pilares estratégicos:</p>
<ol>
<li><strong>Construção de soluções de forma colaborativa com os times:</strong> entendemos que só conseguimos ser pertinentes construindo as ferramentas certas se estivermos muito próximos dos times de Tecnologia entendendo suas dores. Ao mesmo tempo, somos o alicerce para construção de Tecnologia com qualidade, então estamos sempre perto dos times para ajudá-los em suas demandas e entendermos como podemos subir a barra de Engenharia. Em um caso recente, por exemplo, de construção da nova arquitetura Mobile, entendemos junto a todos os times impactados quais casos de uso tinham dificuldades na arquitetura antiga e construímos em conjunto um diagnóstico dos problemas correntes.</li>
<li><strong>Antecipação de problemas e pensamento de longo prazo:</strong> como um alicerce sólido, desenvolvemos soluções que são robustas no longo prazo. Para chegar a esse objetivo consistentemente, utilizamos um <a href="https://medium.com/alice-tech/como-tomamos-decis%C3%B5es-860121def07f">processo diligente</a> de entendimento dos problemas futuros e tomada de decisão. Por exemplo, no caso da nova arquitetura Mobile, além do diagnóstico, projetamos prováveis casos de uso futuros (funcionalidades mais complexas, interações entre diferentes módulos ou até suporte a funções nativas mais recentes), dando insumos para decisões fundamentadas.</li>
<li><strong>Abrangência na resolução de problemas priorizando padronização e plataformização:</strong> um problema só deve ser prioridade para o time de Plataforma se impactar o alicerce de Tecnologia. Portanto, focamos em soluções abrangentes que podem ser padronizadas ou plataformizadas para a utilização em diferentes contextos. Nosso backend, por exemplo, é bastante padronizado: a quase totalidade das aplicações segue a mesma arquitetura e tecnologia (Kotlin) num mesmo repositório (monorepo). Num caso onde precisamos melhorar a utilização de recursos de uma aplicação, conseguimos com pouco esforço estender essa melhoria para todas as outras as aplicações da empresa.</li>
<li><strong>Inovação</strong>: para construir um alicerce que acelera a entrega de saúde no mundo precisamos buscar novas soluções, dado que queremos obter resultados diferentes do que já foi feito no passado. A inovação é o único caminho para chegar no nosso objetivo e temos trilhado essa estrada desde a criação do nosso <strong>Data Layer,</strong> que, diferente de outras soluções de mercado, torna controle de acesso a dados e identificação e de-identificação de dados, padrões em todos os sistemas da Alice.</li>
</ol>
<p>Nosso time tem menos de 6 meses, mas já atuamos nas nossas três frentes principais: Development Experience, Shared Systems e Quality. Algumas de nossas iniciativas recentes:</p>
<ul>
<li>Design System: pensando em DevEx e na padronização de comportamentos, construímos o core do produto, desenvolvemos e aplicamos nossos primeiros componentes Mobile</li>
<li>Ferramentas de Desenvolvimento local: pensando em DevEx, construímos uma nova forma muito fácil de desenvolver localmente na nossa arquitetura de microsserviços utilizando um ambiente remoto</li>
<li>Sherlock: pensando em escalar Privacidade, construímos um sistema interno que permite, em casos específicos, acesso a <a href="https://en.wikipedia.org/wiki/Personal_data">dados PII</a> com rastreabilidade</li>
<li>Observabilidade no frontend: pensando em escalar estabilidade, integramos nossa plataforma de observabilidade (tracing, alertas, etc) com a ferramenta de monitoramento do <a href="https://www.datadoghq.com/">Datadog</a></li>
<li>Data Layer: estamos desenvolvendo novas funcionalidades no nosso sistema compartilhado (que não tínhamos tempo de evoluir no passado) com foco em estabilidade, performance e escala da aplicação</li>
<li>Arquitetura Mobile: como foco em qualidade, estamos construindo uma nova arquitetura de software que prepare o nosso aplicativo Mobile para os próximos anos de Alice</li>
</ul>
<p>E este é só o começo… temos planos ambiciosos de sermos este <strong>alicerce</strong> de Tecnologia em saúde mundial e ainda temos diversas áreas inexploradas (DevTools, Testes de alta complexidade, Microfrontends, etc.)</p>
<h3>Que tal fazer parte desse time?</h3>
<p>Estamos buscando pessoas que topem o desafio de transformar a saúde no Brasil através da tecnologia. <a href="https://www.alice.com.br/carreiras">Clica aqui</a> para saber mais das vagas que temos em aberto!</p>
<p>O post <a href="https://alice.com.br/tech/plataforma-como-escalar-qualidade-em-tech/">Plataforma: como escalar qualidade em Tech</a> apareceu primeiro em <a href="https://alice.com.br/tech">Blog da Alice Tech</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>How we extract data for our DW</title>
		<link>https://alice.com.br/tech/how-we-extract-data-for-our-dw/</link>
		
		<dc:creator><![CDATA[Bruno Federowski]]></dc:creator>
		<pubDate>Sat, 20 Jul 2024 20:23:39 +0000</pubDate>
				<category><![CDATA[Software]]></category>
		<guid isPermaLink="false">https://alice.com.br/tech/sem-categoria/how-we-extract-data-for-our-dw/</guid>

					<description><![CDATA[<p>About a year ago I arrived at Alice with the compromise to make the world healthier. We had less than 100 employees and living from series A, which means short money. A big challen</p>
<p>O post <a href="https://alice.com.br/tech/how-we-extract-data-for-our-dw/">How we extract data for our DW</a> apareceu primeiro em <a href="https://alice.com.br/tech">Blog da Alice Tech</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h4>A long long time ago…</h4>
<p>About a year ago I arrived at Alice with the compromise to make the world healthier. We had less than 100 employees and living from series A, which means short money. A big challenge and a lot of work to do!</p>
<h4>The first challenges</h4>
<p>As a data engineer, my responsibility was to provide data for everybody. The team was very small (actually just me and half the time of my boss) and the systems were changing very fast.</p>
<p>Facing the situation, the plan needed to be as simple and direct as possible:</p>
<ul>
<li>Use a relational database as the data warehouse. We choose PostgreSQL hosted in AWS RDS. Easy to configure and maintain.</li>
<li>Use a simple tool to schedule the ETL pipelines. The choice was Airflow since it&#8217;s a very stable, well know tool and we had experience with it (and we love Python).</li>
<li>A visualization interface. Metabase was the winner for many motives: Free, previous experience with it, easy to install and configure, self-service, very stable and users usually like it.</li>
</ul>
<p>OK…. That&#8217;s something we can make happen! I reused some previous code I wrote in the past to copy data from one place to another and data started to flow! Great! Mission accomplished!</p>
<h4>Problems always happen!</h4>
<p>BUT…. almost every day I had dags broken and had to add a table, fix some table structure, re-run dags, and deploy emergency PRs. The problem was for every new column, every modification in size or type, even the order of some selects could break something. How to solve it?</p>
<h4>For every problem, a solution!</h4>
<p>At that point, I started to work on an Airflow plugin for a smarter extractor which was baptized, given my total lack of imagination, &#8220;SmartTransfer&#8221;. The main idea was to check the existence and structure of the table in the destination stage area and automatically create or re-create as needed.</p>
<p>The intention was to be really easy to be called, with minimal parameters. Below is a real example of a very simple dag with it:</p>
<p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/7faf4916b61074e1a251a48b55577003/href">https://medium.com/media/7faf4916b61074e1a251a48b55577003/href</a></iframe></p>
<p><em>(all code is available at </em><a href="https://github.com/alice-health/airflow_plugins">https://github.com/alice-health/airflow_plugins</a> <em>)</em></p>
<p>So, how does it work? No big secret, but there are some steps in the process.</p>
<p>First, we need to check the structure of the source table. We run a query and get one row from the source table and analyze the columns.</p>
<p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/aa1ad187358be8b92f52a8ba5fd8d6c5/href">https://medium.com/media/aa1ad187358be8b92f52a8ba5fd8d6c5/href</a></iframe></p>
<p>From the table, we can create build the &#8216;create table&#8217; statement.</p>
<p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/612364fbe3b882fca211d453c0fa7964/href">https://medium.com/media/612364fbe3b882fca211d453c0fa7964/href</a></iframe></p>
<p>We used the &#8216;unlogged table&#8217; PostgreSQL feature because it should be, in principle, faster. Unlogged tables are faster but not crash-free, so be careful! Since staging is just a copy of production, it&#8217;s not a problem to lose data. <a href="https://www.postgresql.org/docs/11/sql-createtable.html">You can learn more about PostgreSQL here</a>. We didn&#8217;t notice much difference but we have only a few gigabytes. We will benchmark again in the future as our database grows.</p>
<p>Everything set, the logic is quite straightforward:</p>
<ul>
<li>If the destination table doesn&#8217;t exist, create it</li>
<li>If the destination table exists but the structure is different, drop it and recreate it</li>
<li>If tables have the same structure, same primary keys, just keep the table</li>
</ul>
<p>It&#8217;s important to remember in the case of (re)creating the destination table we need to do a full import, so we set the flag &#8220;need_full_import&#8221; to True</p>
<p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/2bfb41b76b83a85411afcbaf739329d5/href">https://medium.com/media/2bfb41b76b83a85411afcbaf739329d5/href</a></iframe></p>
<p>Finally, transfer the data. The first step is to know if we are going to do a full import or an incremental import:</p>
<p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/aaa4f0613d2923850568eed527c52622/href">https://medium.com/media/aaa4f0613d2923850568eed527c52622/href</a></iframe></p>
<p>and prepare the insert statements. The syntax is PostgreSQL specific, with &#8220;<em>ON CONFLICT DO UPDATE&#8221;</em> to create a mixed insert/update statement:</p>
<p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/538289ba2b8b9bcd3fb07634be08bca1/href">https://medium.com/media/538289ba2b8b9bcd3fb07634be08bca1/href</a></iframe></p>
<p>The main loop makes the data transfer. The most important part here is the grouper function: It lazily consumes the source_cursor, keeping in memory only the data will be sent in the current block</p>
<p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/aca4c1f9af8fe1c23f37b2fd81b3a271/href">https://medium.com/media/aca4c1f9af8fe1c23f37b2fd81b3a271/href</a></iframe><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/e52079bf806612b757bf4497fb89a7b4/href">https://medium.com/media/e52079bf806612b757bf4497fb89a7b4/href</a></iframe></p>
<p>More details of installing, using, and testing SmartTransfer are in the README file in the official repository at <a href="https://github.com/alice-health/airflow_plugins">https://github.com/alice-health/airflow_plugins</a>.</p>
<h4>Conclusion</h4>
<p>I tried to cover the most important (and interesting) parts of the code and show how we solved the problem of moving, not hundred of terabytes with 100 people, but a couple of gigabytes with two people, in a way to automatize all table synchronization and copying process to minimize the data engineer manual work.</p>
<p>O post <a href="https://alice.com.br/tech/how-we-extract-data-for-our-dw/">How we extract data for our DW</a> apareceu primeiro em <a href="https://alice.com.br/tech">Blog da Alice Tech</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Como fazemos microbenchmarks em Kotlin</title>
		<link>https://alice.com.br/tech/como-fazemos-microbenchmarks-em-kotlin/</link>
		
		<dc:creator><![CDATA[Bruno Federowski]]></dc:creator>
		<pubDate>Sat, 20 Jul 2024 20:23:39 +0000</pubDate>
				<category><![CDATA[Software]]></category>
		<guid isPermaLink="false">https://alice.com.br/tech/sem-categoria/como-fazemos-microbenchmarks-em-kotlin/</guid>

					<description><![CDATA[<p>As vezes precisamos fazer alguns testes de performance ou de benchmark, a fim de ter um melhor embasamento na hora de tomar nossas decisões.</p>
<p>O post <a href="https://alice.com.br/tech/como-fazemos-microbenchmarks-em-kotlin/">Como fazemos microbenchmarks em Kotlin</a> apareceu primeiro em <a href="https://alice.com.br/tech">Blog da Alice Tech</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>As vezes precisamos fazer alguns testes de performance ou de benchmark, a fim de ter um melhor embasamento na hora de <a href="https://medium.com/alice-tech/como-tomamos-decis%C3%B5es-860121def07f">tomar nossas decisões</a>. Dado que não existe muito material sobre o assunto com essa stack específica, pensamos em descrever aqui como fizemos nossa aplicação simples para benchmarks.</p>
<h3>Afinal, o que é um microbenchmark?</h3>
<p>Um microbenchmark é um teste projetado para medir o desempenho de uma unidade muito pequena: o tempo para chamar um método sincronizado versus um método não sincronizado; a sobrecarga na criação de um encadeamento versus o uso de um conjunto de encadeamentos; o tempo para executar um algoritmo aritmético versus uma implementação alternativa; e assim por diante.</p>
<p>É uma forma bem interessante de verificar se algum fluxo que estamos fazemos está consumindo muito ou pouco tempo ou recursos (CPU, memória, rede, disco, etc). Porém deve ser feito com cautela.</p>
<p>Muitos fatores podem interferir na execução e aferição de um benchmark, como capacidade de processamento do computador, memória disponível, versão do framework, entre outros. Por conta disso, deve ser feito para testes isolados de unidades bem específicas.</p>
<h3>Testando uso de reflections para nossos logs</h3>
<p>Há alguns meses atrás, o time <a href="https://alice.com.br/blog/conheca-a-alice/alice-e-a-empresa-mais-inovadora-da-america-latina-segundo-fast-company/">Alice</a> estudou a necessidade do uso de <em>Reflection</em> para identificar a função e a classe exata de onde o log foi gerado.</p>
<p>Nossa hipótese era que a utilização de <em>Reflection</em> poderia aumentar o consumo de recursos da função, mas não sabíamos o quanto aumentaria e se isso impactaria de verdade nossas aplicações.</p>
<h4>Importação de dependências</h4>
<p>Usamos a biblioteca JMH (the Java Microbenchmark Harness) para fazer a comparação. Utilizamos tanto o <a href="https://search.maven.org/classic/#artifactdetails%7Corg.openjdk.jmh%7Cjmh-core%7C1.19%7Cjar">JMH Core</a> quanto <a href="https://search.maven.org/classic/#artifactdetails%7Corg.openjdk.jmh%7Cjmh-generator-annprocess%7C1.19%7Cjar">JMH Annotation Processor</a>.</p>
<pre>plugins <strong>{
    </strong><em>kotlin</em>("jvm") <em>version </em>"1.4.32"
    <em>kotlin</em>("kapt") <em>version </em>"1.4.32"
    id("me.champeau.gradle.jmh") <em>version </em>"0.5.2"
    id("io.morethan.jmhreport") <em>version </em>"0.9.0"
    <em>application
</em><strong>}</strong></pre>
<p>No build.gradle.kts do projeto nós declaramos a task para rodar os testes de benchmark</p>
<pre><em>task</em>("benchmarks", type = JavaExec::class) <strong>{
  </strong><em>classpath </em>= <em>sourceSets</em>.getByName("test").<em>runtimeClasspath
  main </em>= "br.com.alice.benchmarks.BenchmarksRunnerKt"
<strong>}</strong></pre>
<p>Além disso importamos a biblioteca orgs.slf4j.Logger para criar nossos logs. A lista de dependências ficou:</p>
<pre><em>dependencies </em><strong>{
    </strong><em>kapt</em>("org.openjdk.jmh:jmh-generator-annprocess:1.25")

    <em>implementation</em>("org.openjdk.jmh:jmh-core:1.25")
    <em>implementation</em>("org.openjdk.jmh:jmh-generator-annprocess:1.25")

    <em>api</em>("ch.qos.logback:logback-classic:1.2.3")
    <em>implementation</em>("net.logstash.logback:logstash-logback-encoder:6.4")

    <em>annotationProcessor</em>("org.openjdk.jmh:jmh-generator-annprocess:1.25")

    <em>testImplementation</em>(<em>kotlin</em>("test-junit"))
<strong>}</strong></pre>
<h4>Criação da função de log</h4>
<p>Para realizar o teste, criamos uma abstração para a biblioteca orgs.slf4j.Logger . Só possui uma simples função de logar info, simulando nossa biblioteca interna para logs.</p>
<p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/e613b3205a2f958257f256880d60dc51/href">https://medium.com/media/e613b3205a2f958257f256880d60dc51/href</a></iframe></p>
<h4>Criando os casos de teste</h4>
<p>JMH suporta diferentes tipos de benchmarks: <em>Throughput,</em> <em>AverageTime,</em> <em>SampleTime</em>, and <em>SingleShotTime</em>. São configurados via annotation @BenchmarkMode .</p>
<ul>
<li><em>Throughput</em>: nesse modo, o teste é executado em um período pre determinado e é avaliado o número de vezes que o método em teste foi executado</li>
<li><em>AverageTime</em>: inverso ao <em>Throughput</em>, esse método é usado para se ter o tempo médio de cada chamada do método em teste.</li>
<li><em>SampleTime</em>: esse método também utiliza um tempo pré determinado, porém aqui algumas chamadas são selecionadas randomicamente e seu tempo avaliado.</li>
<li><em>SingleShotTime</em>: mede o tempo de uma única chamada.</li>
</ul>
<p>Para o nosso caso, utilizamos <em>AverageTime</em>, dessa forma a gente simular os nossos micro-serviços utilizando os métodos de log diversas vezes e ver o quanto isso impactaria o tempo e os recursos dos mesmos.</p>
<p>Configuramos também a unidade de medida temporal para microsegundos, também via annotation @OutputTimeUnit .</p>
<p>Usamos a annotation @Benchmark para definir uma função como <em>test case</em> do benchmarking. Criamos 3 tipos de testes:</p>
<ul>
<li>Log sem nenhuma reflection</li>
<li>Log utilizando reflection através do Throwable para receber os nomes de classe e método.</li>
<li>Log utilizando reflection através da Thread para receber os nomes de classe e método.</li>
</ul>
<p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/d4d08cafb3722fed8a0ab3599682a6db/href">https://medium.com/media/d4d08cafb3722fed8a0ab3599682a6db/href</a></iframe></p>
<h4>Configuração final do benchmark</h4>
<p>Para agrupar todos os testes, configurar saída do resultado e definir últimas configurações, nós criamos o arquivo <strong>BenchmarksRunner.kt</strong>, assim declarado no gradle.build.kts , mostrado no início do artigo.</p>
<p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/cf5835559cc5bcb2f4e16b799c9127f2/href">https://medium.com/media/cf5835559cc5bcb2f4e16b799c9127f2/href</a></iframe></p>
<p>As configurações utilizadas no OptionsBuilder:</p>
<ul>
<li>include adiciona o teste que vamos realizar. Nele indicamos qual a classe a ser executada, nesse caso o LogReflectionBenchmark .</li>
<li>forks é o número de testes paralelos que vão ser executados em cada iteração. Utilizamos 2 forks.</li>
<li>threads é o número de threads a ser utilizada para cada teste. Escolhemos duas threads. Dependendo do número de threads disponíveis na máquina, esse valor pode aumentar.</li>
<li>warmupBatchSize é o tamanho o grupo de aquecimento. Utilizamos 2 <em>batches</em>.</li>
<li>warmupIterations é o número de iterações a serem executadas antes de começar a contabilizar o tempo. Esse número é importante pois ajuda a contabilizar depois que a máquina já estiver rodando os testes. Um número muito alto pode impactar negativamente o teste, se o processo já tiver consumido bastante recurso da máquina.</li>
<li>measurementIterations é o número de iterações, agora contabilizando o tempo de cada teste. O resultado final é montado a partir a média entre as diferentes iterações.</li>
</ul>
<p>Além disso, definimos como arquivos output benchmark_output.log e benchmark_result.json . Eles vão conter as informações dos testes.</p>
<h4>Hora de rodar os testes</h4>
<p>Depois de toda a configuração, podemos rodar o BenchmarksRunner.main e aguardar os resultados. Após alguns minutos, o resultado foi mostrado no arquivo benchmark_output.log .</p>
<pre>LogReflectionBenchmark.logWithReflectionThreadGetStackTrace     avgt    4  28.860 ± 7.172  us/op
LogReflectionBenchmark.logWithReflectionThrowableGetStackTrace  avgt    4  42.075 ± 11.087  us/op
LogReflectionBenchmark.logWithoutReflection                     avgt    4  0.36028 ±  0.00035  us/op</pre>
<p>Como vocês podem ver, a utilização do log sem nenhum tipo de <em>reflection</em> foi cerca de 100x mais rápida do que com uso de qualquer <em>reflection</em>. Isso já foi necessário para que o nosso time decidisse não precisar logar o nome da função e nem da classe.</p>
<h3>Teste você mesmo</h3>
<p>Caso queira validar também em sua máquina, o código de exemplo está aberto. Você pode fazer o mesmo teste que nós fizemos, ou usar o exemplo para criar seus próprios microbenchmarks em Kotlin.</p>
<p><a href="https://github.com/alice-health/kotlin-benchmark-example">alice-health/kotlin-benchmark-example</a></p>
<p>No repositório tem a descrição de como executar os testes. E se você conseguiu testar outros <em>use cases</em>, compartilha aqui com a gente!</p>
<h3>Que tal fazer parte desse time?</h3>
<p>Estamos buscando pessoas que topem o desafio de transformar a saúde no Brasil através da tecnologia. <a href="https://www.alice.com.br/carreiras">Clica aqui</a> para saber mais das vagas que temos em aberto!</p>
<p>O post <a href="https://alice.com.br/tech/como-fazemos-microbenchmarks-em-kotlin/">Como fazemos microbenchmarks em Kotlin</a> apareceu primeiro em <a href="https://alice.com.br/tech">Blog da Alice Tech</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Descomplicando o Apache Kafka</title>
		<link>https://alice.com.br/tech/descomplicando-o-apache-kafka/</link>
		
		<dc:creator><![CDATA[Bruno Federowski]]></dc:creator>
		<pubDate>Sat, 20 Jul 2024 20:23:39 +0000</pubDate>
				<category><![CDATA[Software]]></category>
		<guid isPermaLink="false">https://alice.com.br/tech/sem-categoria/descomplicando-o-apache-kafka/</guid>

					<description><![CDATA[<p>Na Alice, temos a cultura de tomada de decisões em conjunto para assuntos que impactem a engenharia como um todo.</p>
<p>O post <a href="https://alice.com.br/tech/descomplicando-o-apache-kafka/">Descomplicando o Apache Kafka</a> apareceu primeiro em <a href="https://alice.com.br/tech">Blog da Alice Tech</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h2>Introdução</h2>
<p>Na Alice, temos a <a href="https://medium.com/alice-tech/como-tomamos-decis%C3%B5es-860121def07f">cultura de tomada de decisões em conjunto</a> para assuntos que impactem a engenharia como um todo. Isso sendo desde a definição da <a href="https://medium.com/alice-tech/flutter-eu-escolho-voc%C3%AA-83ef5ee5c4a3?source=---------5-----------------------">tecnologia a ser usada para desenvolvimento mobile</a>, até a arquitetura de processamento assíncrono dos serviços (spoiler: ela é baseada em Kafka).</p>
<p>Mas antes de contar como e porque escolhemos o Kafka, vale uma n̶ã̶o̶ ̶t̶ã̶o̶ breve introdução sobre ele.</p>
<h2><strong>O que é o Apache Kafka?</strong></h2>
<p>Resumidamente, o Kafka pode ser definido como um sistema de processamento de stream de dados em tempo real / um sistema de mensageria (messaging system) publish-subscribe distribuído.</p>
<p>Ele possui como principais características — se comparado com outros sistemas de mensageria — um alto throughput, clusterização no DNA (permitindo escalabilidade horizontal), ordenamento e persistência de mensagens com estrutura de disco O(1) (entraremos em mais detalhes sobre o que isto representa).</p>
<h2><strong>O que é um sistema de mensageria?</strong></h2>
<p>Um sistema de mensageria nada mais é do que uma forma de comunicação assíncrona entre duas (ou mais) aplicações. Neste conceito, as aplicações se comunicam através de uma fila (message queue), de forma totalmente desacoplada, onde o produtor da mensagem (producer) não tem conhecimento de quem a processará, assim como o consumidor (consumer) também não possui ciência de quem a produziu. Ambas as pontas apenas se preocupam com o conteúdo da mensagem.</p>
<p>Existem dois tipos de padrões de mensageria: ponta à ponta (point to point) e publish-subscribe (pub-sub).</p>
<h3><strong>Sistema de mensageria ponta à ponta</strong></h3>
<p>Um sistema de mensageria ponta à ponta é caracterizado pelo fato de que cada mensagem apenas poder ser consumida uma única vez. Neste sistema, a mensagem é persistida na fila e, a partir do momento que um consumidor lê esta mensagem, ela é automaticamente removida da fila. Exemplos de sistemas neste modelo temos o Amazon Simple Queue Service (SQS) e o Microsoft Message Queuing (MSMQ).</p>
<figure><img decoding="async" src="https://cdn-images-1.medium.com/max/454/0*jdcRsgpQHczaw322" alt="(Fig. 1: Ilustração de fila ponta à ponta. https://docs.oracle.com/cd/E19340-01/820-6424/aerbj/index.html)" /><figcaption>(Fig. 1: Ilustração de fila ponta à ponta. <a href="https://docs.oracle.com/cd/E19340-01/820-6424/aerbj/index.html">https://docs.oracle.com/cd/E19340-01/820-6424/aerbj/index.html</a>)</figcaption></figure>
<h3><strong>Sistema de mensageria publish-subscribe</strong></h3>
<p>No sistema de mensageria publish-subscribe assim como no de ponta à ponta, as mensagens são persistidas em uma fila através de um produtor (publisher). Porém, diferentemente do modelo anterior, os consumidores podem se inscrever/assinar (subscribe) à uma ou mais filas e consumir todas as mensagens destas filas. Neste modelo, todos os consumidores (subscribers) processam todas as mensagens de todas as filas no qual eles se inscreveram. Exemplos de sistemas neste modelo temos o RabbitMQ e o Apache Kafka.</p>
<figure><img decoding="async" src="https://cdn-images-1.medium.com/max/395/0*KxH9m3CA5A9EHi2Q" alt="" /><figcaption>(Fig. 2: Ilustração de fila pub-sub. <a href="https://docs.oracle.com/cd/E19340-01/820-6424/aerbk/index.html">https://docs.oracle.com/cd/E19340-01/820-6424/aerbk/index.html</a>)</figcaption></figure>
<h2><strong>Background</strong></h2>
<h3><strong>História</strong></h3>
<p>Tudo começou em meados de 2010, com uma necessidade do LinkedIn: integração massiva de dados. Um volume enorme de dados era gerado a todo tempo, porém, com as ferramentas existentes na época, não era possível integrar e centralizar estes dados da forma que gostariam e com a escala que precisavam.</p>
<p>Foi então que <a href="https://twitter.com/jaykreps">Jay Kreps</a> e sua equipe surgiram com o conceito do Kafka.</p>
<h3><strong>Timeline</strong></h3>
<p>Em 2011 tornou-se um projeto open-source, sendo absolvido pela Apache Foundation em 2012.</p>
<p>Em 2014, os engenheiros do LinkedIn responsáveis pelo desenvolvimento do Kafka fundaram a <a href="https://www.confluent.io/">Confluent</a>, empresa com foco em Kafka.</p>
<h3><strong>Fun fact</strong></h3>
<p>Kafka é desenvolvido em Scala e Java, e seu nome é uma referência ao escritor alemão <a href="https://pt.wikipedia.org/wiki/Franz_Kafka">Franz Kafka</a>. Jay diz que a escolha do nome se deu ao fato de que, devido o Kafka ser um sistema otimizado para escrita, faria sentido ter o nome de um escritor. Além de achar que <a href="https://www.quora.com/What-is-the-relation-between-Kafka-the-writer-and-Apache-Kafka-the-distributed-messaging-system">soava bem para um projeto open source</a>.</p>
<h2><strong>Mas por que utilizar Kafka?</strong></h2>
<p>Dentre as principais vantagens do Kafka, podemos destacar:</p>
<ul>
<li><strong>Sistema de registros:</strong> após persistido, um registro (mensagem) nunca mais é mais removido do log (por padrão). Desta forma, é possível “voltar no tempo” e reprocessar todas as mensagens a partir de uma data específica.</li>
<li><strong>Ordenamento garantido</strong>: ao ser publicada a mensagem A (POST) e então a B (PUT), sempre serão retornadas e lidas nesta mesma ordem (FIFO).</li>
<li><strong>Centralização</strong>: uma mesma mensagem pode servir de input para uma operação SQL e para um registro em um Data Lake.</li>
<li><strong>Escalabilidade</strong>: Kafka é totalmente pensado em clusterização e escalabilidade horizontal.</li>
<li><strong>Pull over Push</strong>: diferentemente de outros sistemas de mensageria (e.g. RabbitMQ) e/ou sistemas de service bus, o Kafka trabalha com um modelo de pulling ao invés de pushing, no qual o consumidor tem de solicitar ativamente a leitura de novas mensagens. Isto possibilita a existência de consumers com velocidades de processamento distintas entre si.</li>
<li><strong>Performance</strong>: possui um alto throughput, comportando centenas de milhares de mensagens/seg até em hardwares mais modestos. Como citado anteriormente, possui persistência de mensagens com estrutura de disco <a href="https://pt.wikipedia.org/wiki/Grande-O">O(1)</a>, ou seja, não importa a quantidade de mensagens existentes, a velocidade de escrita sempre se mantém a mesma.</li>
</ul>
<figure><img decoding="async" src="https://cdn-images-1.medium.com/max/600/0*Z4U-ueC2dpCSdLIh" alt="" /><figcaption>(Fig 3: Ilustração de representação do Kafka)</figcaption></figure>
<h3><strong>Performance linear</strong></h3>
<p>Devido a arquitetura de distribuição que o Kafka implementa, é possível obtermos escalabilidade linear em nosso sistema. Desta forma, para cada nó (broker) adicionado ao cluster, teremos um aumento linear de throughput suportado pelo Kafka.</p>
<figure><img decoding="async" src="https://cdn-images-1.medium.com/max/600/0*4htqnFHKombtAbFr" alt="" /><figcaption>(Fig. 4: Gráfico de aumento do throughput do Kafka para cada nó adicionado no Cluster. <a href="https://www.slideshare.net/r39132/linkedin-data-infrastructure-qcon-london-2012/38-Kafka_Performance_Linear_Incremental_Scalability">https://www.slideshare.net/r39132/linkedin-data-infrastructure-qcon-london-2012/38-Kafka_Performance_Linear_Incremental_Scalability</a>)</figcaption></figure>
<h3><strong>Use cases</strong></h3>
<p>Mesmo o Kafka sendo extremamente versátil, existem alguns casos de uso no qual acaba se destacando. Tais como:</p>
<ul>
<li><strong>Hub de eventos</strong>: Kafka pode servir de um hub centralizador dos eventos da sua aplicação, permitindo que inputs de diversas fontes de dados sejam concentrados em um único ponto, para então serem potencialmente filtrados, transformados e processados de formas distintas.</li>
<li><strong>Data pipeline</strong>: um dado pode ser persistido no Kafka para então ser replicado para outros repositórios, tais como banco de dados.</li>
<li><strong>Entry point de Big Data</strong>: em casos de utilização de data lakes baseados em storages na nuvem (e.g. AWS S3), Kafka costuma servir como um “buffer” dos dados devido ao seu throughput, armazenando-os até serem transferidos para o storage final.</li>
</ul>
<figure><img decoding="async" src="https://cdn-images-1.medium.com/max/851/0*4LdPngQKdZbeRF1L" alt="" /><figcaption>(Fig. 5: Ilustração Kafka operando como um hub de eventos. <a href="https://www.confluent.io/">https://www.confluent.io/</a>)</figcaption></figure>
<h2><strong>Semânticas</strong></h2>
<figure><img decoding="async" src="https://cdn-images-1.medium.com/max/481/0*TfavmQXnGDlvnvva" alt="" /><figcaption>(Fig. 6: Representação visual dos fundamentos do Kafka. <a href="https://www.confluent.io/">https://www.confluent.io/</a>)</figcaption></figure>
<h3><strong>Registros</strong></h3>
<p>Os registros (records) são as mensagens persistidas em uma fila (tópico). Um registro é composto de três componentes: chave, valor e timestamp.</p>
<p>A chave (key) é o que define em qual partição este registro será armazenado (mais detalhes sobre particionamento abaixo). A chave não é obrigatória e, caso não seja fornecida, o Kafka se encarregará de definir a partição correta para este registro.</p>
<p>O valor (value) é o conteúdo do registro, o equivalente ao corpo de uma mensagem. O valor pode conter qualquer dado, desde uma simples string até um objeto serializado em JSON.</p>
<p>O timestamp é a data e hora no qual o registro foi persistido, sendo atribuído automaticamente pelo Kafka no momento da criação do registro.</p>
<p>O registro é sempre imutável e append-only, ou seja, somente é possível incluir novos registros. Uma vez incluído não pode mais ser modificado ou removido.</p>
<p>Os registros são sempre persistidos em disco, não havendo nenhum cache em memória, tanto para escrita quanto para leitura.</p>
<figure><img decoding="async" src="https://cdn-images-1.medium.com/max/600/0*r1v6MYiYKT5H23IY" alt="" /><figcaption>(Fig. 7: Registros do Kafka em um log (partição de um tópico). <a href="https://www.confluent.io/">https://www.confluent.io/</a>)</figcaption></figure>
<h3><strong>Producer e Consumer</strong></h3>
<p>O producer é quem será responsável por gerar registros em um tópico e o consumer por ler estes registros. Em ambos os casos, a comunicação é sempre feita com o broker (nó) líder do cluster.</p>
<p>Ao ler um registro, o consumer pode tanto solicitar o último não lido, quanto a partir de uma posição específica.</p>
<figure><img decoding="async" src="https://cdn-images-1.medium.com/max/528/0*qfGkKK_Yx2rlZ16K" alt="" /><figcaption>(Fig. 8: Diagrama producer/consumer de um cluster Kafka. <a href="https://www.confluent.io/">https://www.confluent.io/</a>)</figcaption></figure>
<h3><strong>Tópicos</strong></h3>
<p>O tópico é a nomenclatura lógica para uma ou mais partições. Basicamente é onde os registros ficam armazenados, sendo equivalente à uma fila, porém considerando todas as partições do cluster.</p>
<figure><img decoding="async" src="https://cdn-images-1.medium.com/max/416/0*4XODBKLqrQpMNOPx" alt="" /><figcaption>(Fig. 9: Representação de um tópico do Kafka e suas partições. <a href="https://www.confluent.io/">https://www.confluent.io/</a>)</figcaption></figure>
<h3><strong>Partições</strong></h3>
<p>As partições são as divisões “físicas” de um tópico. Cada partição representará o conjunto de registros de um tópico, em um broker (nó) no cluster.</p>
<p>As partições seguem o modelo de líder/seguidor (leader/follower), onde sempre há ao menos um broker com uma partição principal que recebe todas as operações de leitura e escrita, sendo replicado posteriormente para os demais brokers seguidores em forma de réplica.</p>
<figure><img decoding="async" src="https://cdn-images-1.medium.com/max/600/0*LaNpvKl7mb0oUwEA" alt="" /><figcaption>(Fig. 10: Representação de um cluster Kafka. <a href="https://www.confluent.io/">https://www.confluent.io/</a>)</figcaption></figure>
<p>No exemplo acima, temos quatro partições com duas réplicas cada. Cada partição ficará responsável por um conjunto de dados daquele tópico, onde estes mesmos dados serão replicados em cada um dos outros dois brokers seguidores.</p>
<p>O particionamento pode ser feito manualmente ou baseado em uma chave. No primeiro cenário, quem estiver produzindo e/ou consumindo as mensagens, fica responsável por indicar com qual partição deseja interfacear. Já no segundo caso, deve-se definir previamente qual o range de valores de uma chave que cada partição será responsável. Desta forma, ao publicar ou ler um registro, o Kafka ficará encarregado por atribuir a partição correspondente, baseado nas configurações previamente estabelecidas.</p>
<h3><strong>Grupos de consumo</strong></h3>
<p>Grupo de consumo (consumer group) é o nome lógico para um ou mais consumers. É através dele que se dá a escalabilidade do lado dos consumidores.</p>
<p>Cada grupo lê todas as mensagens de um tópico, dividindo as partições deste tópico por entre os integrantes do grupo.</p>
<p>Cada grupo vai representar um processamento específico (e distinto) dos registros de um tópico em relação ao outro grupo. Já cada integrante de um mesmo grupo representará uma instância de processamento (um processo, uma thread, um container, etc.) idêntica em relação aos consumers deste mesmo grupo.</p>
<figure><img decoding="async" src="https://cdn-images-1.medium.com/max/474/0*RScgni6rLtyU_kF4" alt="" /><figcaption>(Fig. 11: Representação de um grupo de consumo. <a href="https://www.confluent.io/">https://www.confluent.io/</a>)</figcaption></figure>
<p>No exemplo acima, temos um tópico dividido em quatro partições, e dois grupos de consumo: grupo A com dois integrantes e B com quatro.</p>
<p>Desta forma, tanto o grupo A quanto o grupo B processarão todas as mensagens de um determinado tópico. Devido ao grupo A possuir dois integrantes, cada integrante ficará responsável pelos registros de duas partições cada. Já no grupo B por possuir quatro integrantes, cada integrante ficará responsável pelas mensagens provenientes de uma única partição cada.</p>
<p>Com isto, é possível ter N processos distintos para um mesmo dado e paralelizar cada um destes processamentos em N instâncias conforme a necessidade, sem gerar concorrência entre si.</p>
<h3><strong>Offsets</strong></h3>
<p>Ao inserir um registro em um tópico, o Kafka automaticamente atribui um identificador único sequencial para ele, que consiste basicamente de um índice deste registro na partição daquele tópico.</p>
<p>O offset por sua vez, representa a posição de leitura de um grupo de consumo, em relação à uma partição de um tópico.</p>
<figure><img decoding="async" src="https://cdn-images-1.medium.com/max/753/0*ArApyHIsCDJkXF3C" alt="" /><figcaption>(Fig. 12: Demonstração de um tópico com suas partições e respectivos offsets. <a href="https://www.confluent.io/">https://www.confluent.io/</a>)</figcaption></figure>
<p>No exemplo acima, temos um tópico com três partições. As setas representando um grupo de consumo e os números destacados os offsets daquele grupo nas respectivos partições.</p>
<p>O objetivo do offset é definir qual foi o último registro lido por aquele grupo de consumo naquela partição, para que assim possa prosseguir com a leitura de onde parou.</p>
<p>O Kafka mantém o tracking dos offsets para que apenas retorne os registros ainda não lidos. Porém, como citado anteriormente, um consumer pode solicitar um registro em uma posição específica.</p>
<h2><strong>Conclusão</strong></h2>
<p>Conforme pudemos ver, o Kafka é uma excelente ferramenta para criação de sistemas distribuídos, mas assim como qualquer tecnologia, nasceu para resolver problemas específicos e não para ser uma “bala de prata” da persistência de dados.</p>
<h2>Que tal fazer parte desse time?</h2>
<p>Estamos buscando pessoas que topem o desafio de transformar a saúde no Brasil através da tecnologia. <a href="https://www.alice.com.br/carreiras">Clica aqui</a> para saber mais das vagas que temos em aberto!</p>
<p>O post <a href="https://alice.com.br/tech/descomplicando-o-apache-kafka/">Descomplicando o Apache Kafka</a> apareceu primeiro em <a href="https://alice.com.br/tech">Blog da Alice Tech</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Melhor forma de escrever CSS no Vue</title>
		<link>https://alice.com.br/tech/qual-a-melhor-forma-de-escrever-css-no-vue/</link>
		
		<dc:creator><![CDATA[Bruno Federowski]]></dc:creator>
		<pubDate>Sat, 20 Jul 2024 20:23:39 +0000</pubDate>
				<category><![CDATA[Software]]></category>
		<guid isPermaLink="false">https://alice.com.br/tech/sem-categoria/qual-a-melhor-forma-de-escrever-css-no-vue/</guid>

					<description><![CDATA[<p>Vamos lá, CSS não é a coisa mais fácil do mundo.</p>
<p>O post <a href="https://alice.com.br/tech/qual-a-melhor-forma-de-escrever-css-no-vue/">Melhor forma de escrever CSS no Vue</a> apareceu primeiro em <a href="https://alice.com.br/tech">Blog da Alice Tech</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Vamos lá, CSS não é a coisa mais fácil do mundo. Existem diversas formas de resolver o mesmo problema, os browsers nem sempre possuem o mesmo comportamento, já chegamos num nível onde é impossível saber todas as regras que existem, etc. Na expectativa de ajudar o desenvolvimento, temos pré-processadores, pós-processadores, variáveis e metodologias para organização das classes, para citar alguns exemplos das ferramentas que temos para facilitar o uso do CSS.</p>
<p>Mas é claro, como quase tudo no mundo do frontend, as opções não param por ai. Dependendo do framework que você usa, também existem algumas alternativas diferentes para escrever CSS <em>{como se já não fosse complexo o suficiente haha, mas vamos falar disso depois}</em>.</p>
<p>Aqui na Alice, <a href="https://medium.com/alice-tech/h%C3%A1-1-ano-escolhemos-o-vue-js-419cf6c82c1d">nós usamos o Vue</a> e durante algumas semanas no nosso chapter de frontend, discutimos qual seria o padrão que iríamos adotar. Antes de tomar uma decisão, nós testamos as opções mais comuns e algumas obscuras que a comunidade ainda não está usando tanto. Como o nosso chapter de frontends não é muito grande, é importante para nós termos um padrão bem definido <em>{já que cada pessoa está em um time diferente}</em> e que seja fácil para quem não trabalha com frontend <em>{já que nem todo time tem alguém com esse foco}</em>.</p>
<p>No decorrer desse artigo, junto com os pontos que levantamos, tem algumas implementações básicas de um componente de botão <em>{que chamei ele de base-button}</em> que tem algumas propriedades: <em>tamanho</em>, <em>ícone</em> e <em>loading </em>que são as responsáveis por mudar o comportamento/CSS.</p>
<p>Então aperte o cinto que vamos seguir numa jornada do que nós encontramos em cada uma das possibilidades ✨</p>
<h2>Mas antes, uma leve introdução ao vue file</h2>
<p>Para quem nunca trabalhou com o Vue antes, é possível criar componentes usando arquivos <em>.vue</em>, que possuem o HTML dentro do &lt;template&gt;, o JS dentro de &lt;script&gt; e o CSS dentro de &lt;style&gt;.</p>
<p>Focando no assunto desse post, na parte de CSS nós temos algumas alternativas: escrever o CSS puro <em>{assim como vemos da linha 16 a 18}</em>, ou escrever com algum pré-processador.</p>
<p>Escolhendo a segunda o opção, tudo que nós precisamos fazer é adicionar um atributo <em>lang</em> na linha 15 com o nome da <em>&#8220;linguagem&#8221;</em> que queremos <em>{Aqui na Alice nós usamos o </em><a href="https://sass-lang.com/"><em>SASS</em></a><em> com a sintaxe scss, então a maioria dos exemplos daqui pra frente terão o CSS escrito dessa forma}</em>.</p>
<p>Sabendo disso vamos começar falando de uma das nossas opções de escrever CSS, que não depende de estar usando ou não um pré-processador:</p>
<h3>BEM</h3>
<p>Acredito que essa seja uma das formas mais comum de escrever CSS. Por ser uma metodologia, não tem grandes segredos, mas não significa que seja fácil. Pensar no nome das coisas provavelmente é a parte mais difícil do desenvolvimento de software <em>{risos}</em>, e com o <a href="http://getbem.com/introduction/">BEM</a> é preciso pensar com carinho no nome das classes para que a estrutura faça sentido.</p>
<p>Para quem nunca trabalhou com a metodologia antes, vamos a uma explicação rápida:</p>
<figure><img decoding="async" src="https://cdn-images-1.medium.com/max/670/1*2obrsDtnpAfExJALr3ROpQ.png" alt="" /><figcaption><a href="https://keepinguptodate.com/pages/2020/05/bem-visually-explained/">BEM Visually Explained</a> — By Jon Keeping</figcaption></figure>
<p>Nós basicamente dividimos uma classe em três pedaços:</p>
<ul>
<li>O <em>Block</em> representa o bloco que vai ser estilizado <em>{normalmente algum elemento que esteja envolvendo outros elementos/outras tags}.</em></li>
<li>O <em>Element</em> é algum elemento ou tag que esteja dentro desse bloco, e para identificarmos ele facilmente, é separado por dois <em>underscores</em>.</li>
<li>O <em>Modifier</em> significa que o estado daquele elemento mudou, o que significa que o nosso layout vai mudar graças; a separação dele é por dois <em>dashes</em>.</li>
</ul>
<p>Isso significa que em uma classe eu posso ter dois <em>elements</em>? Ou dois <em>modifiers</em>? Não. A estrutura do BEM espera que você tenha um de cada, por isso para pessoas que não estão familiarizadas com a metologia, pode ser bem confuso como criar uma classe nova. <em>{</em><a href="https://keepinguptodate.com/pages/2020/05/bem-visually-explained/"><em>Nesse artigo</em></a><em> tem uma explicação detalhada do uso do BEM e erros comuns, vale a leitura!}</em></p>
<p>De qualquer forma, se usado corretamente vários problemas de CSS são resolvidos, além de termos uma boa organização.</p>

<p>Agora vamos para a aplicação dessa metologia no Vue.</p>
<p>Começando pelas linhas 4, 5, 6, 7 — aqui nós temos classes condicionais baseadas em alguns atributos <em>{que no nosso exemplo são props declaradas nas linhas 28 e 29}</em>, uma coisa que podemos ver é que por serem condicionais, usamos o <em>modifier</em> para alterar visualmente o layout de cada uma delas <em>{já que elas representam um estado do nosso botão}</em>.</p>
<p>Na linha 12, temos uma classe com um <em>element</em>, pois esse componente de icone representa um elemento no nosso bloco <em>{que nesse exemplo é o botão}</em>.</p>
<p>Por fim, na linha 34 temos a declaração da lang, que como é importante dizer que só vai funcionar se o projeto está preparado para o pré-processador declarado. Se você começar um projeto usando o <a href="https://cli.vuejs.org/">Vue CLI</a> é uma das coisas que você pode ou não escolher. Se você quiser mudar o lang, na <a href="https://vue-loader.vuejs.org/guide/pre-processors.html">documentação do Vue</a> tem um passo-a-passo.</p>
<h3>Scoped CSS</h3>
<p>Você pode se perguntar: por quê exatamente eu preciso do BEM? Não é só sair espalhando minhas classes por ai e tudo bem?</p>
<p>Conforme você vai escrevendo o seu CSS, no final das contas o Vue vai pegar o CSS de todos os componentes sendo usados naquela página e jogar ele no &lt;head&gt;. O que significa que qualquer componente vai ser afetado por qualquer regra definida em um componente. O BEM tenta resolver isso tendo classes especificas que não vão afetar outro componente tão facilmente.</p>
<p>É ai que entra o <a href="https://vue-loader.vuejs.org/guide/scoped-css.html">scoped CSS</a>. Ele nos ajuda a resolver esse problema de escopo adicionando um atributo a mais nas nossas tags HTML para deixar as classes específicas para aquele componente.</p>
<p>Tudo o que precisamos para isso funcione é adicionar o atributo <em>scoped</em> à declaração de &lt;style&gt;, assim como na linha 34 do exemplo.</p>
<p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/4c1cc874afea1ff0fbbb82cd2134220d/href">https://medium.com/media/4c1cc874afea1ff0fbbb82cd2134220d/href</a></iframe></p>
<p>Para entender melhor vamos pegar a classe na linha 5.</p>
<p>O Vue vai transformar ela em algo como: .<em>loading[data-v-763db97b]</em>. Esse atributo novo sempre vai começar com <em>data-v </em>e vai terminar com uma <em>hash </em>aleatória, o que ajuda caso tenhamos classes iguais <em>{elas não vão colidir graças ao hash} </em>e impede que um componente distante seja afetado.</p>
<p>O problema dessa solução é que mesmo com esse atributo a mais na tag HTML, as regras afetam os componentes filhos. Olhando no exemplo ao lado, se o &lt;base-icon&gt; tivesse a classe<em> &#8220;icon&#8221;</em> e removêssemos a linha 12, as regras de CSS dessa classe afetariam o componente filho mesmo assim.</p>
<p>Podemos resolver isso facilmente evitando seletores iguais <em>{até mesmo usando uma metologia como o BEM que vimos anteriomente}</em>, para não correr o risco de herdar regras que não gostaríamos.</p>
<h3>CSS Modules</h3>
<p>Assim como a solução anterior, o <a href="https://vue-loader.vuejs.org/guide/css-modules.html#usage">CSS Modules</a> tenta nos ajudar com esse problema de conflitar regras de CSS ou herdar regras que não gostariamos.</p>
<p>A diferença dele para o <em>scoped</em>, é que não teremos um atributo novo no HTML e sim uma classe gerada pelo Vue, composta pelo nome do componente + o nome da classe que nós colocamos no CSS + uma hash aleatória.</p>
<p>Para que essa solução funcione, precisamos adicionar o atributo <em>module</em> à declaração de &lt;style&gt;, assim como na linha 35 do exemplo.</p>
<p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/835a20022087c3a3aa6756877efde63d/href">https://medium.com/media/835a20022087c3a3aa6756877efde63d/href</a></iframe></p>
<p>Uma das coisas mais importantes aqui é que a sintaxe de declarar uma classe sempre vai ser <em>:class=&#8221;$style.xpto&#8221; </em>e com o nome da classe sempre em <em>camelCase</em>. E no caso de classes condicionais como na linha 5, 6 e 7, precisamos usar a classe dentro de colchetes.</p>
<p>Para entender melhor, vamos pegar a linha 5 de exemplo. No fim das contas o Vue vai gerar uma classe parecida com <em>BaseButton_loading_1VuSe</em>. Isso vai resolver o nosso problema de conflito de regras e não é algo que interfere nos filhos.</p>
<p>Mas <em>e se</em> você quisesse que isso acontecesse? Até agora pontuei que um componente filho herdar as regras do pai era uma coisa ruim, mas dependendo da situação é exatamente isso que nós queremos para não repetir código.</p>
<p>Nesse caso, você pode passar as classes como <em>prop</em> para o componente filho, ou usar <a href="https://sass-lang.com/documentation/at-rules/mixin">mixins</a> de um pré-processador e importar nos dois componentes.</p>
<figure><img decoding="async" src="https://cdn-images-1.medium.com/max/1024/0*zmhmFWohYMyOXc0X" alt="" /><figcaption>Photo by <a href="https://unsplash.com/@alistairmacrobert?utm_source=medium&amp;utm_medium=referral">Alistair MacRobert</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure>
<h3>Achou que tinha acabado?</h3>
<p>Achou errado!</p>
<p>As três soluções que vimos até agora, são as formas oficiais do Vue de definir CSS, mas a partir daqui vamos entrar no mundo obscuro das formas alternativas.</p>
<p>Nós separamos duas para testar e ambas são frameworks <a href="https://cssinjs.org/?v=v10.5.1">CSS-in-JS</a>, o que significa que nós escrevemos o CSS no JS e não precisamos mais da tag &lt;style&gt; nos nossos componentes.</p>
<h3>Aphrodite</h3>
<p>Começando pelo <a href="https://github.com/Khan/aphrodite">Aphrodite</a> <em>{que não tem muita coisa sobre o uso dele com o Vue na internet e eu usei </em><a href="https://medium.com/@nicholasbaroni/styling-vue-components-with-aphrodite-dd53bc2fa9d8"><em>esse artigo</em></a><em> como referência para a minha implementação}</em>.</p>
<p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/15e50f0ad53bdfef0f348b7478f076a7/href">https://medium.com/media/15e50f0ad53bdfef0f348b7478f076a7/href</a></iframe></p>
<p>Inicialmente, nós precisamos importar duas coisas do framework: o <em>StyleSheet</em> e o <em>css {como vemos na linha 8}</em>.</p>
<p>O <em>StyleSheet </em>vai ser o responsável por gerar as nossas regras de CSS baseado na estrutura de objeto com o nome da classe sendo a chave, e o valor sendo os atributos de CSS <em>{linha 10 à 19}</em>.</p>
<p>E para que nós possamos usar essas classes no HTML, primeiro precisamos expor elas no JS <em>{como vemos da linha 22 à 24} </em>e usamos o <em>css </em>na linha 2 <em>{separando os nomes das classes por vírgula se necessário}</em>.</p>
<p>Agora vamos voltar o mesmo componente de botão dos exemplos anteriores, mas dessa vez usando Aphrodite:</p>
<p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/c19aebfbe771d7f29025293b5708c073/href">https://medium.com/media/c19aebfbe771d7f29025293b5708c073/href</a></iframe></p>
<p>Temos algumas limitações com essa solução, e de cara o que mais me incomodou foi que por padrão todas as regras são geradas com<em> !important</em>. A linha 18 poderia estar importando só de <em>&#8216;aphoridite&#8217;</em>, mas para não ter o comportamento de <em>!important</em>, eu acabei importando as dependências necessárias de outro pacote.</p>
<p>Também não existe um jeito oficial de definir classes aninhados <em>{ou seja, uma classe dentro de outra classe}</em>, com isso precisamos ter classes diferentes para um estado específico de um elemento, como por exemplo na linha 27 e 28, onde o componente de ícone que nos exemplos anteriores só tinha uma classe, aqui nós precisamos de duas.</p>
<p>Com essa implementação, as classes geradas são completamente aleatórias <em>{algo parecido com _w3twfb}</em>, o que dificulta um pouco encontrar onde que essas regras foram definidas, mas tem a vantagem de serem nomes curtos.</p>
<p>Por fim, a implementação de exemplo não é a mais otimizada possível, dá para criar um plugin que importe o Aphrodite em todos os nossos componentes.</p>
<h3>Styled Components</h3>
<p>Por fim chegamos na última opção da nossa lista, o <a href="https://github.com/styled-components/vue-styled-components">Styled Components</a>, que nos permite criar componentes estilizados.</p>
<p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/ec9dd6c8f4bca0bdc59cb46af4576e02/href">https://medium.com/media/ec9dd6c8f4bca0bdc59cb46af4576e02/href</a></iframe></p>
<p>Na linha 22 e 33 temos dois componentes sendo definidos usando o <em>styled</em> importado do framework. O primeiro parâmetro é a tag HTML que vai ser renderizada, o segundo são as <em>props</em> daquele componente. A partir dai é possível retornar todas as regras de CSS necessárias<em> {e condicionar elas dependendo de uma propriedade, o que nos dá muita liberdade}</em>.</p>
<p>Por mais diferente que essa implementação seja, esses dois componentes são iguais a qualquer outro definido por um arquivo vue <em>{claro, com as suas limitações, ele é um componente puramente visual, então não vamos ter métodos ou outros tipos de atributos nele} </em>e precisa ser declarado como na linha 42 para ser usado pelo HTML.</p>
<p>Eles também não precisavam estar dentro do <em>vue file</em> <em>{só coloquei aqui para facilitar o exemplo rs}.</em> Por serem componentes normais, poderiam estar em arquivos separados para serem importados pelo base-button.</p>
<p>É uma solução simples para componentes básicos.</p>
<figure><img decoding="async" src="https://cdn-images-1.medium.com/max/1024/0*U_Hpbae9C1fL-0mi" alt="" /><figcaption>Photo by <a href="https://unsplash.com/@sagarapher?utm_source=medium&amp;utm_medium=referral">Sagar Rana</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure>
<h2>Conclusão</h2>
<p>Depois de muita discussão e uni-duni-tê, nós escolhemos usar o <strong>CSS Modules</strong> como padrão aqui na Alice <em>{pessoalmente, eu ainda prefiro usar o BEM, mas vamos manter isso entre eu e vc, blz? haha}</em>.</p>
<p>Pelas nossas conversas, foi a opção que mais fez sentido para o nosso momento e para os nossos produtos, onde muitas pessoas precisam mexer. Mesmo sendo uma sintaxe <em>diferente do normal</em>, é algo rápido de aprender/entender e ganhamos uma certa liberdade com qual nome de classes vamos colocar <em>{além de impedir certos problemas de herdar regras desnecessárias/ter seletores de tag HTML}</em>.</p>
<p>Mas por que fizemos essa escolha? As outras opções são ruins?</p>
<p>Particularmente as soluções não oficiais não me agradam, pois é uma dependência a mais que precisamos colocar no projeto, temos uma curva de aprendizado para escrever o CSS dentro do JS, e do meu ponto de vista não é mais vantajoso do que usar uma solução oficial do Vue.</p>
<p>Porém, não existe solução perfeita, não tem uma forma melhor do que a outra, no fim das contas é necessário considerar o que mais faz sentido para o projeto e para as pessoas que vão dar manutenção no código.</p>
<p>Hoje o <em>CSS Modules</em> faz sentido pra gente, mas quem sabe daqui um tempo não faça mais. É importante ter a mente aberta para qualquer solução, e do meu ponto de vista, manter o mais simples possível. 🙂</p>
<h3>Que tal fazer parte desse time?</h3>
<p>Estamos buscando pessoas que topem o desafio de transformar a saúde no Brasil através da tecnologia. <a href="https://www.alice.com.br/carreiras">Clica aqui</a> para saber mais das vagas que temos em aberto! 🙂</p>
<p>O post <a href="https://alice.com.br/tech/qual-a-melhor-forma-de-escrever-css-no-vue/">Melhor forma de escrever CSS no Vue</a> apareceu primeiro em <a href="https://alice.com.br/tech">Blog da Alice Tech</a>.</p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
