Ho un po 'di tempesta in una tazza da tè al lavoro, e sto cercando di capire se ho ragione, nel torto o forse un po' di entrambi.
Tutto è iniziato in modo abbastanza innocente; uno sviluppatore di un altro team stava commentando durante una revisione del codice del codice della mia squadra. Siamo un [relativamente] nuovo team e tendiamo a scrivere il nostro codice un po 'diverso dagli altri team: cerchiamo di seguire Clean Code, i principi SOLID, fare TDD, ecc. Il resto del codebase tende a più ... classica ... progettazione e implementazione aziendale con strati fissi, enormi interfacce / oggetti divini, modelli di dominio anemici e così via.
Lo stesso codebase è per un'applicazione di punta che elabora molte transazioni business-critical
Storicamente è stato costruito in fretta e solo negli ultimi mesi abbiamo avuto il tempo di provare a rimediare a molte delle scelte progettuali precedenti. Non sono un fan del modo in cui è stato fatto, ma sono disposto a fare dei compromessi dove devo.
Ad ogni modo il codice ha un aspetto simile a questo
public class Something
{
readonly IFoo _foo;
public Something(IFoo foo)
{
_foo = foo.ThrowIfNull("foo");
}
}
( ThrowIfNull
è un semplice metodo di estensione generico che racchiude il solito "if x == null throw new ArgumentNullException"). Personalmente non ne sono un fan ma agli altri piace così è bello.
Ora, ecco cosa è stato suggerito:
public class Something
{
readonly IFoo _foo;
public Something(IFoo foo)
{
#if debug
_foo = foo.ThrowIfNull("foo");
#else
_foo=foo;
}
}
La logica è che questo potrebbe in qualche modo risparmiare un sovraccarico nel codice di produzione. Ho sottolineato che non era davvero qualcosa di cui preoccuparsi, e che per me è più importante (come in molti altri ordini di grandezza più importanti) che gli invarianti di classe (in questo caso, le sue dipendenze) siano protetti (cioè _foo
non può essere null
) perché dobbiamo fallire velocemente se per qualche ragione qualcuno o qualcosa ha provato a costruire un Something
con un% co_de nullo %.
Ma poi un architetto anziano intervenne per sostenere che era qualcosa di cui non dovremmo preoccuparci; questi sono più o meno gli argomenti, insieme alle mie confutazioni (tutte parafrasate ovviamente). Sono anche un architetto, ma appena coniato, quindi non ho ancora molto peso:)
-
Siamo strettamente accoppiati alla nostra libreria IOC e si prenderà cura di assicurarci che le dipendenze non siano nulle. Pertanto, questo codice verifica solo indirettamente la libreria IOC e dovrebbe essere eliminato Ciò presuppone che tutte le classi con dipendenze siano gestite dallo IOC, e anche se sono in pratica, credo che non sia il punto - non dovremmo associarci, punto.
-
Il codice che tenta di utilizzare _foo in seguito fallirà comunque Per me, è come giustificare saltare gli assegni pre-volo in aereo perché "hey, se le ali cadono a metà volo, beh allora lo sapremo, giusto?"
(Quest'ultima cosa mi ha reso molto spaventato)
- Abbiamo tonnellate di classi che non lo fanno già, quindi non vogliamo davvero tornare indietro e interrompere i ( pochissimi ) test che avremo che falliranno quando passare null nella classe contstuctors ( come a volte facciamo ) Non ho davvero niente di buono da dire su questo - per quanto posso dire, se questo non è un approccio terribilmente sbagliato, allora penso che prenderò l'agricoltura per vivere. E 'stato a questo punto che ho deciso di smettere di prendere parte alla conversazione, ma devo sapere se sono pazzo o no:)
Quindi la domanda è questa.
Am I wrong, right or a little bit of both? I was always taught that protecting invariants is basic stuff, something that you just have to do, for the reasons I've listed in my rebuttals. Should I just drop this (not asking in terms of politics or career-wise, just if others feel as I do that's it's really something important and worth fighting for)