Essa é uma pergunta mais filosófica, que aborda a plataforma .NET, mas talvez seja útil também para outros idiomas. Estou fazendo muitos testes de unidade e, especialmente, quando estou usando componentes de terceiros com os quais frequentemente luto. No .NET, há uma enorme reivindicação ao design de componentes para a escolha de qual método deve ser virtual ou não. Por um lado, é o uso de componentes (o que faz sentido ser virtual), por outro, é a mockability de componentes . Você pode usar o Shims para simular componentes de terceiros, mas isso geralmente leva a um design e complexidade ruins. Como me lembro da discussão sobre tornar todos os métodos virtuais (o JAVA o tem desde o início), o .NET era sobre desempenho. Mas ainda é o problema? Por que todos os métodos do .NET não são virtuais ou por que cada classe não possui pelo menos uma interface?
fonte
Respostas:
Como Anders diz , em parte se trata de desempenho e, em parte, de bloquear projetos mal-pensados para reduzir o escopo de problemas causados posteriormente por pessoas que herdam cegamente coisas que não foram projetadas para serem herdadas.
O desempenho parece óbvio - embora a maioria dos métodos não seja notada no hardware moderno, um getter virtual pode causar um impacto notável, mesmo no hardware moderno que depende cada vez mais de instruções facilmente previstas no pipeline da CPU.
Agora, o motivo de tornar tudo virtual por padrão parece ser motivado apenas por uma coisa: estruturas de teste de unidade. Parece-me que este é um motivo fraco, em que estamos alterando o código para se adequar à estrutura, em vez de projetá-la adequadamente.
Talvez o problema seja com as estruturas usadas aqui, elas devem melhorar para permitir a substituição de funções em tempo de execução por calços injetados, em vez de criar código que faça isso (com todos os hacks para contornar métodos privados e não virtuais, para não mencionar funções estáticas e de terceiros)
Portanto, a razão pela qual os métodos não são virtuais por padrão é como Anders disse, e qualquer desejo de torná-los virtuais para se adequar a alguma ferramenta de teste de unidade está colocando o carrinho à frente do cavalo, o design adequado supera as restrições artificiais.
Agora você pode mitigar tudo isso usando interfaces ou reformulando toda a sua base de código para usar componentes (ou microsserviços) que se comunicam por meio da passagem de mensagens em vez de chamadas de método com fio direto. Se você aumentar a superfície de uma unidade para que o teste seja um componente e esse componente seja totalmente independente, você não precisará realmente parafusá-lo para testá-lo.
fonte
Existem dois elementos na sua pergunta, então tentarei resolvê-los por vez:
Por que os métodos .NET não são virtuais por padrão?
A herança, na prática, tem muitos problemas . Portanto, se for para ser usado como parte de um design, deve ser cuidadosamente considerado. Ao tornar os métodos não virtuais por padrão, a teoria é que incentiva o desenvolvedor a pensar em herança ao projetar uma classe. Se isso funciona na prática é outra questão, é claro.
Por que nem todas as classes implementam uma interface?
Design deficiente é a resposta simples. Apesar de serem comumente reconhecidas como boas práticas por muito tempo, infelizmente muitas pessoas ainda não projetam seus sistemas com DI e TDD em mente.
A combinação de classes que não são totalmente herdáveis e que não são facilmente ridicularizadas cria uma "tempestade perfeita" de código difícil de testar. Até chegarmos ao dia em que todos usam o DI e o princípio de design para interface, não há muito que possa ser feito para aliviar a dor.
fonte
interface
just porque. Qual o valor de ter uminterface
para o que é essencialmente uma tupla glorificada? (Embora talvez usando um POJO / isto POCO é uma falha de projeto)As soon as you use classes as types, you are no longer doing OO
- Classes são tipos. O que?? A herança de classe normal é OO, não importa o que você diga. Você não decide mais que não é OO só porque DI é toda a raiva agora.