Iniezione delle dipendenze vs Metodi statici

8

Oggi ho avuto un'interessante discussione con un altro sviluppatore su come affrontare una classe con un metodo che accetta una stringa e restituisce una stringa.

Immagina qualcosa come il seguente, completamente creato per lo scopo dell'esempio

public string GetStringPart(string input)
{ 
   //Some input validation which is removed for clarity

   if(input.Length > 5)
        return input.Substring(0,1);

   if(input.Substring(0,1) == "B")
        return input.Substring(0,3);

   return string.empty;
}

Una funzione che ha una logica basata sul suo input di stringa viene aggiunta a un progetto usando DI e ha un contenitore DI in posizione. Vorresti aggiungere questa nuova classe con un'interfaccia e iniettarla dove necessario, o la renderebbe una classe statica? Quali sono i pro ed i contro di ognuno? Perché dovresti (o meno) voler rendere questo qualcosa usato con l'iniezione del costruttore piuttosto che accedere quando richiesto dovunque.

    
posta James 09.11.2017 - 15:14
fonte

2 risposte

13

Non c'è motivo per cui questo debba essere iniettato. Questa è solo una funzione, non ha dipendenze, quindi basta chiamarla. Può anche essere statico se vuoi perché sembra puro. Si possono scrivere prove unitarie contro questo senza difficoltà. Se è usato in altre classi, i test di unità possono ancora essere scritti.

Non è necessario astrarre funzioni senza dipendenze, è eccessivo.

Se questo diventa più complesso allora forse è necessario passare un'interfaccia a un costruttore o un metodo. Ma non andrei su quella strada a meno che non avessi una complessa% di% di logica basata sulla posizione, ecc.

    
risposta data 09.11.2017 - 19:21
fonte
9

Ecco perché

class DOSClient {
    OrderParser orderParser;
    string orderCode;

    DOSClient(OrderParser orderParser, string ordercode) { 
        this.orderParser = orderParser; 
        this.ordercode = ordercode;
    }
    void DisplayOrderCode() {
        Console.Write( "Prefix: " + orderParser.GetStringPart(ordercode) ); 
        ...
    }
}

class GUIClient {
    OrderParser orderParser;
    string orderCode;
    GUI gui;

    GUIClient(OrderParser orderParser, string ordercode, GUI gui) { 
        this.orderParser = orderParser; 
        this.ordercode = ordercode;
        this.gui = gui;
    }

    void DisplayOrderCode() {
        gui.Prefix( orderParser.GetStringPart(ordercode) ); 
        ...
    }
}

class OrderParserUS : IOrderParser {

    public string GetStringPart(string input)
    { 
        //Some input validation which is removed for clarity

        if(input.Length > 5)
            return input.Substring(0,1);

        if(input.Substring(0,1) == "B")
            return input.Substring(0,3);

        return string.empty;
    }
}

class OrderParserEU : IOrderParser {

    public string GetStringPart(string input)
    { 
        //Some input validation which is removed for clarity

        if(input.Length > 6)
            return input.Substring(0,1);

        if(input.Substring(0,1) == "#")
            return input.Substring(0,3);

        return string.empty;
    }
}

Se ti fossi comportato con un metodo statico, non sarebbe possibile modificare il comportamento di GetStringPart senza distruggere il vecchio comportamento o inquinarlo con la logica condizionale. È vero che le statiche sono malvagi globali mascherati, ma il fatto che disabilitino il polimorfismo è la mia principale lamentela su di loro. I metodi statici non sono di prima classe nei linguaggi OOP. Dando al metodo un oggetto in cui vivere, anche uno senza stato, rendiamo il metodo portatile. Il suo comportamento può essere passato come il valore di una variabile.

Qui ho immaginato un sistema che deve comportarsi in modo leggermente diverso quando viene schierato in Europa e poi schierato negli Stati Uniti. Piuttosto, forzare entrambi i sistemi a contenere il codice necessario solo all'altro, possiamo modificare il comportamento controllando quale oggetto di parsing degli ordini viene iniettato nei client. Questo ci consente di contenere la diffusione dei dettagli della regione. Semplifica anche l'aggiunta di OrderParserCanada senza dover toccare i parser esistenti.

Se questo non significa niente per te, non c'è davvero una buona argomentazione per questo.

BTW, GetStringPart è un nome terribile.

    
risposta data 09.11.2017 - 15:58
fonte

Leggi altre domande sui tag