Iniezione di dipendenza (DI) e principio di inversione delle dipendenze (DIP) per funzioni integrate e librerie esterne

0

Domanda

Mi scuso se questa domanda è già stata pubblicata. Ho provato a cercare ma non ho trovato la risposta.

Spesso mi trovo a provare a usare DI e DIP dove ho bisogno di aprire un file o un socket. L'uso di DI avviene naturalmente quando si esegue il TDD poiché a volte è difficile e / o brutto per verificare che qualcosa sia stato scritto correttamente su un file o un socket.

  • Come si può usare DI e DIP per le librerie incorporate o esterne?
  • Questo è anche un modo corretto di fare le cose o sto esagerando?

Grazie in anticipo.

Codice

Ho un semplice archivio di valori-chiave che crea un file per Chiave e scrive il Valore in quel file.

from abc import ABCMeta, abstractmethod

class DiskInterface(metaclass=ABCMeta):

  @abstractmethod
  def open(self, path, mode):
    pass

  @abstractmethod
  def close(self):
    pass

  @abstractmethod
  def read(self):
    pass

  @abstractmethod
  def write(self, value):
    pass

  @abstractmethod
  def exists(path):
    pass


class DiskStore:

  def __init__(self, disk_if):
    assert isinstance(disk_if, DiskInterface)
    self.disk_if = disk_if

  def set(self, key, value):
    assert isinstance(key, str)
    assert isinstance(value, str)

    f = self.disk_if.open("/tmp/" + key, "w")
    f.write(value)
    f.close()

  def get(self, key):
    assert isinstance(key, str)

    key_file = "/tmp" + key 
    if self.disk_if.exists(key_file):
      f = self.disk_if.open(key_file, "r")
      ret = f.read()
      f.close()
      return ret 
    else:
      return None

# Unit tests

def test_set_and_get():
  if_stub = DiskIFStub()
  kvstore = DiskStore(disk_if=if_stub)

  kvstore.set("answer", "42")

  assert kvstore.get("answer") == "42"

class DiskIFStub(DiskInterface):

  def __init__(self):
    self.opened = False

  def open(self, path, mode):
    self.opened = True
    return self

  def close(self):
    self.opened = False

  def read(self):
    assert self.opened
    return self.v

  def write(self, value):
    assert self.opened
    self.v = value

  @staticmethod
  def exists(path):
    return True
    
posta Tomas Vestelind 01.06.2016 - 16:18
fonte

1 risposta

1

Come approccio generale, in gran parte indipendente dal linguaggio, ogni volta che sei preoccupato che il comportamento di una libreria di terze parti possa cambiare, la fornitura di quel comportamento (che sia il tuo codice in futuro o un'altra libreria di terze parti) potrebbe cambiare, o semplicemente si vuole disaccoppiare la libreria di terze parti, è perfettamente ragionevole costruire una classe wrapper più astratta attorno agli oggetti della libreria.

Se la lingua lo consente, il wrapper può essere un'interfaccia, per disaccoppiare e rispettare ulteriormente la mentalità del principio dell'inversione di dipendenza.

    
risposta data 01.06.2016 - 16:56
fonte