TheCodeNaked

Orientação a objetos - Parte 7 (Copy)

Perfeito! Agora vamos aprofundar o conceito de injeção de dependência, que se encaixa naturalmente na arquitetura que estamos construindo com IMotor e ITransmissao.

Este será o próximo post da série, dando continuidade à ideia de sistemas conectados por contrato (interfaces), e mostrando como deixar essas conexões ainda mais limpas e flexíveis.


🔌 Injeção de Dependência: Dê o Motor Certo para Cada Carro

Nos artigos anteriores, aprendemos como encapsular os detalhes de uma classe, e como fazer com que objetos como TMotor e TTransmissao se conectem sem criar dependências circulares — como um parafuso e uma porca.

Também vimos como isso fica ainda mais poderoso quando usamos interfaces, permitindo que cada parte do sistema conheça apenas o contrato da outra parte, e não sua implementação interna.

Agora, vamos explorar o passo seguinte na arquitetura orientada a objetos: a injeção de dependência.


🤝 O que é dependência?

Primeiro, vamos entender o que significa “dependência” nesse contexto.

Quando uma classe precisa de outra para funcionar, dizemos que ela tem uma dependência.
No nosso exemplo:

  • TCarro depende de IMotor para gerar torque.
  • TCarro depende de ITransmissao para enviar esse torque às rodas.

Sem essas duas peças, o carro não anda.


🚫 O problema: criar dependências dentro da própria classe

Uma prática comum (e perigosa) é a classe instanciar suas dependências internamente, assim:

constructor TCarro.Create;
begin
  FMotor := TMotorCombustao.Create;
  FTransmissao := TTransmissaoManual.Create;
end;

Isso funciona, mas tem um custo:

  • Você amarra a classe TCarro a implementações específicas.
  • Fica impossível trocar o motor ou a transmissão sem alterar a própria classe.
  • Testar o carro com simulações ou mocks se torna inviável.

Esse padrão é chamado de injeção interna (ou acoplamento direto) — e é exatamente o que a injeção de dependência tenta evitar.


✅ A solução: Injetar dependências de fora

A ideia da Injeção de Dependência (DI) é simples:

Em vez da classe criar suas dependências, ela as recebe de fora, prontas para uso.

No nosso exemplo, TCarro pode ser construído assim:

constructor TCarro.Create(AMotor: IMotor; ATransmissao: ITransmissao);
begin
  FMotor := AMotor;
  FTransmissao := ATransmissao;
end;

E o uso:

Motor := TMotorCombustao.Create;
Transmissao := TTransmissaoManual.Create;
Carro := TCarro.Create(Motor, Transmissao);

Isso é injeção de dependência via construtor — a forma mais comum e direta.


🔁 Outras formas de injeção

Além do construtor, podemos fazer injeção por propriedade ou por método:

1. Injeção por propriedade

type
  TCarro = class
  public
    property Motor: IMotor write SetMotor;
    property Transmissao: ITransmissao write SetTransmissao;
  end;

Essa abordagem dá mais flexibilidade, mas pode causar erros se esquecer de configurar algo antes de usar o objeto.

2. Injeção por método

procedure TCarro.Configurar(AMotor: IMotor; ATransmissao: ITransmissao);
begin
  FMotor := AMotor;
  FTransmissao := ATransmissao;
end;

Funciona bem para inicializações dinâmicas, mas exige disciplina no uso.


🧪 Benefícios reais da Injeção de Dependência

  • Flexibilidade: troque o motor ou a transmissão a qualquer momento.
  • Testabilidade: injete versões falsas (mocks) para testes.
  • Reutilização: TCarro não muda se você criar TMotorEletrico, TTransmissaoCVT, etc.
  • Baixo acoplamento: classes sabem apenas o necessário sobre suas dependências.
  • Coesão: cada classe cuida apenas da sua própria lógica.

🛠️ Dica prática: use interfaces sempre que possível

Quando combinamos:

  • Encapsulamento
  • Interfaces
  • Injeção de Dependência

… estamos construindo um sistema verdadeiramente modular, escalável e fácil de evoluir.


🔄 Evoluindo ainda mais: Inversão de Controle

A Injeção de Dependência é um dos pilares do padrão maior chamado Inversão de Controle (IoC).

Em vez das classes controlarem suas dependências, o controle é movido para o nível superior do sistema (ou um contêiner de injeção).

No Delphi, isso pode ser feito manualmente, por fábricas, configurações externas, ou usando frameworks como o Spring4D, que oferece suporte a contêineres IoC (mas você pode fazer tudo isso sem framework, como estamos mostrando).


📌 Conclusão

A Injeção de Dependência é como montar um carro com peças modulares:

  • O chassi (TCarro) não precisa saber como o motor ou a transmissão foram feitos.
  • Ele só precisa receber componentes compatíveis — conectados por interfaces — e tudo funciona.

Essa abordagem reduz o acoplamento, aumenta a coesão e transforma seu código em uma plataforma extensível, pronta para crescer com segurança.


Se quiser, no próximo artigo podemos mostrar como criar fábricas para montar objetos com dependências pré-configuradas, ou partir para um exemplo mais completo com testes simulados (mocks).

Qual direção você gostaria de seguir agora?

Sobre o autor

TheCodeNaked

No TheCodeNaked, programar é consequência, não ponto de partida. Antes do código, vem a dúvida, a análise, o contexto. Não seguimos fórmulas — questionamos. Criar software é pensar com clareza. O resto é só digitação.

TheCodeNaked

Criar com clareza. Codificar com intenção.

TheCodeNaked

Ótimo! Você se inscreveu com sucesso.

Bem-vindo de volta! Você acessou com sucesso.

Você se inscreveu com sucesso o TheCodeNaked.

Sucesso! Verifique seu e-mail para acessar com o link mágico.

As suas informações de faturamento foram atualizadas.

Seu pagamento não foi atualizado