A tarefa de construir plataformas de TI para a acumulação e análise de dados, mais cedo ou mais tarde, surge para qualquer empresa cujo negócio é baseado em um modelo de entrega de serviço carregado intelectualmente ou na criação de produtos tecnicamente complexos. Construir plataformas analíticas é uma tarefa difícil e demorada. No entanto, qualquer tarefa pode ser simplificada. Neste artigo, quero compartilhar minha experiência de uso de ferramentas de baixo código para ajudá-lo a criar soluções analíticas. Essa experiência foi adquirida durante a implantação de diversos projetos na direção de Big Data Solutions da empresa Neoflex. Desde 2005, o departamento de Big Data Solutions da Neoflex vem lidando com a questão da construção de data warehouses e lagos, resolvendo problemas de otimização da velocidade de processamento da informação e trabalhando em uma metodologia de gestão da qualidade dos dados.

Ninguém será capaz de evitar o acúmulo deliberado de dados fracamente e / ou altamente estruturados. Talvez até se estivermos falando de uma pequena empresa. Na verdade, ao expandir um negócio, um empreendedor promissor enfrentará os problemas de desenvolver um programa de fidelidade, deseja analisar a eficácia dos pontos de venda, pensar em publicidade direcionada e ficar intrigado com a demanda por produtos que o acompanham. Como uma primeira aproximação, o problema pode ser resolvido no joelho. Mas com o crescimento de uma empresa, chegar a uma plataforma analítica ainda é inevitável.
No entanto, em qual caso as tarefas de análise de dados podem se transformar em tarefas da classe "Rocket Science"? Talvez naquele momento quando se trata de realmente big data.
Para simplificar a tarefa da Rocket Science, você pode comer o elefante pedaço por pedaço.

Quanto mais discrição e autonomia seus aplicativos / serviços / microsserviços tiverem, mais fácil será para você, seus colegas e toda a empresa digerir um elefante.
Quase todos os nossos clientes aceitaram esse postulado, reconstruindo o cenário, com base nas práticas de engenharia das equipes de DevOps.
Mas mesmo com uma dieta "dividida, elefante", temos uma boa chance de "supersaturação" do cenário de TI. Nesse ponto, vale a pena parar, respirar fundo e olhar para a plataforma de engenharia de baixo código .
Muitos desenvolvedores ficam intimidados com a perspectiva de um impasse em suas carreiras ao se afastar da escrita direta de código para "arrastar" setas em interfaces de UI de sistemas de baixo código. Mas o surgimento das máquinas-ferramenta não levou ao desaparecimento dos engenheiros, mas elevou seu trabalho a um novo patamar!
Vamos descobrir o porquê.
A análise de dados no campo da logística, indústria de telecomunicações, no campo da pesquisa de mídia, setor financeiro, está sempre associada às seguintes questões:
- A velocidade da análise automatizada;
- A capacidade de conduzir experimentos sem afetar o fluxo principal de produção de dados;
- A confiabilidade dos dados preparados;
- Controle de mudanças e controle de versão;
- Providência de dados, linhagem de dados, CDC;
- Entrega rápida de novos recursos ao ambiente de produção;
- E o proverbial: custo de desenvolvimento e suporte.
Ou seja, os engenheiros têm um grande número de tarefas de alto nível, que podem ser executadas com eficiência suficiente apenas limpando suas mentes das tarefas de desenvolvimento de baixo nível.
A evolução e a digitalização dos negócios tornaram-se os pré-requisitos para a transição dos desenvolvedores para um novo nível. O valor do desenvolvedor também está mudando: há uma escassez significativa de desenvolvedores que possam mergulhar fundo nos conceitos de negócios que estão sendo automatizados.
Vamos fazer uma analogia com as linguagens de programação de baixo e alto nível. A transição das línguas de baixo nível para as de alto nível é uma transição da escrita de "diretrizes na linguagem de ferro" para "diretrizes na linguagem das pessoas". Ou seja, adicionando alguma camada de abstração. Nesse caso, a transição para plataformas de baixo código de linguagens de programação de alto nível é uma transição de “diretivas na linguagem das pessoas” para “diretivas na linguagem dos negócios”. Se há desenvolvedores que ficam tristes com esse fato, eles ficam tristes, talvez desde o momento em que o Java Script nasceu, que usa funções de classificação de array. E essas funções, é claro, têm a implementação do software sob o capô por outros meios da mesma programação de alto nível.
Portanto, o baixo código é apenas o surgimento de outra camada de abstração.
Experiência aplicada de uso de baixo código
O tópico de baixo código é bastante amplo, mas agora eu gostaria de falar sobre a aplicação aplicada de "conceitos de baixo código" usando o exemplo de um de nossos projetos.
A divisão Big Data Solutions da Neoflex é mais especializada no setor financeiro de negócios, criando storage e data lakes e automatizando diversos relatórios. Nesse nicho, o uso de baixo código há muito se tornou um padrão. Outras ferramentas de baixo código incluem ferramentas para organizar processos ETL: Informatica Power Center, IBM Datastage, Pentaho Data Integration. Ou Oracle Apex, que atua como um ambiente de rápido desenvolvimento de interfaces para acesso e edição de dados. No entanto, o uso de ferramentas de desenvolvimento de baixo código nem sempre está associado à construção de aplicativos altamente direcionados em uma pilha de tecnologia comercial com uma dependência pronunciada do fornecedor.
Usando plataformas de baixo código, você também pode organizar a orquestração de fluxos de dados, criar plataformas de ciência de dados ou, por exemplo, módulos de controle de qualidade de dados.
Um dos exemplos aplicados da experiência de uso de ferramentas de desenvolvimento de baixo código é a colaboração entre a Neoflex e a Mediascope, uma das líderes no mercado russo de pesquisa de mídia. Um dos objetivos de negócio desta empresa é a produção de dados, a partir dos quais anunciantes, sites da Internet, canais de televisão, estações de rádio, agências de publicidade e marcas decidem comprar publicidade e planear a sua comunicação de marketing.

A pesquisa de mídia é uma área de negócios intensiva em tecnologia. Reconhecer sequências de vídeo, coletar dados de dispositivos que analisam a visualização, medir a atividade em recursos da web - tudo isso implica que uma empresa tem uma grande equipe de TI e uma experiência colossal na construção de soluções analíticas. Mas o crescimento exponencial na quantidade de informações, o número e a variedade de suas fontes fazem com que a indústria de dados de TI progrida constantemente. A solução mais simples para dimensionar a plataforma analítica já em funcionamento Mediascope poderia ser um aumento na equipe de TI. Mas uma solução muito mais eficiente é acelerar o processo de desenvolvimento. Uma das etapas que levam nessa direção pode ser o uso de plataformas de baixo código.
No momento do início do projeto, a empresa já tinha uma solução de produto em funcionamento. No entanto, a implementação da solução em MSSQL não atendeu totalmente às expectativas de escalonamento da funcionalidade, mantendo um custo de revisão aceitável.
A tarefa diante de nós era verdadeiramente ambiciosa - Neoflex e Mediascope tiveram que criar uma solução industrial em menos de um ano, desde que o MVP fosse lançado dentro do primeiro trimestre da data de início.
A pilha de tecnologia Hadoop foi escolhida como a base para a construção de uma nova plataforma de dados baseada em computação de baixo código. HDFS se tornou o padrão para armazenamento de dados usando arquivos em parquet. Para acessar os dados da plataforma, foi utilizado o Hive, em que todas as vitrines disponíveis são apresentadas em tabelas externas. O carregamento de dados no armazenamento foi implementado usando Kafka e Apache NiFi.
A ferramenta lowe-code neste conceito foi usada para otimizar a tarefa mais trabalhosa na construção de uma plataforma analítica - a tarefa de calcular dados.

A ferramenta Datagram de baixo código foi escolhida como o principal mecanismo de mapeamento de dados. Neoflex Datagram é uma ferramenta para projetar transformações e fluxos de dados.
Ao usar esta ferramenta, você pode evitar escrever código Scala "manualmente". O código Scala é gerado automaticamente usando a abordagem Model Driven Architecture.
Uma vantagem óbvia dessa abordagem é a aceleração do processo de desenvolvimento. No entanto, além da velocidade, também existem as seguintes vantagens:
- Visualização do conteúdo e estrutura de fontes / destinos;
- Rastrear a origem de objetos de fluxo de dados para campos individuais (linhagem);
- Execução parcial de transformações com visualização de resultados intermediários;
- Visualizando o código-fonte e corrigindo-o antes da execução;
- Validação automática de transformações;
- Carregamento automático de dados 1 em 1.
O limite para inserir soluções de baixo código para gerar transformações é bastante baixo: o desenvolvedor precisa saber SQL e ter experiência com ferramentas ETL. Deve-se observar que os geradores de transformação orientados por código não são ferramentas ETL no sentido amplo da palavra. As ferramentas de baixo código podem não ter seu próprio ambiente de execução de código. Ou seja, o código gerado será executado no ambiente que estava no cluster antes mesmo da instalação da solução de baixo código. E esta é, talvez, outra vantagem no carma de baixo código. Pois, em paralelo com o comando de baixo código, pode funcionar um comando “clássico”, que implementa a funcionalidade, por exemplo, em código Scala puro. Colocar o trabalho de ambas as equipes na produção será simples e contínuo.
Talvez seja importante notar que, além do baixo código, também existem soluções sem código. E em sua essência são coisas diferentes. O baixo código permite que o desenvolvedor interfira com o código gerado em uma extensão maior. No caso do Datagram, é possível visualizar e editar o código Scala gerado, nenhum código pode não fornecer essa oportunidade. Essa diferença é muito significativa não só em termos de flexibilidade de solução, mas também em termos de conforto e motivação no trabalho dos engenheiros de dados.
Arquitetura da solução
Vamos tentar descobrir como exatamente uma ferramenta de baixo código ajuda a resolver o problema de otimizar a velocidade de desenvolvimento da funcionalidade de cálculo de dados. Primeiro, vamos dar uma olhada na arquitetura funcional do sistema. Nesse caso, um exemplo é o modelo de produção de dados para pesquisa de mídia.

As fontes de dados em nosso caso são muito heterogêneas e diversas:
- (-) — - , – , , . – . Data Lake , , , . , , ;
- ;
- web-, site-centric, user-centric . Data Lake research bar VPN.
- , - ;
- -.
A implementação no estado em que se encontra o carregamento dos sistemas de origem para o teste primário de dados brutos pode ser organizada de várias maneiras. Se o código baixo for usado para esses fins, é possível gerar scripts de carregamento automaticamente com base em metadados. Nesse caso, não há necessidade de descer ao nível de desenvolvimento de mapeamentos de origem para destino. Para implementar o carregamento automático, precisamos estabelecer uma conexão com a fonte e, em seguida, definir na interface de carregamento uma lista de entidades a serem carregadas. A criação da estrutura de diretórios no HDFS será automática e corresponderá à estrutura de armazenamento de dados no sistema de origem.
No entanto, no contexto deste projeto, decidimos não aproveitar esta oportunidade da plataforma de baixo código devido ao facto de a Mediascope já ter iniciado de forma independente a produção de um serviço semelhante no link Nifi + Kafka.
Deve-se notar desde já que essas ferramentas não são intercambiáveis, mas sim complementares entre si. Nifi e Kafka são capazes de trabalhar em pacotes diretos (Nifi -> Kafka) e reversos (Kafka -> Nifi). Para a plataforma de pesquisa de mídia, foi utilizado o primeiro link.

Em nosso caso, precisei processar vários tipos de dados dos sistemas de origem e enviá-los ao corretor Kafka. Ao mesmo tempo, o direcionamento de mensagens para um tópico específico do Kafka foi realizado usando os processadores PublishKafka Nifi. A orquestração e manutenção desses pipelines é feita em uma interface visual. A ferramenta Nifi e o uso do pacote Nifi + Kafka também podem ser chamados de uma abordagem de baixo código para o desenvolvimento, que tem um limite baixo para a entrada em tecnologias de Big Data e acelera o processo de desenvolvimento de aplicativos.
A próxima etapa na implementação do projeto foi a redução ao formato de uma única camada semântica de dados detalhados. Se uma entidade possui atributos históricos, o cálculo é realizado no contexto da partição em questão. Se a entidade não for histórica, é opcionalmente possível recalcular todo o conteúdo do objeto ou recusar-se a recalcular esse objeto (devido à ausência de alterações). Nesse estágio, as chaves são geradas para todas as entidades. As chaves são salvas nos diretórios Hbase correspondentes aos objetos mestres, contendo a correspondência entre as chaves da plataforma analítica e as chaves dos sistemas fonte. A consolidação das entidades atômicas é acompanhada pelo enriquecimento com os resultados do cálculo preliminar dos dados analíticos. A estrutura para calcular os dados era o Spark.A funcionalidade descrita de conversão de dados em uma semântica única também foi implementada com base nos mapeamentos da ferramenta de baixo código Datagram.
A arquitetura de destino precisava fornecer acesso a dados SQL para usuários de negócios. O Hive foi usado para esta opção. Os objetos são registrados no Hive automaticamente quando a opção “Registrar Hive Table” é habilitada no instrumento de baixo código.

Controle de fluxo de pagamento
O Datagram possui uma interface para a construção de designs de fluxo de trabalho. Os mapeamentos podem ser iniciados usando o planejador Oozie. Na interface do desenvolvedor de streams, é possível criar esquemas de paralelos, sequenciais ou dependendo das condições especificadas para a execução das transformações de dados. Há suporte para scripts de shell e programas java. Também é possível usar o servidor Apache Livy. Apache Livy é usado para executar aplicativos diretamente do ambiente de desenvolvimento.
Se a empresa já tiver seu próprio orquestrador de processo, é possível usar a API REST para incorporar mapeamentos em um fluxo existente. Por exemplo, tivemos uma experiência bastante bem-sucedida de incorporação de mapeamentos Scala em orquestradores escritos em PLSQL e Kotlin. A API REST de uma ferramenta de baixo código implica a presença de operações como gerar um ano executável com base no projeto de mapeamento, chamar um mapeamento, chamar uma sequência de mapeamentos e, claro, passar parâmetros para a URL para iniciar os mapeamentos.
Junto com o Oozie, é possível organizar um fluxo de cálculo usando o Airflow. Talvez eu não me detenha na comparação de Oozie e Airflow por muito tempo, mas direi simplesmente que, no contexto de trabalho em um projeto de pesquisa de mídia, a escolha recaiu sobre o Airflow. Os principais argumentos desta vez foram uma comunidade mais ativa no desenvolvimento do produto e uma interface + API mais desenvolvida.
O Airflow também é bom porque usa o amado Python para descrever os processos de cálculo. Em geral, não existem tantas plataformas de gerenciamento de fluxo de trabalho de código aberto. Iniciar e monitorar a execução de processos (incluindo aqueles com um gráfico de Gantt) apenas adiciona pontos ao carma do Airflow.
O formato do arquivo de configuração para iniciar mapeamentos de solução de baixo código é spark-submit. Isso aconteceu por dois motivos. Primeiro, o spark-submit permite que você execute o arquivo jar diretamente do console. Em segundo lugar, pode conter todas as informações necessárias para configurar o fluxo de trabalho (o que torna mais fácil escrever scripts que formam o Dag).
O elemento mais comum do fluxo de trabalho do Airflow em nosso caso é o SparkSubmitOperator.
SparkSubmitOperator permite que você execute jar`niks - mapeamentos de Datagramas compactados com parâmetros de entrada pré-formados para eles.
Deve ser mencionado que cada tarefa do Airflow é executada em um thread separado e não sabe nada sobre as outras tarefas. Neste contexto, a interação entre as tarefas é realizada usando operadores de controle, como DummyOperator ou BranchPythonOperator.
No total, o uso da solução de baixo código Datagram em conjunto com a universalização dos arquivos de configuração (formando Dag) levou a uma significativa aceleração e simplificação do processo de desenvolvimento de fluxos de download de dados.
Cálculo de demonstração
Talvez o estágio de carregamento mais inteligente na produção de dados analíticos seja a etapa de construção da vitrine. No âmbito de um dos fluxos de dados da empresa de investigação, nesta fase, ocorre a conversão para uma emissão de referência, tendo em conta a correcção dos fusos horários com referência à grelha de difusão. Também é possível ajustar para a rede de radiodifusão local (notícias e publicidade local). Entre outras coisas, esta etapa divide os intervalos de visualização contínua de produtos de mídia com base na análise dos intervalos de visualização. Imediatamente, os valores de visualização são "ponderados" com base nas informações sobre sua significância (cálculo do fator de correção).

A validação de dados é uma etapa separada na preparação de data marts. O algoritmo de validação usa vários modelos de ciências matemáticas. No entanto, o uso de uma plataforma de baixo código permite que um algoritmo complexo seja dividido em vários mapeamentos separados e visualmente legíveis. Cada um dos mapeamentos executa uma tarefa restrita. Como resultado, a depuração intermediária, registro e visualização dos estágios de preparação de dados são possíveis.
Decidiu-se discretizar o algoritmo de validação nas seguintes subestágios:
- Traçando regressões de dependências de assistir a uma rede de televisão em uma região com assistir a todas as redes da região por 60 dias.
- Cálculo de resíduos estudentizados (desvios dos valores reais daqueles previstos pelo modelo de regressão) para todos os pontos de regressão e para o dia calculado.
- Uma amostra de pares de região-rede anômalos, em que o restante estudentizado do dia calculado excede a norma (especificada pela configuração de operação).
- Recálculo do restante estudentizado corrigido para pares região-rede anormais para cada respondente que visualizou a rede na região com a determinação da contribuição deste respondente (o valor da mudança no restante estudentizado) ao excluir este respondente da amostra
- Busca de candidatos, cuja exclusão normalize o saldo estudentizado do dia da liquidação.
O exemplo acima é uma confirmação da hipótese de que um engenheiro de dados deveria ter muito na cabeça de qualquer maneira ... E se este for realmente um "engenheiro", não um "codificador", então o medo da degradação profissional ao usar ferramentas de baixo código ele deve finalmente recuar.
O que mais o código baixo pode fazer?
O escopo de uma ferramenta de baixo código para lote e streaming de dados sem escrever manualmente o código Scala não termina aí.
O uso de baixo código no desenvolvimento de datalakes já se tornou um padrão para nós. Talvez possamos dizer que as soluções na pilha do Hadoop seguem o caminho de desenvolvimento do DWH clássico baseado em RDBMS. Ferramentas de baixo código na pilha do Hadoop podem resolver tanto as tarefas de processamento de dados quanto as tarefas de construção de interfaces finais de BI. Além disso, deve-se destacar que BI pode significar não só a representação de dados, mas também sua edição pelas forças de usuários de negócios. Muitas vezes usamos essa funcionalidade ao construir plataformas analíticas para o setor financeiro.

Entre outras coisas, usando low-code e, em particular, Datagram, é possível resolver o problema de rastrear a origem de objetos de fluxo de dados com atomicidade para campos individuais (linhagem). Para fazer isso, a ferramenta de baixo código implementa interface com Apache Atlas e Cloudera Navigator. Na verdade, o desenvolvedor precisa registrar um conjunto de objetos nos dicionários Atlas e consultar os objetos registrados ao construir mapeamentos. O mecanismo de rastreamento da origem dos dados ou análise das dependências dos objetos economiza muito tempo caso seja necessário fazer melhorias nos algoritmos de cálculo. Por exemplo, ao construir demonstrações financeiras, esse recurso permite que você sobreviva com mais conforto ao período de mudanças legislativas. Afinal, quanto melhor entendermos a dependência entre as formas no contexto dos objetos da camada detalhada,menos encontraremos defeitos "repentinos" e reduziremos o número de retrabalhos.

Qualidade de dados e baixo código
Outra tarefa implementada pela ferramenta de baixo código no projeto Mediascope é a tarefa da classe Data Quality. Uma característica da implementação do pipeline de verificação de dados para o projeto da empresa de pesquisa foi a falta de impacto no desempenho e na velocidade do fluxo de dados principal. O familiar Apache Airflow foi usado para permitir a orquestração da validação de dados por threads independentes. Conforme cada etapa da produção de dados estava pronta, uma parte separada do pipeline de DQ foi lançada em paralelo.
É uma boa prática monitorar a qualidade dos dados desde o início na plataforma analítica. Tendo informações sobre os metadados, podemos, a partir do momento em que a informação entra na camada primária, verificar se as condições básicas são atendidas - não nulo, restrições, chaves estrangeiras. Esta funcionalidade é implementada com base em mapeamentos gerados automaticamente da família de qualidade de dados no Datagram. A geração de código, neste caso, também é baseada nos metadados do modelo. No projeto Mediascope, a interface foi realizada com os metadados do produto Enterprise Architect.
Ao emparelhar a ferramenta de baixo código e o Enterprise Architect, as seguintes verificações foram geradas automaticamente:
- Verificar a presença de valores "nulos" em campos com o modificador "não nulo";
- Verificar a presença de duplicatas da chave primária;
- Validação de chave estrangeira de entidade;
- Verificar a exclusividade de uma string em relação a um conjunto de campos.
Para verificações de validade e disponibilidade de dados mais sofisticadas, foi criado um mapeamento de expressão Scala que aceita um código de verificação Spark SQL externo preparado por analistas no Zeppelin.

Claro, é necessário chegar gradualmente à geração automática de cheques. No âmbito do projeto descrito, isto foi precedido pelas seguintes etapas:
- DQ implementado em notebooks Zeppelin;
- DQ embutido em mapeamento;
- DQ na forma de mapeamentos massivos separados contendo todo um conjunto de verificações para uma entidade particular;
- Mapeamentos DQ parametrizados universais que aceitam metadados e informações de validação de negócios como entrada.
Talvez a principal vantagem de se criar um serviço de cheques parametrizados seja a redução do tempo de entrega da funcionalidade ao ambiente de produção. Novas verificações de qualidade podem contornar o padrão clássico de entrega de código indiretamente por meio de ambientes de desenvolvimento e teste:
- Todas as verificações de metadados são geradas automaticamente quando o modelo muda no EA;
- As verificações de disponibilidade de dados (determinando a presença de quaisquer dados em um ponto no tempo) podem ser geradas com base em um diretório que armazena o tempo esperado para o aparecimento do próximo dado no contexto de objetos;
- As verificações de plausibilidade dos dados de negócios são criadas por analistas em notebooks Zeppelin. De onde eles vão direto para as tabelas de configuração do módulo DQ no ambiente de produção.
Não há riscos de envio direto de scripts para a produção como tal. Mesmo com um erro de sintaxe, o máximo que nos ameaça é a falha em realizar uma verificação, porque o fluxo de cálculo de dados e o fluxo de verificação de qualidade de lançamento estão separados um do outro.
Na verdade, o serviço DQ está permanentemente em execução no ambiente de produção e está pronto para começar a trabalhar quando o próximo dado aparecer.
Em vez de uma conclusão
A vantagem de usar baixo código é óbvia. Os desenvolvedores não precisam desenvolver um aplicativo do zero. Um programador livre de tarefas adicionais fornece resultados mais rápidos. A velocidade, por sua vez, libera um recurso adicional de tempo para resolver problemas de otimização. Portanto, neste caso, você pode contar com uma solução melhor e mais rápida.
Claro, o código baixo não é uma panacéia, e a mágica não acontecerá por conta própria:
- A indústria de baixo código está passando por um estágio de "crescimento" e, até o momento, não há padrões industriais uniformes;
- Muitas soluções de baixo código não são gratuitas e comprá-las deve ser uma etapa deliberada, o que deve ser feito com total confiança nos benefícios financeiros de seu uso;
- GIT / SVN. ;
- – , , « » low-code-.
- , low-code-. . / IT- .

No entanto, se você conhece todas as deficiências do sistema escolhido e os benefícios de seu uso, no entanto, são a maioria dominante, então vá para o código pequeno sem medo. Além disso, a transição para ele é inevitável - como qualquer evolução é inevitável.
Se um desenvolvedor em uma plataforma de baixo código puder fazer seu trabalho mais rápido do que dois desenvolvedores sem baixo código, isso dará à empresa uma vantagem inicial em todos os aspectos. O limite para entrar em soluções de baixo código é mais baixo do que nas tecnologias "tradicionais" e isso tem um efeito positivo na questão da falta de pessoal. Ao usar ferramentas de baixo código, é possível acelerar a interação entre as equipes funcionais e tomar decisões mais rápidas sobre a correção do caminho de pesquisa de ciência de dados escolhido. Plataformas de baixo nível podem impulsionar a transformação digital de uma organização, uma vez que as soluções produzidas podem ser entendidas por especialistas não técnicos (em particular, usuários de negócios).
Se você tem um prazo curto, uma lógica de negócios ocupada, uma falta de conhecimento tecnológico e precisa acelerar o tempo de colocação no mercado, o baixo código é uma das maneiras de atender às suas necessidades.
Não há como negar a importância das ferramentas de desenvolvimento tradicionais, mas em muitos casos o uso de soluções de baixo código é a melhor maneira de melhorar a eficiência dos problemas que estão sendo resolvidos.