Dívida tecnológica

Origem: Wikipédia, a enciclopédia livre.

No desenvolvimento de software, a dívida tecnológica (também conhecida como dívida digital, dívida técnica, dívida de design[1] ou dívida de código) é um déficit ou custo implícito de retrabalho futuro necessário. Ela ocorre quando diante de um problema tecnológico, opta-se inicialmente por uma solução mais fácil, embora limitada e incompleta, ao invés de se adotar uma abordagem melhor e mais aprimorada que embora possa levar um pouco mais de tempo ou demandar um pouco mais de esforço para ser alcançada, não geraria um retrabalho futuro, ou seja, uma dívida tecnológica.[2]

Analogamente à dívida monetária,[3] se a dívida tecnológica não for paga, pode ir acumulando "juros" ao longo do tempo, dificultando cada vez mais a implementação de mudanças e evoluções. O déficit produzido pela dívida tecnológica não resolvida aumenta a entropia ou desordem do software e o custo de retrabalhos adicionais. Da mesma forma que a dívida monetária, a dívida tecnológica não é necessariamente uma coisa ruim e, às vezes (por exemplo, em uma prova de conceito) é algo necessário para se levar os projetos adiante. Por outro lado, alguns especialistas afirmam que a metáfora da "dívida tecnológica" tende a minimizar as suas implicações, o que resulta em uma priorização insuficiente do trabalho necessário para corrigi-la ou quita-la.[4][5]

Dado que uma mudança é iniciada em uma base de código, muitas vezes há a necessidade de fazer outras mudanças coordenadas em outras partes da base de código ou documentação, ou até em outros sistemas relacionados. As alterações necessárias que não forem concluídas então passam a ser consideradas dívidas e, até serem pagas, incorrerão em juros sobre juros, dificultando a construção e a evolução de um projeto. Embora o termo seja usado principalmente no desenvolvimento de software, ele também pode ser aplicado a outras profissões e cenários.

Causas[editar | editar código-fonte]

Causas comuns da dívida tecnológica incluem:

  • O desenvolvimento contínuo e a longa série de melhorias e mudanças de projetos ao longo do tempo tornam as soluções antigas abaixo do padrão ideal.
  • Definição inicial insuficiente, na qual os requisitos ainda estão sendo definidos enquanto o desenvolvimento já se iniciou. Casos em que o desenvolvimento começa antes de qualquer esforço de elaboração e gestão da demanda. Isso é feito para economizar tempo, mas geralmente ocasiona a necessidade futura de retrabalho.
  • As pressões de negócios, em que o negócio considera lançar algo antes que as implementações e mudanças necessárias sejam concluídas, produzem déficit tecnológico envolvendo essas mudanças incompletas.

[6]:4 [7]:22

  • Falta de processo ou compreensão tecnológica, nos quais as empresas ou organização são "cegas" ao conceito de dívida tecnológica e tomam decisões sem considerar suas implicações futuras.
  • Componentes fortemente acoplados, onde as funções não são modulares e o software não é flexível o suficiente para se adaptar às mudanças nas necessidades do negócio.
  • Falta de um conjunto de testes, que incentiva correções rápidas e arriscadas de bugs com "gambiarras".
  • Falta de documentação de software, onde o código é criado sem documentação de suporte. O trabalho para criar a documentação necessária representa uma dívida.[6]
  • Falta de colaboração entre as equipes, onde o conhecimento não é compartilhado em toda a organização e a eficiência do negócio é prejudicada, ou os desenvolvedores iniciantes não são devidamente orientados.
  • O desenvolvimento paralelo em várias ramificações acumula dívida tecnológica devido ao trabalho necessário para se mesclar as alterações em uma única base de código. Quanto mais mudanças feitas isoladamente, mais dívidas.
  • Refatoração adiada. À medida que os requisitos de um projeto evoluem, pode ficar claro que partes do código se tornaram ineficientes ou difíceis de editar e devem ser refatoradas para dar suporte a requisitos futuros. Quanto mais a refatoração demorar e quanto mais código for adicionado, maior será a dívida.

[7]:29

  • Falta de alinhamento com os padrões, onde recursos, frameworks e tecnologias padrões de mercado são ignorados. Eventualmente, a integração com os padrões virá e fazê-lo mais cedo custará menos (semelhante à "refatoração adiada").

[6]:7

  • Falta de conhecimento, quando o desenvolvedor não sabe escrever código adequado.[7]
  • Falta de propriedade, quando as demandas de software terceirizadas resultam na necessidade de uma revisão ou reengenharia interna para refatorar ou reescrever o código terceirizado.
  • Liderança tecnológica pobre, onde decisões mal pensadas ou sem propriedade das implicações tecnológicas são transmitidas na cadeia de comando.
  • Mudanças de especificação de última hora. Eles têm potencial para causar impacto em todo o projeto, mas geralmente não há tempo ou orçamento suficientes para se documentar e testar todas as mudanças necessárias.

Reparar ou quitar a dívida tecnológica[editar | editar código-fonte]

Kenny Rubin usa as seguintes fases possíveis de itens da dívida tecnológica, no que se refere a identificação e reparo:[8]

  • Dívida tecnológica descoberta ao acaso — um débito que a equipe de desenvolvimento desconhecia existir até que foi exposto durante o curso normal da execução do trabalho no produto. É uma dívida que era desconhecida até então. Por exemplo, a equipe está adicionando um novo recurso ao produto e, ao fazê-lo, percebe que uma solução inadequada havia sido incorporada ao código anos antes por alguém que já partiu há muito tempo da instituição.
  • Dívida tecnológica conhecida — dívida que é do conhecimento da equipe de desenvolvimento e foi dada visibilidade dentro das demais equipes da organização, mas ainda não foi endereçada.
  • Dívida tecnológica endereçada — dívida que é conhecida e já está no backlog para atendimento e reparo pela equipe de desenvolvimento.

Consequências[editar | editar código-fonte]

Os "pagamentos de juros" da dívida tecnológica são os "custos" que são gerados por ela ao longo do tempo. Estes custos surgem na forma de necessidade de manutenção frequente para que o software funcione minimamente conforme o esperado, ou surgem também pela ausência de manutenção do mesmo apesar dos problemas existentes. Neste último caso, os problemas tendem a aumentar com o tempo e tendem a gerar custos extras, como por exemplo, custos adicionais de suporte pelo aumento do número de chamados abertos pelos usuários ou custos de desenvolvimento futuros maiores pela qualidade cada vez mais afetada. Quanto mais se adia a resolução da dívida tecnológica, mais ela se eleva e maior será seu custo de quitação no futuro. Ainda mais se o software em questão estiver sofrendo modificações. Paga-se a dívida simplesmente concluindo-se o trabalho necessário para sanar os problemas e os déficits existentes.

O acúmulo de dívida tecnológica é uma das principais causas de atrasos nos projetos.  É difícil estimar exatamente quanto trabalho é necessário para se saldar a dívida. Para cada mudança iniciada, uma quantidade incerta de trabalho incompleto é comprometida com o projeto. Porque as incertezas vão se acumulando. O prazo é perdido quando o projeto percebe que há mais trabalho incompleto (dívida) do que tempo para concluí-lo. Para ter cronogramas de lançamento previsíveis, uma equipe de desenvolvimento deve limitar a quantidade de trabalho em andamento para manter a quantidade de trabalho incompleto (ou dívida) pequena o tempo todo.

Se o critério de aprovação de um software é apenas o trabalho concluído, então este projeto pode ser lançado com uma quantidade substancial de dívida tecnológica, pois apenas um critério superficial foi considerado. Se esse software chegar à produção, os riscos de se implementar quaisquer refatorações futuras para sanar a dívida tecnológica aumentam drasticamente. A modificação do código de produção acarreta o risco de interrupções, perdas financeiras reais e possivelmente repercussões legais se os contratos envolverem acordos de nível de serviço (SLA). Por esse motivo, podemos ver a transposição da dívida tecnológica para a produção quase como se fosse um aumento na taxa de juros e a única forma de diminuir essa taxa seria quando estes softwares em produção são desativados ou inteiramente substituídos.

À medida em que um software é continuamente modificado, sua complexidade refletindo sua deterioração estrutural se eleva, a menos que um trabalho seja feito para mantê-la constante ou reduzi-la.
Original (em inglês): As an evolving program is continually changed, its complexity, reflecting deteriorating structure, increases unless work is done to maintain or reduce it.

 Leis da Evolução do Software Revisitadas (Laws of Software Evolution Revisited), 1996[9] (em inglês)

Embora a Lei de Manny Lehman já indicasse que os programas em evolução têm sua complexidade e deterioração estrutural aumentadas, a menos que seja feito um trabalho para mantê-las, Ward Cunningham foi o primeiro a traçar uma comparação entre complexidade técnica e dívida tecnológica em um relatório de 1992:

Implantar código novo é como cair em dívida. Uma pequena dívida acelera o desenvolvimento tanto quanto este possa se pagar rapidamente com uma reescrita... O perigo está quando a dívida não é paga. Cada minuto gasto em código não muito bem escrito, se contabiliza como juros daquela dívida. Empresas de tecnologia inteiras podem ser paralisadas sob o peso da dívida de uma implementação mal consolidada, orientada a objetos ou não.
Original (em inglês): Shipping first time code is like going into debt. A little debt speeds development so long as it is paid back promptly with a rewrite... The danger occurs when the debt is not repaid. Every minute spent on not-quite-right code counts as interest on that debt. Entire engineering organizations can be brought to a stand-still under the debt load of an unconsolidated implementation, Object-oriented programming or otherwise.
Ward Cunningham, 1992

 O Sistema de Gestão de Portifólio WyCash (The WyCash Portfolio Management System), 1992 "[10] (em inglês)

Em seu texto de 2004, Refatoração para Padrões, Joshua Kerievsky apresenta um argumento comparável sobre os custos associados à negligência arquitetural de software, que ele descreve como "dívida de design".[11]

As atividades que podem ser adiadas, ou negligenciadas, incluem documentação, roteiros de testes, implementações das seções de código incompletas, tratamento dos alertas emitidos pelos compiladores das linguagens e análises estáticas de código. Outros aspectos que produzem dívida tecnológica incluem o conhecimento que não é compartilhado pela organização e código que é muito confuso para ser facilmente modificado.

Escrevendo sobre o desenvolvimento do PHP em 2014, Junade Ali disse:

O custo de nunca se pagar a dívida técnica é claro; eventualmente o custo de se entregar novas funcionalidades se tornará tão lento que se torna fácil para um produto de software bem desenhado ultrapassar o software mal desenhado em termos de funcionalidades. Na minha experiência, software mal desenhado também pode levar a uma força de trabalho de engenharia mais estressada, que por sua vez pode levar a uma maior rotatividade de pessoal (que por sua vez afeta os custos e a produtividade de se entregar novas funcionalidades). Adicionalmente, devido à complexidade de uma dada base de código, a habilidade de se estimar com precisão o trabalho, desaparece. Nos casos em que as empresas de desenvolvimento de software cobram seus serviços baseadas em funcionalidade por funcionalidade, a margem de lucro para entrega de código irá eventualmente se deteriorar.
Original (em inglês): The cost of never paying down this technical debt is clear; eventually the cost to deliver functionality will become so slow that it is easy for a well-designed competitive software product to overtake the badly-designed software in terms of features. In my experience, badly designed software can also lead to a more stressed engineering workforce, in turn leading higher staff churn (which in turn affects costs and productivity when delivering features). Additionally, due to the complexity in a given codebase, the ability to accurately estimate work will also disappear. In cases where development agencies charge on a feature-to-feature basis, the profit margin for delivering code will eventually deteriorate.
— Junade Ali

 Dominando Padrões de Projeto PHP (Mastering PHP Design Patterns), 2016[12] (em inglês)

Grady Booch compara como a evolução das cidades é semelhante à evolução dos sistemas de alta demanda por software e como a falta de refatoração pode levar à dívida tecnológica.

O conceito de dívida tecnológica é central para se compreender as forças que pesam sobre sistemas, porque frequentemente ele explica "onde", "como" e "porquê" um sistema é estressado. Nas cidades, reparos na infraestrutura são frequentemente adiados e mudanças incrementais são preferidas ao invés de mudanças mais ousadas. E da mesma forma ocorre em sistemas que possuem grande demanda por software. Usuários sofrem as consequências de complexidades preciosistas, atrasos nas melhorias e mudanças evolutivas insuficientes; os desenvolvedores que evoluem estes sistemas sofrem as estilingadas e flechadas por nunca terem tido a oportunidade de escrever código de qualidade porque eles estão sempre tentando recuperar o atraso.
Original (em inglês): The concept of technical debt is central to understanding the forces that weigh upon systems, for it often explains where, how, and why a system is stressed. In cities, repairs on infrastructure are often delayed and incremental changes are made rather than bold ones. So it is again in software-intensive systems. Users suffer the consequences of capricious complexity, delayed improvements, and insufficient incremental change; the developers who evolve such systems suffer the slings and arrows of never being able to write quality code because they are always trying to catch up.
Grady Booch, 2014

 (em inglês)

No software de código aberto, postergar o envio de alterações locais para o projeto upstream é uma forma de dívida tecnológica. 

Ver também[editar | editar código-fonte]

Referências

  1. Suryanarayana, Girish (novembro de 2014). Refactoring for Software Design Smells 1st ed. [S.l.]: Morgan Kaufmann. 258 páginas. ISBN 978-0128013977 
  2. «Definition of the term "Technical Debt" (plus, some background information and an "explanation")». Techopedia. Consultado em 11 de agosto de 2016 
  3. Allman, Eric (maio de 2012). «Managing Technical Debt». Communications of the ACM. 55 (5): 50–55. doi:10.1145/2160718.2160733 
  4. Jeffries, Ron. «Technical Debt – Bad metaphor or worst metaphor?». Consultado em 10 de novembro de 2015. Cópia arquivada em 11 de novembro de 2015 
  5. Knesek, Doug. «Averting a 'Technical Debt' Crisis». Consultado em 7 de abril de 2016 
  6. a b c Girish Suryanarayana; Ganesh Samarthyam; Tushar Sharma (11 de novembro de 2014). Refactoring for Software Design Smells: Managing Technical Debt. [S.l.]: Elsevier Science. ISBN 978-0-12-801646-6 
  7. a b c Chris Sterling (10 de dezembro de 2010). Managing Software Debt: Building for Inevitable Change (Adobe Reader). [S.l.]: Addison-Wesley Professional. ISBN 978-0-321-70055-1 
  8. Rubin, Kenneth (2013), Essential Scrum. A Practical Guide to the Most Popular Agile Process, ISBN 978-0-13-704329-3 (em inglês), Addison-Wesley, p. 155 
  9. Lehman, MM (1996). «Laws of Software Evolution Revisited». EWSPT '96 Proceedings of the 5th European Workshop on Software Process Technology: 108–124. ISBN 9783540617716. Consultado em 19 de novembro de 2014 
  10. Ward Cunningham (26 de março de 1992). «The WyCash Portfolio Management System». Consultado em 26 de setembro de 2008 
  11. Kerievsky, Joshua (2004). Refactoring to Patterns. [S.l.: s.n.] ISBN 978-0-321-21335-8 
  12. Ali, Junade (setembro de 2016). Mastering PHP Design Patterns | PACKT Books (em inglês) 1 ed. Birmingham, England, UK: Packt Publishing Limited. p. 11. ISBN 978-1-78588-713-0. Consultado em 11 de dezembro de 2017