BT

Disseminando conhecimento e inovação em desenvolvimento de software corporativo.

Contribuir

Tópicos

Escolha a região

Início Artigos Unindo desenvolvimento ágil e DevOps

Unindo desenvolvimento ágil e DevOps

Favoritos

Pontos Principais

  • A metodologia ágil mais famosa para gestão e planejamento de projetos, conhecida o Scrum, precede o crescimento de uma cultura DevOps. Consequentemente, as práticas dentro dessa metodologia (e outros frameworks ágeis), focam bastante no que podemos vagamente definir como os aspectos de entrega de software, e bem menos nos aspectos operacionais.
  • Uma abordagem DevOps deve fazer você repensar o modo como sua equipe é formada, repensar os backlogs, como as histórias de usuários são escritas, e assim por diante. m backlog, por exemplo, deve incluir escalablidade, implantação, monitoramento, dentre outros.
  • Uma reunião de planejamento Sprint deve incluir alguns aspectos DevOps para que você possa discutir sobre a funcionalidade do produto, assim como seus recursos operacionais.
  • Um Scrum Master tradicional talvez não seja a melhor opção.o papel é mais parecido com o de um Agile coach.
  • Precisamos levar em consideração DevOps desde o momento que contratamos as pessoas integrantes da equipe, passando pelo planejamento e construção de nossos produtos até a sua aposentadoria.

Não adianta criar um produto que seja super legal, mega funcional, com um belo design e muito user friendly, se você não tem como implantar e mantê-lo, e muito menos fornecer uma rede de suporte após seu lançamento.

Na cultura Agile, muitas tentativas vêm sendo realizadas para garantir que a entrega do produto seja do jeito esperado pelo cliente, dentro do orçamento e no tempo estimado. Com muita dedicação, fazemos da nossa prioridade ajudar os clientes a determinar quais recursos são preferíveis por eles, para que possamos sempre oferecer o melhor serviço. Fazemos nossas entregas de serviços em menos tempo e com mais frequência, visando receber constantes feedbacks construtivos. Usamos o termo histórias de usuário para nos ajudar a pensar com o ponto de vista de um usuário, e nós testamos nosso código em cada commit para ter certeza que não estamos quebrando nossa base de código.

Isso é ótimo, mas onde estão todos os truques inteligentes e técnicas projetadas para assegurar a entrega de serviços implementáveis, escaláveis e eficazes, com a capacidade de serem atualizados em tempo real, monitorados desde o primeiro minuto de sua existência e gerenciados no dia a dia sem precisar ter uma equipe de engenheiros de suporte?

O desenvolvimento ágil pegou emprestado (e vem melhorando) ótimas ideias da indústria automotiva, do mundo da neurociência, da filosofia antiga, do exército e da matemática. Alguns exemplos são: a Manufatura Enxuta, tendência cognitiva, filosofias e práticas de liderança, e planejamento e dimensionamento de software. Agora é uma boa hora para pegar emprestado alguns princípios e idéias DevOps para garantir que o ágil continuará como a melhor e bem mais sucedida prática de entrega de produtos.

A maioria dos produtos passa a maior parte de suas vidas precisando de suporte e manutenção logo após serem lançados (correção de falhas, atualizações e melhorias, por exemplo). O jeito prático que eles são gerenciados (mudando para um serviço real, testados em ambientes reais, e assim por diante), bem como a maneira que seu desempenho pode exercer, são vistos como "Recursos Operacionais", e normalmente não são encontrados no Product Backlog.

O relatório da Gartner de 2006 relata que uma empresa gasta até 80% do seu budget para manter uma solução no ar, enquanto um relatório mais recente no ZDNet cita uma pesquisa da empresa de consultoria CEB que "descobriu que 57% de um budget vai para manutenção e atividades obrigatórias em compliance, bem abaixo do ano de 2011 que era de 63%."

DevOps nos ensina que os Recursos Operacionais, ou "Operabilidade", são na verdade cidadãos de primeira classe, e devem ser tratados com tanto cuidado e consideração quanto qualquer outra característica de um produto. A melhor maneira de garantir que isso aconteça é promover uma cultura de colaboração entre as equipes de desenvolvimento e operações. Como você poderá conseguir essa colaboração é outra questão, e os modelos DevOps podem ser bastante diferentes. Segundo o mantra do Amazon "você implementa, você executa", dessa forma tanto as atividades de desenvolvimento e as operacionais existem dentro de uma única equipe, para o "DevOps como uma plataforma", encontrada em algumas equipes da Google.

A necessidade de DevOps

Há alguns anos que ágil e DevOps caminham lado a lado. Porém, as várias discussões sobre o relacionamento dos dois continua a existir.

Algumas pessoas acham que DevOps é uma subclasse do desenvolvimento ágil, enquanto outras definem DevOps como "um baita acerto do Agile" e como um conjunto de práticas de automatização que são vagamente conectadas com a ideia principal do desenvolvimento Agile. Tudo isso depende da sua definição de DevOps. Independente do seu ponto de vista, a vontade de entregar um software funcionando que pode ser gerenciado, escalável, mantido e cuidado facilmente é algo que o mundo da entrega de software precisa desesperadamente.

A forma como executamos e operamos um software mudou drasticamente desde os dias em que o nosso framework de desenvolvimento ágil foi criado. O método Scrum começou em 1993, o livro da XP foi lançado em 1999 e o DSDM lançado em 1994. Naquela época, estávamos escrevendo ainda instaladores para Windows, colocando-os em disquetes e os publicando para as pessoas!

O ato de executar, manter e operar um software não era algo que fazia parte da realidade de um desenvolvedor.

Desde então, uma grande mudança ocorreu para Saas e PaaS, e o ambiente de produção está ao nosso alcance. Os desenvolvedores agora estão ativamente envolvidos no processo de operação e suporte de seus sistemas, mas nós ainda estamos seguindo frameworks que não acomodam esta mudança na maneira como trabalhamos.

Continuous Delivery para a salvação

Continuous Delivery necessita de uma implantação automatizada de entregas em produção. Este foi um passo na direção certa, ainda que criou sem querer um spin-off na carreira de engenheiros que lidam com o Continuous Delivery (gerando, assim, mais um silo). Engenheiros que cuidam do Continuous Delivery mudaram para equipes de Continuous Delivery, e eventualmente para "Equipe de Plataformas", uma vez que o gerenciamento dessas infraestruturas torna-se cada vez mais importante. Em muitos casos, esse "deslocamento" do aspecto do Continuous Delivery em várias equipes parece até algo natural, e isso permitiu que muitos times ágeis voltassem para a área que se sentiam mais confortáveis - desenvolvendo softwares, ao invés de entregá-lo.

Infelizmente, isso se encaixa perfeitamente com o framework Scrum - a Equipe de Desenvolvimento foca em criar, desenvolver e testar softwares, a Equipe de Continuous Delivery se concentra no gerenciamento do sistema que o implanta e na sua infraestrutura.

O problema com esta abordagem é que, ao separar o trabalho de construção e de implantação, junto com as atividades de gerenciamento de infraestrutura, estamos basicamente fazendo com que "o problema seja de outra pessoa" no ponto de vista da equipe ágil, e mais uma vez, a "Operabilidade" desaparece no background.

Muitas equipes adotaram o Continuous Delivery do "jeito certo" e isso permitiu que adotassem o mantra "nós construímos, nós gerenciamos" para a entrega de software (e com isso veio um maior senso de propriedade, e como resultado a qualidade melhorou). Porém, o mesmo não pode ser dito para todos. Existe uma grande resistência à adoção de novas práticas de desenvolvimento, mesmo que essas práticas sejam "´ágeis" na sua essência. Agora temos visto a mesma coisa acontecer com DevOps.

Anti-padrões DevOps

O foco principal de uma cultura DevOps é preencher a lacuna entre Dev e Ops, diminuindo as transferências maçantes e aumentando a colaboração, para que atividades como "implantação", escalabilidade, monitoramento e suporte não sejam negligenciadas no processo.

No entanto, já começamos a perceber um surgimento de anti-padrões no cenário DevOps, tal como a separação entre a equipe Dev e a equipe DevOps, criando um outro silo e fazendo pouquíssimo para aumentar a colaboração.

De uma perspectiva prática, não existe muita informação que nos ajude a juntar a equipe de desenvolvimento ágil com a nova metodologia DevOps.

Quais métodos devemos adotar? Quais metodologias precisamos parar de usar? Como começamos? Quais cargos e funções devemos exercer dentro da equipe? A maioria dessas perguntas continua sem resposta. Em consequência, tais equipes estão deixando de utilizar DevOps em vez de integrá-lo por completo em seus processos de desenvolvimento de software.

É dentro deste anti-padrão clássico que acontecem todas as cerimônias ágeis e muitas das práticas DevOps. Porém, o resultado final não é melhor do que o anterior. A manutenção de um sistema em produção ainda não é uma prioridade, e os produtos estão sendo aperfeiçoados em seu desenvolvimento, ao invés de melhorar em áreas como as de entrega e operação. Isso ocorre pois as principais práticas DevOps estão sendo deixadas de lado logo no início de um projeto, ao invés de serem vistas como algo vantajoso desde o início.

A solução, claramente, é criar o hábito de usar as práticas do DevOps desde o início, utilizando-as nos nossos processos e práticas diárias. Isso requer alguns ajustes e mudanças em nossos frameworks ágeis.

Atualizando as práticas ágeis

O que podemos fazer para garantir que estamos desenvolvendo softwares de maneira ágil, ao mesmo tempo em que entregamos e mantemos nossos produtos e serviços de acordo com uma das mais atualizadas e melhores práticas DevOps? Bem, isso é fácil - simplesmente usamos o conceito "shift left"!

Ok, eu sei que isso soa bem mais fácil na teoria do que na prática, mas o conceito é bem direto e simples de entender. Sublinhamos essa parte e adicionamos histórias e tarefas de funcionalidade no backlog, junto com as nossas de usuários. Nosso backlog, de repente, vira um conjunto completo de tarefas, épicos e narrativas que nos ajuda a entregar os produtos com sucesso, e em mantê-los uma vez que lançados (ao contrário a um simples conjunto de recursos funcionais do ponto de vista de um usuário).

A princípio isso pode parecer fácil, mas existem algumas coisas que devemos levar em consideração:

  • Quem vai trabalhar nessas histórias/tarefas de operação da aplicação?
  • Como alguém consegue escrever uma história sobre a operação sem um usuário final ?
  • Quais são as melhores práticas DevOps?
  • Como se pode esperar que um Product Owner gerencie isso?

A resposta de todas estas questões é: "as coisas precisarão mudar"!

Equipe

A maioria das equipes ágeis com as quais trabalhamos não possuem especialistas em operações, suporte ou infraestrutura. Você pode argumentar dizendo que não existe demanda suficiente para que tais especificações estejam em cada equipe agil, e talvez você venha a ter razão. Mas não se esqueça que foi dito a mesma coisa sobre os testers e arquitetos, engenheiros de banco de dados e UXs, dentre outros...

Se é importante a maneira que você entrega, mantém, atualiza e escala um produto, então você realmente precisa dessas habilidades na sua equipe.

Isso significa que você quebrará a regra das "duas Pizzas" do querido Jeff Bezos? Existe essa possibilidade. Mas se a sua quantidade de pizza é realmente importante para você, você sempre tem a possibilidade de melhorar suas habilidades! Não é tão assustador quanto parece - quanto mais nos movemos em direção a um mundo x de serviço, menos conhecimentos específicos de administração de sistema você precisará. Como alternativa, precisaremos de um vasto conhecimento das funções das nuvens e seus serviços.

Backlog

Se temos equipes multifuncionais, então também precisamos ter backlogs multifuncionais.

Deixe a ideia tradicional de Product Backlog no passado - já é mais do que a hora de termos uma nova abordagem focada nos aspectos operacionais de nossos serviços. E sim, usamos o termo "serviço" de propósito, já que atualmente estão mesmo sendo criados serviços, e não produtos empacotados. Serviços são produtos que precisam ser implantados, escaláveis, mantidos, monitorados e ter um suporte de serviço. E claro, o nosso backlog deve refletir tais características.

Atualmente, a maioria dos products backlogs do Scrum contém 90% de funcionalidades tradicionais. Essas funcionalidades são as mais desejadas pela perspectiva dos usuários finais. Os 10% restantes estão relacionados ao desempenho do serviço, ou algo com o modo de preparação (criação de um ambiente de desenvolvimento, organização de banco de dados, etc.) Temos muito a descobrir com os feedbacks dos usuários finais em relação a funcionalidade e recursos de um certo produto/software. Não sei ao certo se isso é uma consequência da própria estrutura Scrum, ou um resultado parcial vindo dos usuários finais pelos Product Owners (ou algo totalmente diferente).

Uma boa gestão de backlog deve conter (além das funcionalidades dos usuários):

  • A escalabilidade de um produto/serviço: está diretamente associada com a distribuição de sistemas.
  • O processo de implantação / deploy: o serviço tem que ser implantado na hora que lançado sem algum tempo de inatividade?
  • Monitoramento do serviço: quais aspectos precisam ser monitorados? Como atualizamos nosso sistema de monitoração com cada upgrade e mudança nova?
  • Registro de dados (logging): quais informações devem ser registradas? Por que? E como?
  • Alertas e avisos: a quem? Quando? Como?
  • Como realizar os testes para um serviço.
  • Aspectos relacionados à segurança e compliance, tais como modelos de criptografia, proteção de dados, PCI compliance e legislação de dados.
  • Performance operacional.

Skelton diz:

"Para evitar "a criação de um serviço legado", precisamos, desde o início, usar a maioria do orçamento do produto (e utilizar o tempo em equipe) em aspectos operacionais. Como uma regra geral, descobri que gastando 30% do orçamento do serviço em aspectos operacionais produz bons resultados, e em consequência, o sistema fica mais sustentável, implantável e mais fácil de diagnosticar um problema. E assim, os sistemas continuam a funcionar por muitos anos".

É importante lembrar que esses quesitos de segurança e operabilidade mudam constantemente, e evoluem juntamente com o produto/serviço, de modo que não se pode simplesmente realizá-los no início de um projeto e depois focar nos recursos tradicionais. Por exemplo, pode não ser rentável a implementação de uma solução auto-scaling para o seu sistema até que esse seja comercialmente bem-sucedido. Ou talvez, você precise alterar seu modelo de criptografia para que se adeque as novas medidas de compliance. Da mesma forma, talvez seja necessário que mude seu próprio modelo de deploy quando locais geograficamente diferentes apareçam online. Além disso, monitoramento geralmente precisa ser atualizado quando ocorrer qualquer alteração e mudança significante na funcionalidade de um aplicativo.

Estórias de usuários

As histórias de usuários são uma maneira fantástica de conseguir saber quais são os requesitos mais desejados em um produto/serviço no ponto de vista de um resultado esperado. As narrativas de usuários tem ajudado vários desenvolvedores (incluindo nós mesmos) a enxergar os problemas do ponto de vista do usuário final, e assim pensar em soluções para tais problemas ao invés de simplesmente seguir instruções. Estou usando como referência à maneira como as histórias de usuários focam no "o que" e não no "como" (uma boa história de usuário apresenta o problema e deixar a solução para os desenvolvedores).

As histórias de usuários são normalmente escritas no seguinte formato:

"Como a...

Eu quero...

Para que…"

Consequentemente, isso nos obriga a escrevê-los na perspectiva de um usuário (embora não seja necessariamente um usuário final).

No entanto, ao longo dos anos descobrimos que escrever histórias de operação usando este formato não nos traz muitas melhorias. Isso pode ocorrer porque a "perspectiva do usuário" não tem impacto algum na forma que a solução é tecnicamente implementada. De qualquer maneira, acho um pouco redundante escrever como um "administrador de sistemas" ou como "um desenvolvedor" se estiver implementando as soluções você mesmo.

Não é muito incomum ver "itens de backlog técnicos" escritos em um backlog sem usar o formato "Como a... Eu quero...Para que..." e, do mesmo jeito, não recomendo o formato para recursos operacionais. Prefiro usar o formato "O que e porquê", no qual enumera O QUE precisa ser feito e PORQUÊ (com fins the fornecer um contexto e background).

Sprints

Os Sprints que duram duas semanas são a melhor opção para o desenvolvimento de novos recursos e para melhorar a implantação e os testes. Logo em seguida são apresentados aos acionistas. Se os Sprints durassem mais tempo, seria difícil manter o foco e manter atualizado a lista de feedback loop. Se o tempo fosse ainda mais curto, digamos de uma semana, e de repente reuniões e cerimônias passam a ocupar uma porcentagem grande desse tempo reservado para o Sprint, significa que o tempo que você realmente tem para realizar os Sprints é bem pequeno. Como consequência, Sprints com duração de duas semanas são vistos como uma ótima opção para várias pessoas. É o tempo ideal para que as pessoas fiquem focadas e determinadas a terminar o que começaram.

Isso é ótimo se você está desenvolvendo um novo produto, mas e se você estiver no processo de melhorias ou de desenvolvimento de uma nova versão?

Quem irá cuidar de todos os problemas que poderão surgir na plataforma de produção?

Se você trabalha em um ambiente propício a barulhos e interrupções, então está ciente que tais podem estragar e retardar os processos durante o Sprint. Sprints com durabilidade de duas semanas parecem agregar muito valor em termos de ajudar as pessoas a se concentrarem em um alvo realista. Porém, em um ambiente imprevisível é mais complicado determinar com certa clareza o quanto você consegue realizar do seu backlog. É difícil, mas não impossível.

Se medirmos a quantidade média de atividades que conseguimos realizar a partir do backlog, e a quantidade média de "interrupções" da plataforma de produção, podemos chegar a duas estimativas de velocidades.

A velocidade de um backlog é uma estimativa de tempo em que se pode completar as atividades planejadas relacionadas ao produto e serviço, enquanto a velocidade não planejada é a quantidade de trabalho realizado durante o Sprint. Saber esses dois tipos de velocidades nos permite planejar de forma mais eficaz.

Outra opção viável é a metodologia Kanban, no qual possui três campos: O que precisa ser feito, Em execução e o Finalizado, e é muitas vezes o framework escolhido pelas equipes que tem menos visão de futuro em termos do que vão fazer na semana seguinte. Também pode ser altamente eficaz para a entrega de projetos de longo prazo, mas requer muita disciplina para garantir que o backlog seja uma prioridade.

Planejamento do Sprint

Se você estiver utilizando Sprints, deverá realizar uma reunião de planejamento do Sprint. Para que se tenha uma perspectiva DevOps no seu plano, precisará fazer o seguinte:

  • Convidar os responsáveis pelas operações, infraestrutura e o time de suporte para a reunião de planejamento.
  • Discutir sobre a funcionalidade do produto, assim como seus recursos operacionais.
  • Organizá-las para que estejam no próximo Sprint.
  • Tenha em mente o tempo e o trabalho que serão consumidos por "interrupções", ou seja, trabalhos que não estavam planejados vindos da solução em produção, tais como correções de erros, escalas, etc. Esse valor é a sua "velocidade não planejada" e atua para reduzir a velocidade do seu backlog. Quanto maior é a velocidade não planejada, menor será a velocidade do backlog.

Definição de pronto

O conceito de pronto também pode ser definido, em termos populares, como "teste de usuário realizado com sucesso", que é basicamente outra maneira de dizer "um novo recurso foi aprovado". Porém, isso normalmente não leva em conta atividades como segurança, desempenho e gestão operacional, entre outros. Para que uma história seja considerada "pronta", ela precisa estar apta para ser lançada (ou melhor ainda, estar no ambiente de lançamento). Isso significa que tal história tem que ter um modelo de negócio escalável, ser monitorada e obviamente implantável! Se a sua narrativa não se encaixa nesses critérios, não a pode considerar pronta.

Scrum Master

Tenha em mente que vamos precisar mudar ou quebrar algumas regras existentes do Scrum (exemplos acima), o papel do Scrum Master é questionável. Mesmo que queira manter o processo mais parecido com o Scrum possível, a verdade é que não será Scrum. Vai ser uma mistura de Scrum e DevOps.

Certos aspectos do papel do Scrum Master, como a remoção de obstáculos, ainda são perfeitamente válidos, mas agora o Scrum Master não só precisará remover os obstáculos das atividades de desenvolvimento de software, mas também para entrega e manutenção do software.

Outra opção é realizar a transição para um papel de Agile Coach, no qual os principais valores das técnicas ágeis são usados. Esses valores são adotados de uma forma compreensiva, e não são limitadas as regras prescritivas do modelo Scrum. A última coisa que você quer é um Scrum Master que não valoriza a finalidade do DevOps. Isso só vai gerar uma divisão ainda maior entre os lados de desenvolvimento e operações.

Product Owner

Em nosso ambiente de Agile e DevOps, nosso Product Owner precisa, mais do que qualquer outra pessoa, entender a importância da fase de gestão de operação.

Em ambientes SaaS, PaaS e Serverless, muito do seu valor está oculto - não está localizado na etapa front-end. O valor, porém, está em como nossos serviços funcionam. Entre vários resultados, alguns são: economia de tempo e dinheiro, melhor desempenho, riscos reduzidos, melhoria na segurança ou qualquer outro "valor" oculto. É imperativo que os Product Owners entendam esse processo, já que são eles que definem os itens que compõem o Product Backlog e os prioriza nos planejamentos de Sprint.

Integração contínua (CI) and entrega contínua (CD)

Algumas pessoas recomendam separar suas ferramentas de CI e CD, provavelmente porque a CI é mais focada em desenvolvimento enquanto a CD tem uma visão mais holística.

Independente da maneira que você enxerga as coisas, CI e CD são mais do que apenas ferramentas, são jeitos de trabalhar. Existe uma grande diferença entre ter um sistema de CI e fazer uma integração contínua. O mesmo pode ser dito sobre entrega contínua.

No nosso ambiente DevOps / Agile, é crucial que usamos CD como um mecanismo de entrega e também como um guia de regras e princípios. Isso é de extrema importância pois a entrega contínua consegue colocar os times de desenvolvimento e de operações juntos, em uma mesma equipe. Um bom pipeline de CD, como mostrado abaixo, mostrará todas as etapas necessárias para ter um software entregue com sucesso e regularmente. Você consegue ver com seus próprios olhos quão importante é ter um teste de infraestrutura disponível, estrutura de testes confiáveis, boa monitoração e automação de implantação.

Não se esqueça dos 8 Principios e 4 Práticas de Continuous Delivery, conforme descrito por Dave Farley, dando uma atenção especial às principais práticas de "construir o binário somente uma vez", "use o mesmo mecanismo de implantação em todos os ambientes" e "se algo der errado, pare a linha!". Mas, acima de tudo, nunca se esqueça dessa frase: "todo mundo é responsável pelo processo de release de um software".

Conclusão

O Scrum foi criado em uma época em que equipes não se preocupavam com problemas operacionais tais como escalabilidade, implementação, monitoramento e manutenção.

Consequentemente, as práticas dentro desse método (e outros frameworks ágeis), focam bastante no que podemos vagamente definir como os aspectos de entrega de software, e bem menos nos aspectos operacionais.

DevOps ajuda a corrigir esse desequilíbrio, mas tem pouca influência sobre as práticas que ocorrem durante a fase de desenvolvimento. A falta de uma definição e de um framework prescritivo significa que não existe muitas informações em como juntar o conhecimento do DevOps com os processos de desenvolvimento ágil de software.

Para maximizar o valor do ágil e do DevOps, você deve começar a utilizar alguns dos princípios do DevOps logo no início do seu processo de desenvolvimento, pois cessar o processo de implementação automotiva no final não irá te ajudar a criar uma solução mais escalável, implantável e gerenciável.

Precisamos levar em consideração DevOps desde o momento que contratamos nossos membros da equipe, passando pelo planejamento e construção de nossos produtos até a sua aposentadoria.

Isso significa que precisamos de uma nova maneira de de olhar para alguns conceitos do ágil, tais como habilidades e papéis dentro da equipe de produção, do Backlog, e como planejamos e executamos iterações.

Várias equipes já adaptaram suas práticas ágeis para se tornarem mais alinhadas com DevOps, mas não existe uma solução única para todos os problemas, apenas uma coleção de bons padrões.

Sobre os Autores

James Betteley tem experiência no ramo de desenvolvimento e operações, algo bastante útil para alguém que agora trabalha na área de DevOps! Ele passou os últimos anos soterrado no mundo de Transformações DevOps, ajudando várias organizações empresariais a usar princípios ágeis e DevOps para que possam oferecer um software melhor e bem mais rápido.

 

Matthew Skelton vem construindo, implantando e operando sistemas de software comerciais desde 1998. Cofundador e Consultor Principal da Skelton Thatcher Consulting, ele é especialista em ajudar as organizações a adotar e manter boas práticas para criar e operar sistemas de softwares: Continuous Delivery, DevOps, Aspectos do ITIL, e operabilidade do software. Matthew é um colaborador do famoso DevOps team topologies patterns e é o coautor dos livros Database Lifecycle Management (Redgate) and Continuous Delivery with Windows and .NET (O'Reilly). @matthewpskelton

Avalie esse artigo

Relevância
Estilo/Redação

Conteúdo educacional

BT