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
Como promover a aprendizagem acelerada dentro de uma organização?
Tech Writers Agosto 01, 2022

Como promover a aprendizagem acelerada dentro de uma organização?

Vivemos um momento de transformações significativas na sociedade, sejam elas relacionadas à evolução humana ou causadas pela recente pandemia de Covid-19. O cenário de mudança exige esforço de adaptação e visão estratégica apurada. Nesse contexto, a capacidade de aprendizagem acelerada é muito útil, especialmente no mercado de trabalho.  Por outro lado, a aprendizagem acelerada tem tudo a ver com a flexibilidade cognitiva. Essa, por sua vez, liga-se à capacidade contínua de aprendizagem da pessoa, o que permite a adequação a diferentes cenários.  Em contextos relacionados à evolução tecnológica, requisita-se ainda mais a flexibilidade cognitiva. Isso porque, a velocidade de transformação de conceitos, técnicas de aprendizagem, ferramentas e procedimentos digitais é ainda maior do que em contextos antes analógicos. Sendo uma empresa de tecnologia, as mudanças do negócio e a evolução do conhecimento técnico são variáveis recorrentes na Softplan. Além disso, geram impacto em toda a estrutura, de processos a produtos fornecidos. A promoção da aprendizagem acelerada também liga-se à visão da liderança. Ela demanda que gestores compreendam a importância do aprendizado contínuo para a sustentabilidade do seu negócio. No conteúdo de hoje vamos contar uma das nossas experiências neste processo de aceleração da aprendizagem. Fique com a gente!  Quais os desafios da aprendizagem acelerada? O desenvolvimento do SAJ (Sistema de Automação da Justiça), exige, não apenas conhecimento em tecnologia, mas também em relação aos processos das instituições clientes e legislações vigentes. Por isso, é necessário para o seu desenvolvimento, a criação, manutenção e disseminação de conhecimentos muito especializados. Além das particularidades do negócio da Softplan, temos ainda o avanço da tecnologia em diferentes segmentos da economia, impactando diretamente na demanda por mão de obra qualificada em TECH. Por isso, iniciamos em 2019 o projeto “Academia de Base”, um dos exemplos de ação com foco na aprendizagem acelerada em um contexto corporativo.  Criamos um modelo de programa de estágio, em que a própria capacitação se revelou também um processo seletivo natural, levando para a efetivação somente os profissionais de fato aptos ao atendimento aos clientes e já adaptados à cultura da unidade.  Já realizamos 4 edições, com mais de 900 inscritos e mais de 60 pessoas capacitadas neste modelo! Como realizamos o projeto “Academia de Base”?  O projeto “Academia de Base” foi desenhado para resolver os desafios relacionados à disseminação de conhecimento especializado no time de Suporte da Unidade de Justiça, focando na inteligência necessária ao atendimento aos clientes da Softplan. As principais características foram:  Programação de fases de capacitação Na programação das fases de capacitação organizamos como se dariam os repasses de conhecimentos sobre: Tecnologia (produto SAJ e configurações);  Regra de negócio (processos do judiciário); Processos e ferramentas de trabalho; Essa etapa foi feita em ondas incrementais de aprendizagem e com realização de atividades práticas (“hands on” na etapa de acompanhamento em campo). Conteúdos adaptáveis  Conteúdo com possibilidades de adaptação para atender às demandas específicas de conhecimento dos times da operação de atendimento. Nesse sentido, permitindo uma certa flexibilidade na modelagem de cada turma. Processo seletivo com base em perfil comportamental  O processo seletivo para participação no projeto foi realizado baseado em perfil comportamental. Ou seja, nossos critérios foram além da seleção por curso de graduação correlacionado ao negócio da Justiça. Instrutores Capacitados e materiais de apoio relacionados Para realizar o projeto, buscamos alocar colaboradores com conhecimento especializado avançado e com ampla experiência no atendimento aos clientes como instrutores. Além disso, realizamos a disponibilização de materiais, bases de dados, bases de conhecimento, documentações de produto e práticas totalmente correlacionados à realidade do trabalho do suporte. Proximidade com a rotina de trabalho Elaboramos um período de “sombra” para os participantes do projeto. Ou seja, nesse momento, os estagiários realizaram o acompanhamento da rotina real de trabalho, definindo mentores para orientação no dia a dia. Acompanhamento contínuo  Promovemos o acompanhamento constante da evolução do aprendizado dos estagiários, incluindo avaliações teóricas, práticas, banca técnica, feedbacks constantes e pesquisa junto aos mentores. Além disso, mapeamos a evolução do conhecimento técnico através de auto avaliação e levantamento de dados de produtividade de cada estagiário no período pós-efetivação. Criação da Marca do projeto Criamos uma marca para o projeto, promovendo o senso de pertencimento dos estagiários a uma iniciativa inovadora de desenvolvimento de carreira, e de alta qualidade como ação educadora. O que aprendemos com o projeto? A aplicação desse projeto resultou em muitas lições. Percebemos que, apesar de não haver uma única fórmula de aprendizagem acelerada, algumas estratégias e ações podem potencializar esse processo.  As principais inferências sobre a relação entre os resultados gerados pela “Academia de Base” e a aplicação de práticas de Gestão do Conhecimento, referenciadas neste estudo, são: Criação de um modelo de replicação do conhecimento especializado para novos colaboradores totalmente escalável quanto à estratégia de seleção, planejamento, execução e monitoramento. Isso confirma a importância de um programa de capacitação incremental e conectado com os conhecimentos requisitados pela operação do negócio; Aplicação do modelo de aprendizagem centrado na prática (experimentação dos processos e dos sistemas). Isso  otimiza o aprendizado para adultos (reforçando a assertividade da escolha de metodologias fundamentadas na andragogia); Valor estratégico da atuação do time da Gestão do Conhecimento para desenho da metodologia, planejamento, logística e execução do programa, implementando práticas da governança multinível recomendada no modelo de Universidade Corporativa em Rede; Aceleração da aprendizagem em função da disponibilização de especialistas de diferentes áreas da vertical de Justiça como instrutores para realização dos tópicos de treinamento previstos no programa, reforçando a importância da aprendizagem organizacional centrada na prática do trabalho cotidiano; Impacto financeiro positivo, justificando o investimento financeiro para contratação de estagiários em modelo de capacitação para melhor assertividade na contratação em modelo CLT, demonstrando que as boas práticas de Gestão do Conhecimento podem ser traduzidas em retorno quantitativo para a organização (custos gerais reduzidos e indicadores de produtividade aumentados). Nossa experiência reforçando os processos de Gestão do Conhecimento evidenciam os impactos positivos gerados por uma estratégia sólida de investimento em ações focadas no capital intelectual. Em síntese: para a obtenção de melhores resultados, investir em pessoas é crucial ! Quer saber mais sobre o assunto? Recomendo:  https://justicadigital.com/unisoft-gestao-do-conhecimento/  https://www.linkedin.com/pulse/acelera%C3%A7%C3%A3o-da-aprendizagem-na-unidade-de-justi%C3%A7a-softplan-prado/?trk=public_profile_article_view Gostou de saber um pouco mais sobre aprendizagem acelerada e como buscamos aplicá-la na Softplan?  Confira mais conteúdos como esse em nosso Blog! Quer ser nosso próximo Tech Writer? Confira nossas vagas na página Carreira!

Microsserviços do “tamanho certo” – Parte I
Tech Writers Julho 18, 2022

Microsserviços do “tamanho certo” – Parte I

Uma pergunta difícil de ser respondida quando trabalhamos com microsserviços é com relação ao “tamanho” adequado das aplicações que constituem o ecossistema.   A princípio, apenas para citarmos alguns exemplos e evidenciar a importância do assunto, serviços de granularidade inadequada podem implicar em:   Aumento do custo de manutenção e do índice de retrabalho das equipes;  Prejuízo nos requisitos não funcionais como escalabilidade, elasticidade e disponibilidade;  Agravamento do impacto de arquitetura descentralizada em termos de performance;  Complexidade acidental no monitoramento e detecção de falhas da aplicação.  Determinar a granularidade adequada é uma tarefa difícil. Provavelmente, não será na primeira tentativa que você obterá sucesso.  Nesse artigo, trarei alguns insights de possíveis cenários que justificam a decomposição de uma aplicação em microsserviços menores para te ajudar nessa questão. Confira! Granular ou modular microsserviços? Para compreendermos melhor as justificativas que irão nos conduzir durante o processo de refinamento da aplicação, devemos esclarecer a diferença conceitual entre os termos “granularidade” e “modularidade”.  Embora intimamente relacionados, tratam de aspectos arquiteturais distintos.   Modularidade, em nosso contexto de discussão, trata da organização interna de uma aplicação em componentes separados de alta coesão e com baixo acoplamento.  Idealmente, toda aplicação (principalmente monolíticas) deve ter essa preocupação, sendo desenvolvida em um formato modular flexível que facilite uma eventual decomposição.  A ausência de modularidade conduzirá o projeto ao perigoso e quase certamente irreversível big ball of mud (ou ainda pior: big ball of distributed mud). Figura 1- Exemplo de módulos coesos com dependência  Granularidade, por outro lado, diz respeito ao tamanho dos nossos módulos e/ou serviços. Em uma arquitetura distribuída é muito mais comum termos problemas com granularidade do que com a modularidade.   O ponto central dessa discussão é que uma arquitetura modular facilita muito a quebra de um serviço centralizado em microsserviços mais refinados, sendo quase um pré-requisito para uma decomposição arquitetural de menor esforço e com risco controlado.  A velha advertência de refatorar um trecho de código problemático antes de alterar seu comportamento também pode, nas devidas proporções, nos servir de orientação. Assim, é uma escolha sábia reestruturar um serviço em um formato modular flexível antes de aplicar as diretrizes que abordaremos na sequência.  Dica: Ferramentas simples como NetArchTest (.NET) e ArchUnit (Java) podem ser utilizadas pelo arquiteto para garantir a modularidade de uma aplicação, seguindo o conceito de fitness functions e arquiteturas evolucionárias! Critérios de desintegração dos microsserviços Afinal de contas, quais seriam os critérios que justificariam quebrar um serviço em aplicações menores?   São eles:  Escopo e funcionalidade;  Código de alta volatilidade;  Escalabilidade e throughput;  Tolerância à falha;  Segurança;  Extensibilidade.  A seguir, explicaremos melhor cada um desses tópicos: Escopo e funcionalidade Essa é a justificativa mais comum na quebra de granularidade de um serviço. Um microsserviço objetiva ter alta coesão. Desse modo, deve fazer uma única coisa e fazê-la muito bem.  A natureza subjetiva desse critério pode induzir a decisões equivocadas de arquitetura.  Como “responsabilidade única” acaba dependendo da avaliação e interpretação individual de cada um, é muito difícil afirmar com precisão quando essa recomendação é válida.  Observe a imagem: Figura 2 – Decomposição de serviço com boa coesão  No exemplo acima, as funcionalidades estão intimamente relacionadas dentro de um mesmo contexto de negócio (notificação). Avaliando apenas do ponto de vista da coesão, é provável que não tenhamos uma boa justificativa para uma decomposição arquitetural. Figura 3 – Serviço tratando de funcionalidades sem relação  Agora, considere um único serviço que gerencia o perfil do usuário e é responsável por manipular uma sessão de comentários. Claramente, estamos falando de contextos de negócio distintos e seria mais fácil de aceitar uma decisão apoiada nessa justificativa.  Para reforçar: este critério, por si só, muitas vezes não justifica a quebra de um serviço. Geralmente, ele é aplicado em conjunto com outros critérios, reforçando a tomada de decisão.   2 – Código de alta volatilidade A velocidade que o código fonte muda é uma ótima diretriz para fundamentar a decomposição de uma aplicação.  Imagine um serviço de títulos financeiros, no qual o módulo de histórico tem novas implementações a cada semana, enquanto os módulos de títulos a pagar e receber são alterados a cada seis meses. Figura 4 – Separando código de alta volatilidade  Nessa situação, a decomposição arquitetural pode ser uma decisão sábia para reduzir o escopo de testes antes de cada liberação.  Além disso, essa decisão também trará ganho de agilidade e manterá nosso risco de deploy controlado, garantindo que o serviço de títulos não seja mais afetado pelas frequentes mudanças na lógica do serviço de histórico.  3 – Escalabilidade e throughput Muito semelhante ao item anterior, o throughput de um serviço pode ser uma ótima justificativa para a quebra da aplicação.  Diferentes níveis de demanda, em diferentes funcionalidades, podem exigir que o serviço tenha que escalar de formas distintas e independentes.  Manter a aplicação centralizada pode impactar diretamente a capacidade e os custos da arquitetura em termos de escalabilidade e elasticidade.  Dependendo do contexto de negócio, este critério, por si só, pode ser suficiente para justificar sua decisão.  Figura 5 – Serviço com diferentes níveis de requisição em tpm (transactions per minute)  4 – Tolerância à falha O termo tolerância à falha descreve a capacidade de uma aplicação de continuar operando mesmo quando uma determinada parte desta aplicação deixa de funcionar.  Vamos considerar o exemplo anterior. Imagine um cenário onde o serviço de histórico, por integrar com diversas aplicações de terceiros fora da nossa arquitetura, costuma falhar com certa frequência, chegando ao ponto de reiniciar todo o serviço de títulos financeiros e gerar indisponibilidade.  Nesse caso, uma decisão compreensível seria: separar a rotina problemática em um serviço isolado. Para, assim, manter nossa aplicação funcional a despeito de eventuais falhas catastróficas no serviço de históricos. Figura 6 – Separando uma rotina problemática para melhorar a tolerância à falha 5 – Segurança Considere o exemplo ilustrado na figura abaixo. Nele, um serviço que trata das informações básicas de um usuário (endereço, telefone, nome etc.) precisa gerenciar dados sensíveis dos seus cartões de crédito.  Essas informações podem ter requisitos distintos com relação ao acesso e a proteção dos mesmos.  Quebrar o serviço, neste caso, pode auxiliar em:  Restringir ainda mais o acesso ao código cujos critérios de segurança sejam mais rigorosos; Evitar que o código menos restrito seja impactado com complexidade acidental de outros módulos.  Figura 7 – Serviços com critérios de acesso e segurança distintos  6 – Extensibilidade Uma solução extensível tem a capacidade de ter novas funcionalidades adicionadas com facilidade conforme o contexto de negócio cresce. Essa habilidade também pode ser um forte motivador para segregar uma aplicação.   Imagine que uma empresa tem um serviço centralizado para gerenciar formas de pagamento e deseja suportar novos métodos.  Certamente, seria possível consolidar tudo isso em um único serviço. Porém, a cada nova inclusão, o escopo de testes se tornaria mais e mais complexo, aumentando o risco de liberação, e, com isso, o custo de novas modificações.  Dessa forma, uma forma de mitigar esse problema, seria separar cada forma de pagamento em um serviço exclusivo. Assim, seria permitido que novos serviços pudessem subir e estender a funcionalidade atual sem impactar o código em produção ou aumentar o escopo de testes, mantendo, assim, o risco de novas implementações sob controle. Figura 8 – Segregação de serviços para permitir extensibilidade  Conclusão Dificilmente um arquiteto irá acertar de primeira. Requisitos mudam. Conforme aprendemos com nossas ferramentas de telemetria e feedback, a decomposição arquitetural de uma aplicação acaba sendo um processo natural dentro de uma aplicação moderna e evolutiva.  Felizmente, temos exemplos baseados na experimentação prática que nos servem de balizadores nessa empreitada:  Garanta que seu serviço possui uma estrutura interna modular flexível;  Avalie com calma os critérios que justifiquem uma decomposição arquitetural;  Considere cada trade-off face às necessidades do seu contexto de negócio.  Por fim, aos leitores que desejam saber mais sobre o tema, recomendo a leitura do livro que fundamentou este artigo: Software Architecture: The Hard Parts. Uma abordagem profunda e prática sobre este e muitos outros desafios enfrentados na arquitetura de software moderna de sistemas complexos.  Posteriormente, na parte II deste artigo, discutiremos os critérios que podem levar um arquiteto a unificar serviços distintos em uma aplicação centralizada. Fique ligado! Gostou de conhecer um pouco mais sobre Microsserviços? Me conte aqui nos comentários!  Confira mais conteúdos como esse em nosso Blog! Quer ser nosso próximo Tech Writer? Confira nossas vagas na página Carreira!

Singleton: guia completo para entender essa polêmica de uma vez por todas!
Tech Writers Julho 04, 2022

Singleton: guia completo para entender essa polêmica de uma vez por todas!

O Singleton corresponde a um padrão de projeto de software. Padrões de projeto, conforme tratei no meu artigo sobre o Strategy, nada mais são do que um catálogo de soluções a problemas comuns.  Cada padrão de projetos carrega prós e contras; benefícios e custos de implementação. No caso específico do Singleton, os críticos consideram estes “custos” grandes demais. Neste artigo, vou te explicar o que é singleton, quais os “problemas” que ele pode trazer para o código, e quais as alternativas do seu uso. Continue a leitura!  O que é um Singleton? Para entendermos as dificuldades que o padrão de projeto Singleton traz, primeiro precisamos definir o que é um “Singleton”. Afinal de contas, muitas vezes, é a própria confusão sobre o conceito que torna algumas pessoas contra esse padrão.  Podemos começar com a seguinte afirmação: uma instância única de determinado objeto durante a vida útil de uma requisição não é um Singleton. Um Singleton, por definição, é justamente esta instância acessível globalmente no projeto. Análogo às descrições dadas pela GoF (Gang of Four), no livro “Design Patterns”, podemos elencar 3 características básicas para definir o que precisamos para criar um Singleton: Ele deve possuir uma única instância durante a vida útil da aplicação; Não deve ser possível instanciá-lo através do seu construtor, que precisa ter visibilidade preferencialmente privada; Sua instância deve estar disponível de forma global, no seu projeto. Estas definições são muito importantes, pois a falha no entendimento do que um Singleton representa pode acabar levando pessoas a não entenderem a acusação de ele ser considerado um anti-pattern. Anti-Pattern? É de comer? Anti-Patterns, ao contrário do que soa à primeira vista, não são necessariamente o oposto de um padrão de projeto. Os chamados “anti-padrões”, em resumo, são respostas comuns a problemas frequentes, que são normalmente ineficazes e têm um grande risco de serem contraproducentes. Atenção no detalhe: são “respostas comuns” para “problemas frequentes”.  Ou seja, ser um anti-pattern não anula o fato de o Singleton continuar sendo um padrão de projetos.  Os anti-padrões têm mais a ver com o uso errado de uma solução correta, do que a solução em si ser algo ruim  ─ apesar de que isso também pode ocorrer. O Singleton na prática O Singleton, como já explicado, provê ao desenvolvedor uma instância única de um objeto e de escopo global. Abaixo, segue um exemplo de como seria sua implementação utilizando a linguagem de programação Java. public class Singleton {     private static Singleton instance;     private Singleton() {}     public static Singleton getInstance() {         if (instance == null) {             instance = new Singleton();         }         return instance;     } } Observação: Apesar de na classe de exemplo estar explicitado o nome “Singleton”, é importante reforçar que você não precisa mencionar o nome do padrão de projetos no nome da classe. Isso apenas foi feito para exemplificar a sua estrutura. O Singleton pode ser uma solução viável caso esteja em uma situação em que se apresente esses dois problemas: Você precisa de apenas uma instância de um “objeto X”; Você precisa acessar essa instância de qualquer lugar da sua aplicação. Caso um dos dois itens acima não fizerem parte das suas necessidades, provavelmente há outra saída para o seu problema. Se você não necessitar de uma única instância, o construtor de seu objeto não precisa ser privado. Basta instanciar seu objeto onde quer que você precise utilizá-lo; Se não é preciso acessar sua instância de qualquer lugar, significa que você possui um escopo limitado. Neste caso, uma alternativa seria identificar “a partir de onde” é necessário acessar seu objeto. Uma forma de fazer isso consiste em criar um campo estático privado que guarde sua instância e passar este objeto por injeção de dependência onde quer que ele seja utilizado.  O tema “injeção de dependência” e sua ligação com o Singleton, será abordado mais adiante ainda neste artigo. Benefícios do Singleton Apesar da resistência de algumas pessoas, os Singletons possuem benefícios bastante interessantes.  Confira alguns deles:  É extremamente fácil de acessar: servindo como uma variável “de escopo global”, fica evidente que seu acesso é excepcionalmente simples. Não há a necessidade de transitar a instância do seu objeto por todo o seu sistema. Garante que só haja uma única instância: independente de qual o objeto ou motivo, o Singleton vai garantir que exista apenas uma única instância dentro do seu projeto. Assim, são evitadas falhas lógicas que podem envolver esta regra. Algo interessante de se comentar, que tem direta ligação com os benefícios citados acima, é a sua versatilidade para atuar como uma chave Mutex (Mutual Exclusion). Em ambientes multi-thread, onde duas ou mais operações podem entrar em concorrência, a instância da “chave” se mantém sendo uma só. Dessa forma, o controle de execuções é facilitado.  Evidentemente, o Singleton em si não está isento de concorrências. Por isso, precisa de um tratamento adequado dependendo da linguagem em que está sendo utilizado, para que, assim, possa ser considerado uma solução thread-safe. Se você nunca ouviu falar sobre Mutex (também chamados de “semáforos”, ou “locks”), mas se interessou pelo assunto, recomendo uma leitura deste artigo. Custos do Singleton Fazendo uma breve pesquisa, podemos encontrar vários artigos de diferentes autores comentando sobre custos diversos que envolvem a implementação de um Singleton.  Dentre os mais discutidos, os que mais considero interessantes abordar, são: Quebra dos princípios SOLID; Fator “falta de rastreabilidade”; Dificulta na implementação de testes; Sacrifica transparência, por conveniência. Para tornar mais fácil a digestão do que cada problema representa, vou explorar cada um desses fatores nos próximos tópicos.  Ele quebra os princípios SOLID A primeira e mais comum questão quando se trata do Singleton, é que ele quebra os princípios do SOLID. Para ser mais exato, o Princípio da Responsabilidade Única (SRP – Single Responsability Principle). O seguinte trecho é responsável pelo problema: public static Singleton getInstance() {     if (instance == null) {         instance = new Singleton();     }     return instance; } Isso acontece, porque, além de o Singleton ter o controle do ciclo de vida do objeto (sua instância interna), ele também garante o acesso do mesmo. Com esses dois fatores somados, acabamos com duas responsabilidades. Mas, o que deveria ser feito para que não houvesse a quebra do SRP? Em resumo, a responsabilidade de popular o instance deveria ser delegada para outra classe; exatamente uma das propostas de outro padrão de projetos, conhecido como Monostate. Caso queira saber mais sobre o SRP e entender o porquê da sua importância, recomendo a leitura do nosso artigo Conheça um dos princípios SOLID mais importantes: Single Responsibility Principle, escrito por meu colega, Pacifique Mukuna. Falta com rastreabilidade Suponhamos que você está em uma situação em que precisa criar e controlar as instâncias de um usuário de um determinado sistema, e que apenas um usuário pode estar conectado por vez. Uma possibilidade seria a de criar uma classe “gestora” dessa instância de usuário conectado. Existem algumas alternativas possíveis para seguir com o desenvolvimento. Criar um Singleton servindo como a “classe gestora” é uma delas. Assim, não seria necessário se preocupar com as partes do sistema que precisarão consumir este usuário conectado: basta recuperar a instância da classe gestora, que é acessível de qualquer lugar do projeto. Agora, podemos fazer uma reflexão: “neste sistema, qual o objeto que pode alterar o usuário que está conectado?” Parece fácil: “o Gestor”, provavelmente seria a primeira resposta. Refletindo um pouco mais na solução, podemos observar um detalhe muito importante sobre este desenho: a classe gestora é acessível de qualquer lugar do sistema. Portanto, a solução implica que o usuário pode ser alterado de qualquer local também. Indo um pouco mais além neste exercício, podemos esquecer a classe “usuário” e substituí-la pelo “Objeto Genérico X”, que constantemente é modificado pelos objetos que o chamam. Observe que conforme o nosso objeto Gestor é utilizado, mais comum passa a ser o fator “falta de rastreabilidade”. A questão aqui é mais filosófica do que prática. O fato é que, por mais que seja justificado o seu uso, podemos concluir que há duas questões absolutas e intrínsecas neste padrão de projetos: Você não pode garantir que as propriedades do seu objeto não vão mudar, quando não deveriam mudar. Neste quesito, o acesso global é o fator que torna muito difícil prever o uso indevido do Singleton; Como consequência do fator anterior, se houver uma modificação indevida nas propriedades do seu objeto, é extremamente complexo de identificar o ponto em que está havendo a alteração. Principalmente em grandes aplicações onde operações que modificam as propriedades do objeto são comuns. Torna difícil a implementação de testes Sobre esse ponto, quero que você preste atenção. Não estou dizendo que o Singleton é difícil de testar, mas sim que ele torna difícil a implementação de testes. Isso ocorre, geralmente, no código que o consome. Para não me estender nesta explicação, leve em consideração que para ter o entendimento do porquê o Singleton dificulta a implementação de testes, é necessário ter uma base do que são testes automatizados. Em especial testes unitários e como eles são implementados. Mas, de forma resumida, um teste unitário consiste nas seguintes ideias: Testar uma classe de forma isolada: se todas as partes de um determinado sistema estiverem funcionando de forma independente, não deveria haver problema quando todas juntas. Porém esse é um assunto discutível, e depende da intenção do desenvolvedor; Testar de forma independente: além de testar a classe de forma isolada, cada teste deve ser absolutamente independente um do outro. Independentemente da ordem de execução, todos os testes precisam passar; Testar de forma rápida: por consequência dos pontos anteriores, os testes unitários têm a peculiaridade de serem de pequeno escopo, e, portanto, são de rápida execução. Os testes unitários são a base daquilo que na engenharia de software é conhecido como “pirâmide de testes”. Em ordem de prioridade, são aqueles que deveriam existir em mais abundância nos projetos. Para entendermos o problema que o Singleton pode apresentar durante a execução de um teste unitário, podemos recuperar a ideia descrita mais acima, sobre existir uma “classe gestora” do usuário conectado. Vamos chamá-la de RegistroUsuario.  Além disso, levemos em consideração que determinado sistema possui um serviço com a seguinte verificação: public class Servico {     public boolean usuarioPodeCadastrarNovosClientes() {         // Obtém a instância do Singleton         RegistroUsuario registroUsuario = RegistroUsuario.getInstance();         // Guarda o usuário conectado no sistema em uma variável         Usuario usuarioLogado = registroUsuario.getUsuarioLogado();         // Faz um retorno indicando se o usuário conectado tem a permissão         return usuarioLogado != null && usuarioEhAdmin(usuario));     }     private boolean usuarioEhAdmin(Usuario usuario) {         return “ADMIN“.equals(usuario.getPermissao());     } } O serviço acima é relativamente simples, e apenas verifica se o usuário conectado no sistema atualmente possui permissão para cadastrar novos clientes.  O método deve retornar “VERDADEIRO”  se houver um usuário conectado, e este usuário possuir a permissão “ADMIN”. Se você já tem o costume de criar testes, facilmente conseguirá identificar três possíveis cenários: ou o usuário é ADMIN; ou o usuário não é ADMIN; ou não tem usuário conectado. Podemos criar uma classe de teste unitário para automatizar estas verificações, como no exemplo abaixo: public class ServicoTest {     private Usuario usuarioAdmin = new Usuario(“ADMIN“);     private Usuario usuarioComum = new Usuario(“COMUM“);     private Servico servico;     @Before     public void setUp() {         this.servico = new Servico();     }     @Test // Quando não há usuário conetado.     public void teste01() {         RegistroUsuario.getInstance().setUsuarioLogado(null);         Assert.assertFalse(servico.usuarioPodeCadastrarNovosClientes());     }     @Test // Quando há usuário conetado, mas não possui permissão.     public void teste02() {         RegistroUsuario.getInstance().setUsuarioLogado(usuarioComum);         Assert.assertFalse(servico.usuarioPodeCadastrarNovosClientes());     }     @Test // Quando há usuário conetado, e possui permissão.     public void teste03() {         RegistroUsuario.getInstance().setUsuarioLogado(usuarioAdmin);         Assert.assertTrue(servico.usuarioPodeCadastrarNovosClientes());     } } Acontece que os testes unitários, na maioria dos casos, rodam em paralelo por serem independentes. É exatamente neste ponto que o Singleton passa a ser um problema. A execução em paralelo faz com que os testes executem modificações no Singleton em concorrência, e, quando teste01, por exemplo, for realizar o assert da informação invocando o método do serviço, é bem provável que outro teste, como o teste02, já tenha modificado o valor do Singleton novamente, o que causaria um falso-negativo no assert do teste01. Talvez o gráfico abaixo facilite em elucidar o exemplo descrito acima: Retomando o segundo item elencado sobre a definição de um testes unitário: os testes devem ser independentes. Portanto, em alguns casos, é extremamente difícil de testar unitariamente um código que consome um Singleton. Principalmente se o Singleton tiver uma ligação direta com o retorno do método que você está testando. Sacrifica transparência, por conveniência No artigo “Singletons são mentirosos patológicos”, de Misko Hevery, é dado um bom contexto por meio de testes de qual é o problema aqui: Singletons, dentre muitos outros problemas, podem tornar excepcionalmente difíceis análises e descoberta de cadeias de dependências. O exemplo utilizado por Hevery pode ser considerado um tanto extremo. E, talvez, realmente seja, por ser um caso bem particular de um evento que ocorreu com ele enquanto desenvolvia para a Google. Mas, o seu principal ponto continua sendo válido: o Singleton nada mais é do que um estado global.   Estados globais fazem com que seus objetos possam secretamente se apossar de coisas que não são declaradas em suas interfaces. Como resultado, Singletons transformam suas interfaces em mentirosos patológicos. Assim, podemos interpretar a frase “sacrifica transparência por conveniência” como sendo algo comum de variáveis de escopo global, por não haver explícito as dependências na interface do código que consome o Singleton. Análogo à imagem acima, podemos dizer que o método fazAlgumaCoisa(), do Objeto A, não sabe que o fazOutraCoisa(), do Objeto B, utiliza o Singleton. E,  novamente, isto torna excepcionalmente complexo análises de cadeias de dependências. Hevery, em especial, fez uma palestra para a Google Tech Talks em 2008, a qual eu recomendo muito caso você entenda inglês e se interesse pelo tema. Na palestra, ele aprofunda no fato de ele considerar Singletons uma má prática. Singleton versus Monostate O Monostate Pattern, ou simplesmente “Monostate”, foi um padrão de projetos proposto por Robert C. Martin em seu artigo Singleton and Monostate, em 2002, como uma proposta “Clean Code” de um Singleton. Este padrão de projetos propõe guardar uma instância única de um objeto e prover acesso global à esta instância ─ assim como o Singleton, porém, com algumas pequenas diferenças: Seu construtor deve ser público; Seus métodos não podem ser estáticos; Deve possuir uma propriedade estática privada, para guardar a instância do objeto desejado. public class Monostate {     private static Object instanciaDoObjeto;     // …demais propriedades     public Monostate() {}     public void setInstanciaDoObjeto(Object objeto) {         Monostate.instanciaDoObjeto = objeto;     }     public Object getInstanciaDoObjeto() {         return Monostate.instanciaDoObjeto;     }     // …demais métodos } Observando a estrutura de sua implementação, podemos notar que o Monostate, além de precisar ser instanciado onde quer que seja utilizado,  não controla o ciclo de vida da instância de seu objeto. Portanto, este controle também deve ser implementado pelo código que o consome. Isso traz para quem o utiliza três vantagens principais: Não quebra o Single Responsibility Principle do SOLID. Por consequência, temos à disposição seus benefícios; Por precisar ser instanciado para consumir a instância única do objeto, que é privado em relação ao Monostate, pode ser considerado uma solução mais transparente que o Singleton; Mesmo que haja concorrência de chamada do getter do Monostate, não existe nenhum controle interno que crie uma instância para você. Assim, é mais difícil de ocorrer o problema de serem criadas instâncias de forma não-intencional do seu objeto ─ e se ocorrer, provavelmente é relacionado à invocação do setter no código que o consome. Em questão de comparação, não existe muito no que se debruçar aqui. Costuma-se dizer que o Monostate e o Singleton são dois lados de uma mesma moeda, com o detalhe do tipo de categoria que cada um cai. O Monostate é um padrão de projetos do tipo comportamental, enquanto o Singleton é criacional. Ainda assim, vale o conhecimento para julgar qual o melhor padrão de projetos para cada situação. Ficou curioso? Quer saber mais sobre o Monostate? Leia o artigo completo do Uncle Bob sobre este assunto em: SINGLETON and MONOSTATE. Singleton versus Injeção de Dependência Enquanto uma das maiores premissas do Singleton é a sua conveniência, transparência é a chave da injeção de dependência. A lógica por trás deste tópico é bem simples de se entender: se uma classe ou método requer um determinado objeto para efetuar as suas operações, este objeto deve ser injetado como uma dependência. Reescrevendo o método usuarioPodeCadastrarNovosClientes(), do serviço descrito mais acima, podemos, ao invés de recuperar o usuário de um Singleton, tornar explícito a dependência que o método precisa de um Usuario. Isso também é conhecido como “passar objeto por referência”. public class Servico {     public boolean usuarioPodeCadastrarNovosClientes(Usuario usuario) {         return usuarioLogado != null && usuarioEhAdmin(usuario));     }     private boolean usuarioEhAdmin(Usuario usuario) {         return “ADMIN“.equals(usuario.getPermissao());     } } O serviço não precisa se preocupar de onde vem o usuário. Esta é uma preocupação que o cliente ─ aquele que consome este serviço ─ deve ter. Com esta pequena alteração, o serviço passou a ser: Transparente: está claro quais as suas dependências e como ele as manipula; Fácil de testar: sem o uso do Singleton, o nosso problema de execuções de testes em paralelo deixou de existir. Por último, a injeção de dependência também serve para causar reflexões em quem está escrevendo o código, trazendo insights bem interessantes.  Um exemplo seria refletir se o nosso método usuarioPodeCadastrarNovosClientes realmente precisa do objeto Usuario, ou se apenas a String de permissão já basta;  Aliás, será que realmente é necessário um método no nosso serviço para fazer essa verificação?  E se o próprio objeto Usuario possuir um método interno para validar esta regra?  Questões como essas são 100% pertinentes, e podem naturalmente ocorrer a partir do momento em que estiverem explícitas as dependências daquele trecho de código. Opinião do autor Como comentado no início deste artigo, todo padrão de projetos possui custos e benefícios de implementação (trade-offs). É importante conhecer o “lado bom” e o “lado ruim”, antes de julgarmos ou defendermos uma ideia. Eu escrevi este artigo, em grande parte, pois cada lugar no qual eu pesquisava, encontrava uma informação nova com pouquíssimas explicações que justificassem o que estava sendo dito.  Este artigo, portanto, serve como material de estudo para consolidar todas essas informações em um local centralizado. A maioria dos autores se posiciona de um lado. No entanto, em algumas ocasiões, não tem como: existem situações em que você precisa de uma única instância de um objeto, e essa instância precisa ser de escopo global.  Mas, mais importante do que precisar usar algum recurso, é entender direito como esse mesmo recurso funciona. Agradecimentos especiais Fazer este texto foi especial para mim, e muita gente me ajudou para chegar no resultado.  Assim, gostaria de deixar alguns agradecimentos. Gostaria de agradecer, primeiramente, à minha esposa, por ter gastado seu tempo lendo e relendo as versões deste texto. Mesmo sem ser da área, ela foi uma peça muito importante e um dos meus maiores motivadores para continuar escrevendo.  Queria agradecer também aos meus colegas Fernando Costa Leite e Felipe Pereira Maragno, por terem me dado alguns valiosos feedbacks durante o desenvolvimento do artigo; e ao Fabio Domingues e Francisco Hillesheim por apoiarem a escrita das vantagens que o Singleton traz para o desenvolvedor, bem como agregarem na ideia de solução thread-safe.  Por último, mas não menos importante, também queria agradecer ao Cleidir Cristiano Back, Vinicius Roggia Gomes, e Renato Mendes Viegas por terem revisado o resultado final: vocês foram peças fundamentais para o refinamento do artigo. Gostou de conhecer um pouco mais sobre a polêmica do Singleton? Me conte aqui nos comentários a sua opinião!  Confira mais conteúdos como esse em nosso Blog. Quer ser nosso próximo Tech Writer? Confira nossas vagas na página Carreira!

Plataforma SaaS: o que você ainda não sabe sobre ela!
Tech Writers Junho 20, 2022

Plataforma SaaS: o que você ainda não sabe sobre ela!

Você certamente concorda que o cloud computing está se tornando vital para as empresas. Neste contexto, uma enorme parcela de sua popularização no mercado se deve às plataformas SaaS, conhecidas como Software as a Service ou Software como Serviço. Para você ter ideia, 80% das organizações planejam ter todos os seus sistemas em SaaS até 2025, sendo que 38% já rodam suas aplicações quase que totalmente no modelo. Os dados são do DevSquad. Considerando que este segmento deve atingir US$143,7 bilhões ainda em 2022, segundo a Gartner, é fundamental que todo profissional de tecnologia fique atento às suas particularidades, desafios e tendências. É isso que abordaremos neste artigo. Acompanhe! O que você ainda precisa saber sobre a plataforma SaaS? Graças à rápida e crescente expansão do cloud computing, atualmente é mais prático, barato e rápido para os desenvolvedores SaaS implementarem suas aplicações do que seria no desenvolvimento tradicional de software, feito localmente. Como você já sabe, todas as tecnologias em nuvem são executadas via sistemas subjacentes. Entretanto, as plataformas SaaS dizem respeito especificamente aos aplicativos de negócios que operam via cloud. Atualmente, praticamente todas as ferramentas essenciais para as empresas são disponibilizadas por provedores de softwares SaaS. Tanto que essas aplicações podem ser encontradas em diferentes formatos, escopos e direcionamentos. Apesar dessa variabilidade, os sistemas SaaS quase sempre podem ser englobados em três categorias específicas. Descubra como cada uma delas se delimita e quais são os seus propósitos de mercado: SaaS colaborativo No caso das plataformas SaaS colaborativas, a finalidade é favorecer a atuação conjunta de times de profissionais, seja no mesmo ambiente corporativo ou de maneira remota. Portanto, sempre que você se deparar com um sistema em nuvem voltado à troca de mensagens, compartilhamento de arquivos e documentos, videoconferências, integrações de processos, entre outros semelhantes, isso é considerado um SaaS de colaboração. Mais uma vez, os exemplos são amplos. Eles incluem aplicativos de vídeo-chamadas como o Zoom, soluções web de gerenciamento de projetos como o Trello e assim por diante. Technical SaaS Por fim, os sistemas SaaS da categoria Technical são aqueles direcionados à realização, ao aprimoramento e à gestão de processos técnicos. Os exemplos são de softwares web que demandam aptidões técnicas para serem utilizados. Isso envolve aplicações como o Google Analytics, usado por profissionais de marketing, pacote Adobe online, usado por designers, Sienge, para gestores do segmento da construção, etc. Características principais do SaaS A maior vantagem das plataformas SaaS certamente é a possibilidade de rodar tudo via web. Ou seja, os usuários não precisam instalar os sistemas localmente e executá-los em seus dispositivos, o que barateia os investimentos iniciais com hardware. Somado a isso, os provedores são responsáveis por todas as demandas de desempenho, disponibilidade e segurança das aplicações. Mais que praticidade, isso também gera economia com questões como licenciamento e suporte. Muito além desses benefícios, os projetos e produtos SaaS têm mais características interessantes, que justificam sua atual popularidade. São elas: Arquitetura Multi Tenant A distribuição das plataformas SaaS se baseia em uma arquitetura Multi Tenant direcionada a todos os clientes. Isso significa que os usuários têm o mesmo código fonte e recebem automaticamente novas funcionalidades sempre que elas são adicionadas. Fácil personalização Mesmo com a arquitetura Multi Tenant, a grande maioria dos sistemas SaaS são personalizáveis. A intenção é atender melhor às demandas de cada usuário, sendo que nenhuma personalização afeta a infraestrutura. Fácil acesso Muito além do acesso a qualquer hora, de qualquer lugar e por meio de qualquer dispositivo conectado à nuvem, o SaaS ainda oferece o mesmo grau de funcionalidade dos softwares tradicionais, mas com custos muito menores. SaaS aproveita a Web do consumidor A facilidade que mencionamos acima também passa pelo fato de que as organizações podem acessar as aplicações e começar a utilizá-las imediatamente. Isso porque o acesso é direto pela web do cliente, sendo que o sistema já está prontamente instalado e configurado. Desafios do SaaS Indo além das questões de código, dos benefícios e das possibilidades das plataformas SaaS, é importante ressaltar que elas também possuem certos desafios. Como em qualquer tecnologia, há pontos relevantes de cautela para os profissionais, o que inclui: Questões além do controle do cliente Mesmo que os aplicativos possam ser personalizados, isso só é possível até certo ponto. As funcionalidades e recursos são limitados à arquitetura do sistema. Às vezes, essas ferramentas podem não atender completamente às necessidades específicas de cada empresa. Aumento do lifetime value Os clientes não compram o Software as a Service SaaS uma única vez. As assinaturas precisam ser renovadas para que os recursos continuem disponíveis. Portanto, os fornecedores devem manter os usuários engajados e interessados no valor das funcionalidades. Redução da taxa de churn O aumento do tempo médio que os usuários investem no produto está diretamente relacionado à diminuição da taxa de churn. Inovações surgem a todo momento na internet e, caso você não as acompanhe, o cliente pode não continuar comprando seu SaaS todos os meses ou anos. Aumento do ticket médio A escalabilidade é inerente às plataformas SaaS. Ou seja, os consumidores podem acessar mais ou menos funções de acordo com sua demanda. Nesse sentido, mais que aumentar o LFV e reduzir o churn, é preciso elevar o ticket médio com mais extensões úteis e atraentes. Tendências do mercado SaaS para o futuro Agora que você já conhece todas as características e oportunidades oferecidas pelas plataformas SaaS, é hora de voltar seus olhares para o futuro (que já está bem próximo). Afinal, este é um mercado que evolui rapidamente e que está repleto de novas soluções. Para se destacar perante os consumidores e manter relevância diante de tantas inovações, é fundamental ficar atento às tendências do segmento. Entre aquelas que já estão ditando os novos rumos da área, destacam-se: Modelos de pagamentos baseados em transações Como você pôde ver anteriormente, as plataformas SaaS geralmente são pagas em modelos de assinatura. Ou seja, o desafio é manter os pagamentos mensais e anuais dos clientes pelo maior tempo possível. Como o surgimento de novos sistemas e recursos é crescente, cada vez mais empresas da área procuram destacar-se ao oferecer flexibilidade para os consumidores. Isso significa que os formatos de assinatura estão sendo trocados pelo pay-per-use. Dessa maneira, os usuários devem pagar de acordo com sua demanda. A contrapartida é pelo tempo específico de uso e pelo nível de recursos utilizados. Inclusive, condicionar pagamentos maiores a ferramentas mais robustas aumenta as possibilidades de melhores precificações. Whatsapp e SaaS Ao contrário dos Estados Unidos e dos países da Europa, o Brasil tem entre seus principais meios de comunicação o WhatsApp. De acordo com uma pesquisa divulgada pelo Valor Investe, 80% da população usa o aplicativo para se comunicar com as marcas. Atentas a essa realidade específica do mercado nacional, cada vez mais organizações reconhecem a necessidade de se adaptar a essa preferência dos brasileiros, adequando os seus canais e abordagens. Nesse sentido, as plataformas SaaS já têm um volume crescente de funcionalidades integradas ao aplicativo. Isso inclui ferramentas de atendimento, vendas, prospecção, help desk, entre outras semelhantes. Se você chegou até aqui, provavelmente é porque sabe que todos esses conhecimentos sobre as plataformas SaaS irão somar à sua carreira. A Softplan valoriza profissionais com esse perfil e atua para que eles atinjam sua melhor versão. Quer ser o próximo Tech Writer do nosso time e nos ajudar a transformar a vida das pessoas? Clique aqui e confira nossas vagas!

Metodologias, métodos & processos de design!
Tech Writers Junho 06, 2022

Metodologias, métodos & processos de design!

Diariamente, nos deparamos com alguma atividade composta por etapas. Muitas vezes, não as enxergamos dessa forma por fazerem parte de nossa rotina. Mas pare para pensar por um momento no ato de lavar louças. Isso mesmo, lavar louças! Eu, particularmente, possuo uma ordem muito específica para escolher os itens que lavarei, ensaboarei, enxaguarei e colocarei em um secador para escorrer a água. A minha maneira de executar essa tarefa doméstica é muito diferente, por exemplo, de quem possui um lava louças.  Já conheci uma pessoa que fazia uma pré-lavagem dos pratos antes mesmo de colocá-los na máquina. Observe como esse é um exemplo simples, de uma rotina banal, onde encontramos processos diferentes para executar uma mesma ação.  Com essa simples metáfora, quero te fazer refletir sobre como podemos alcançar um objetivo por meio de diferentes processos. Nesse conteúdo, vamos falar sobre processos de design, suas etapas e particularidades.  Lavar a louça, uma rotina banal onde encontramos processos diferentes para executar uma mesma atividade. Conceito de processos de design Processos, a meu ver, são estratégias para esvaziar a mente e se organizar. São passos que seguimos para programar etapas e ferramentas, a fim de deixar o ambiente ao nosso redor preparado para resolver um problema ou executar uma atividade. Organizar os nossos passos gera clareza sobre o que precisamos fazer.  Processos de Design claros levam a caminhos simples e tranquilos na resolução de questões. Já métodos e técnicas adequados guiam o designer na descoberta da melhor maneira de resolver problemas e, no nosso caso, no desenvolvimento e melhoria de um produto. O processo deve ser um guia para enxergar o caminho onde o design pode seguir. Métodos de design Métodos de design são garantias da efetividade do processo e da entrega da qualidade do design. Ignorando a separação das áreas de atuação do design, seja ele industrial, de produtos ou gráfico, ao olharmos para o processo sempre vamos nos deparar com o “básico que funciona”.  Assim, “podemos fazer uma divisão de etapas formadas por informações, observações e reflexões que decorrem de uma investigação” (GERHARDT e SILVEIRA, 2009, p. 76). Dessa forma, podemos transformar esse conhecimento em um “relato escrito daquilo que o investigador ouve, vê, experiencia e pensa no decurso de um estudo qualitativo” (BOGDAN e BIKLEN, 1991, p. 150). Etapas dos métodos  O primeiro passo vem alinhado com um entendimento muito similar aos conceitos das técnicas de briefings comuns na área do marketing. É quando realizamos um alinhamento e olhamos para técnicas de levantamento de dados, o popular Discovery no mundo dos produtos. Caminhamos para a etapa das descobertas onde buscamos, através de pesquisas, questões importantes em relação ao produto. Dessa maneira, colocamos na balança dados relevantes que entram em contrapeso com todas as hipóteses construídas de forma interna. Logo depois, vem a etapa de análise e ideação. Essa fase é uma das mais desafiadoras, porque precisamos racionalizar tudo aquilo que foi descoberto nas informações levantadas. A partir disso, para resolver o problema levantado, idealizamos os caminhos que seguiremos. A etapa de design ou de desenho das ideias, consiste no desenvolvimento visual que materializa as ideias, com o intuito de torná-las tangíveis e testáveis. O famoso protótipo. No teste, validamos a descoberta junto com as personas construídas ao redor do problema inicial. Aqui, observamos opiniões, comportamentos e compreensão da solução que construímos. Finalmente, chegamos ao acompanhamento de tudo aquilo que foi validado e lançado para enxergarmos o engajamento do que foi produzido. Essa etapa poderia ser muito bem observada como final. No entanto, ela alimenta uma geração de insights para os próximos ciclos da solução desenvolvida. Em resumo, o processo de design é: Entender; Pesquisar; Fazer o design; Analisar; Acompanhar.  No decorrer do seu percurso em design você vai se deparar com diversos modelos de processos que englobam essas mesmas etapas. O que importa, no final, é que essa jornada deve ser simples, direta e estruturada. Adapte-se a metodologia de design Um processo de design claro e completo pode orientar de maneira ordenada, otimizando e simplificando o resultado. O processo determina as etapas do design, enquanto esse requer métodos específicos e estratégias de apoio e orientação.  Os métodos determinam as medidas e o efeitos do design e devem ser adaptados e alterados de acordo com os procedimentos específicos. Dessa forma, os problemas são resolvidos de forma eficiente e criativa. Nesse ponto, é essencial lembrar de que o UX — User experience, ou seja, o estudo da experiência do usuário, não é um processo direto e pré-determinado. Ele necessita de constantes adaptações.  No processo de encontrar o produto e design ideal, é necessário avançar e retroceder até encontrar o ajuste adequado. Por isso, devemos nos adaptar em relação aos problemas que estamos tentando resolver em conjunto com outras áreas e equipes. Padrões dos processos de design Os padrões que compõem métodos do design são uma parte importante da metodologia. É um conceito muito mais amplo que um processo.  Metodologias compreendem um conjunto de princípios e de diretrizes das melhores práticas da aplicação de métodos e processos relacionados a uma disciplina. Metodologia de design é área de conhecimento estudada por designers para pesquisar e ensaiar o caminho pelo qual será possível obter um resultado em um projeto;  Por meio dela, será possível prever, de antemão, um conjunto de procedimentos, regras e técnicas para chegar a uma meta prevista. Um método é uma maneira isolada de fazer as coisas. Ele está relacionado às etapas do projeto, enquanto a metodologia é um conjunto de métodos. Metodologia é toda a execução do projeto. É uma ciência que se ocupa do estudo de métodos, técnicas ou ferramentas, suas aplicações e definições.  Assim, eles são compostas por instrumentos de ordenação, organização e suporte lógico ao desenvolvimento, e na organização de resolução de problemas teóricos e práticos. A metodologia abraça o processo, servindo o designer com métodos e ferramentas. O diálogo entre metodologia e design proporcionou a este último se tornar ensinável, aprendível e comunicável. Isso porque teoria e metodologia do design se desenvolvem com base em hipóteses e suposições que têm como intuito aperfeiçoar métodos, regras e critérios. Conclusão Conhecer a teoria base pode nos dar o poder de aplicá-la e não ser apenas um integrante passivo nos projetos.  Todo designer precisa ter noção da profundidade desse conhecimento e da aplicabilidade disso no dia a dia.  A base nos faz compreender nossas ações diárias para que, mesmo na falha, o suporte da metodologia nos dê uma forma de recuperação através de algum processo. É nossa responsabilidade como designers ir além do operacional. Assim, nossa ação dentro das empresas ocorre de forma ativa e não apenas de forma replicadora, sem entender os porquês existentes em nossos processos. Bonsiepe et al. (1984, p. 34) destaca que a metodologia projetual não deve ser confundida com um livro de receitas de bolo, pois receitas de bolo levam, com certeza, a um determinado resultado, e técnicas projetuais só têm certa “probabilidade de sucesso”. Saiba usar cada peça de equipamento para entregar trabalhos de alto nível valorizando o que você faz, mesmo que seja lavar a louça. Gostou de saber um pouco mais sobre metodologias, métodos e processos em design? Confira mais conteúdos como esse em nosso Blog! Quer ser nosso próximo Tech Writer? Confira nossas vagas na página Carreira! Até a próxima!

Aplicações distribuídas e acoplamento em engenharia de software valem a pena?
Tech Writers Maio 16, 2022

Aplicações distribuídas e acoplamento em engenharia de software valem a pena?

Nos dias de hoje, é muito comum vermos aplicações monolíticas sendo migradas, ou até mesmo nascendo, em uma arquitetura distribuída. Seja ela composta por serviços de domínio com granularidade grossa ou mesmo por refinados microsserviços.  Não vou entrar, neste momento, nos detalhes e riscos envolvidos em uma eventual – e provável – decomposição prematura. Porém, é inegável que aplicações distribuídas são uma tendência absoluta em termos de arquitetura de soluções modernas.  Parte desse movimento foi incentivado pelas grandes empresas de tecnologia. Foi também propulsionado por ferramentas como: Conteinerização de aplicações; IaC (Infrastructure as Code);  Cloud Computing. Essas, por sua vez, acabam resolvendo problemas que há pouco tempo eram obstáculos intransponíveis para qualquer proposta de natureza distribuída. Aplicações distribuídas valem a pena? Para encontrar essa resposta, precisamos começar com um questionamento: qual a razão deste estilo arquitetural ser tão atraente aos olhos das empresas?  É perfeitamente compreensível que desenvolvedores e arquitetos se sintam intrigados pelos desafios técnicos implícitos neste tipo de abordagem. Mas quais justificativas tornam possível a aplicação dessa complexidade adicional em uma solução de software do ponto de vista do negócio? Antes de discutirmos essas vantagens, vale mencionar que uma arquitetura distribuída deve ser aplicada apenas em sistemas cuja complexidade é muito alta. Ou seja, aqueles que são difíceis de evoluir e manter em uma arquitetura monolítica.  Assim, ela não deve ser aplicada apenas pelos desafios técnicos implícitos que costumam motivar a equipe técnica. Não é o foco deste artigo, mas deixo uma boa referência sobre o tema aqui. Dito isso, vamos supor que uma análise considerável dos trade-offs tenha sido feita e que haja uma real necessidade e maturidade que justifique este tipo de abordagem. Algumas das principais vantagens que você poderá obter são:  Manutenibilidade da aplicação;  Código mais testável;  Escalabilidade e elasticidade;  Maior tolerância a falhas;  Disponibilidade dos serviços; Tudo isso permite que nossa solução responda rapidamente às mudanças do negócio. Assim, é possível viabilizar uma melhora considerável no time-to-market do produto, proporcionando grandes vantagens competitivas. O grande vilão das aplicações distribuídas! Para preservar estas vantagens é fundamental que o time esteja ciente sobre a importância de se proteger uma das características mais fundamentais em uma arquitetura distribuída: a independência entre os serviços.  Quando dois ou mais serviços do seu ecossistema estão acoplados e têm sua independência comprometida, as vantagens proporcionadas por este estilo de arquitetura começam a ser sobrepujadas pelas complexidades ditas essenciais. Isso afeta diretamente a capacidade da equipe em responder rapidamente às mudanças do negócio.  Dessa maneira, a vantagem competitiva acaba sendo perdida.  Tipos de acoplamento em engenharia de software Vou explicar de maneira simples dois dos principais tipos de acoplamento em engenharia de software: acoplamento estático e acoplamento dinâmico. Acompanhe: Acoplamento estático É aquele que “amarra” dois componentes de software, fazendo com que as mudanças em um elemento afetem todos os seus dependentes.  Quanto maior o acoplamento eferente do seu serviço, maior será a sua instabilidade e a chance dele ser impactado por mudanças externas.  Quando pensamos nesse tipo de definição, o exemplo mais óbvio são pacotes ou bibliotecas das quais nossa solução depende. Porém, todos os elementos necessários para garantir que o serviço seja inicializado também se enquadram nessa categoria de acoplamento, inclusive banco de dados e message brokers.  Esse tipo de acoplamento em arquitetura de software é um dos principais responsáveis por tornar uma abordagem orientada a serviços de domínio (onde é comum optar em utilizar o banco de dados como ponto de integração da aplicação) menos flexível que uma arquitetura de microsserviços com bases independentes. Uma consequência desse acoplamento, seria a quase inevitável possibilidade de uma alteração em nível de banco, centralizado,  impactar mais de um serviço do ecossistema. Acoplamento dinâmico É o acoplamento em engenharia de software que ocorre durante a comunicação entre dois serviços.  Um exemplo prático: supondo que tenhamos dois serviços que se comuniquem de forma síncrona. Dessa forma, eles estarão dinamicamente acoplados durante a execução dessa comunicação.   Se o serviço que está sendo consumido falhar ou mesmo enfrentar algum problema de performance, esse acoplamento momentâneo afetará, também, as características do consumidor.  Escalar um serviço não garante eficiência se ele estiver dinamicamente acoplado com serviços ineficientes.  Neste cenário, talvez fizesse mais sentido um acoplamento estático com o message broker e uma comunicação assíncrona para evitar o acoplamento dinâmico entre as aplicações. Mas, como tudo em engenharia de software, a resposta sempre depende do contexto e das reais necessidades do negócio. Conclusão Acoplamento estático e dinâmico são inevitáveis em uma arquitetura distribuída. Ao invés de combatê-los, é necessário gerenciá-los.  O time deve ter ciência da importância da independência entre os serviços e dos impactos que cada tipo de acoplamento em engenharia de software pode causar nas características arquiteturais da solução.  Considerar os trade-offs e documentar os porquês constituem uma parte fundamental do trabalho necessário para garantir uma arquitetura de software evolutiva e flexível. Dessa forma, são asseguradas as vantagens competitivas que justificam este estilo arquitetural tão  interessante. Gostou de saber um pouco mais sobre aplicações distribuídas e acoplamento em engenharia de software? Confira mais conteúdos como esse em nosso Blog! Quer ser nosso próximo Tech Writer? Confira nossas vagas na página Carreira! Até a próxima!