Resumo : neste tutorial, você aprenderá sobre o princípio de inversão de dependência do Python para tornar seu código hi
Introdução ao princípio de inversão de dependência
O princípio de inversão de dependência é um dos cinco princípios SOLID na programação orientada a objetos:
- S – Princípio da responsabilidade única
- O – Princípio Aberto-Fechado
- L – Princípio da Substituição de Liskov
- I – Princípio de Segregação de Interface
- D – Princípio de Inversão de Dependência
O princípio da inversão de dependência afirma que:
- Módulos de alto nível não devem depender de módulos de baixo nível. Ambos devem depender de abstrações.
- As abstrações não devem depender de detalhes. Os detalhes devem depender de abstrações.
O princípio de inversão de dependência visa reduzir o acoplamento entre classes criando uma camada de abstração entre elas.
Veja o exemplo a seguir:
class FXConverter:
def convert(self, from_currency, to_currency, amount):
print(f'{amount} {from_currency} = {amount * 1.2} {to_currency}')
return amount * 1.2
class App:
def start(self):
converter = FXConverter()
converter.convert('EUR', 'USD', 100)
if __name__ == '__main__':
app = App()
app.start()
Linguagem de código: Python ( python )
Neste exemplo, temos duas classes FXConverter
e App
.
A FXConverter
classe usa uma API de um terceiro FX imaginário para converter um valor de uma moeda para outra. Para simplificar, codificamos a taxa de câmbio como 1.2
. Na prática, você precisará fazer uma chamada de API para obter a taxa de câmbio.
A App
classe possui um start()
método que usa uma instância da FXconverter
classe para converter 100 EUR em USD.
O App
é um módulo de alto nível. No entanto, The App
depende muito da FXConverter
classe que depende da API do FX.
No futuro, se a API do FX mudar, o código será quebrado. Além disso, se quiser usar uma API diferente, você precisará alterar a App
classe.
Para evitar isso, você precisa inverter a dependência para que a FXConverter
classe precise se adaptar à App
classe.
Para fazer isso, você define uma interface e torna-a App
dependente dela em vez de FXConverter
uma classe. E então você altera FXConverter
para ficar de acordo com a interface.
Primeiro, defina uma classe abstrata CurrencyConverter
que atue como uma interface. A CurrencyConverter
classe possui o convert()
método que todas as suas subclasses devem implementar:
from abc import ABC
class CurrencyConverter(ABC):
def convert(self, from_currency, to_currency, amount) -> float:
pass
Linguagem de código: Python ( python )
Segundo, redefina a FXConverter
classe para que ela herde da CurrencyConverter
classe e implemente o convert()
método:
class FXConverter(CurrencyConverter):
def convert(self, from_currency, to_currency, amount) -> float:
print('Converting currency using FX API')
print(f'{amount} {from_currency} = {amount * 1.2} {to_currency}')
return amount * 2
Linguagem de código: Python ( python )
Terceiro, adicione o __init__
método à App
classe e inicialize o CurrencyConverter
objeto ‘:
class App:
def __init__(self, converter: CurrencyConverter):
self.converter = converter
def start(self):
self.converter.convert('EUR', 'USD', 100)
Linguagem de código: Python ( python )
Agora, a App
classe depende da CurrencyConverter
interface, não da FXConverter
classe.
O seguinte cria uma instância do FXConverter
e passa-a para o App
:
if __name__ == '__main__':
converter = FXConverter()
app = App(converter)
app.start()
Linguagem de código: JavaScript ( javascript )
Saída:
Converting currency using FX API
100 EUR = 120.0 USD
No futuro, você poderá oferecer suporte a outra API de conversor de moeda criando uma subclasse da CurrencyConverter
classe. Por exemplo, o seguinte define a AlphaConverter
classe que herda do CurrencyConverter
.
class AlphaConverter(CurrencyConverter):
def convert(self, from_currency, to_currency, amount) -> float:
print('Converting currency using Alpha API')
print(f'{amount} {from_currency} = {amount * 1.2} {to_currency}')
return amount * 1.15
Linguagem de código: Python ( python )
Como a AlphaConvert
classe herda da CurrencyConverter
classe, você pode usar seu objeto na App
classe sem alterar a App
classe:
if __name__ == '__main__':
converter = AlphaConverter()
app = App(converter)
app.start()
Linguagem de código: JavaScript ( javascript )
Saída:
Converting currency using Alpha API
100 EUR = 120.0 USD
Junte tudo.
from abc import ABC
class CurrencyConverter(ABC):
def convert(self, from_currency, to_currency, amount) -> float:
pass
class FXConverter(CurrencyConverter):
def convert(self, from_currency, to_currency, amount) -> float:
print('Converting currency using FX API')
print(f'{amount} {from_currency} = {amount * 1.2} {to_currency}')
return amount * 1.15
class AlphaConverter(CurrencyConverter):
def convert(self, from_currency, to_currency, amount) -> float:
print('Converting currency using Alpha API')
print(f'{amount} {from_currency} = {amount * 1.2} {to_currency}')
return amount * 1.2
class App:
def __init__(self, converter: CurrencyConverter):
self.converter = converter
def start(self):
self.converter.convert('EUR', 'USD', 100)
if __name__ == '__main__':
converter = AlphaConverter()
app = App(converter)
app.start()
Linguagem de código: Python ( python )
Resumo
- Use o princípio de inversão de dependência para tornar seu código mais robusto, tornando o módulo de alto nível dependente da abstração, não da implementação concreta.