Ci sono degli svantaggi significativi nel dipendere dalle astrazioni?

9

Stavo leggendo questo wiki sul principio delle astrazioni stabili (SAP) .

Il SAP afferma che più un pacchetto è stabile più dovrebbe essere astratto. Ciò implica che se un pacchetto è meno stabile (più probabile che cambi), allora dovrebbe essere più concreto. Quello che non capisco veramente è perché dovrebbe essere così. Sicuramente in tutti i casi, indipendentemente dalla stabilità, dovremmo dipendere dalle astrazioni e nascondere l'implementazione concreta?

    
posta SteveCallender 09.11.2015 - 11:25
fonte

5 risposte

7

Pensa ai tuoi pacchetti come API, prendi l'esempio dal foglio, prendi le definizioni per Reader con string Reader.Read() e Writer con void Writer.Write(string) come API astratta.

Puoi quindi creare una classe Copy con un metodo Copier.Copy(Reader, Writer) e l'implementazione Writer.Write(Reader.Read()) e forse alcuni controlli di integrità.

Ora realizzi implementazioni concrete, ad es. FileReader , FileWriter , KeyboardReader e DownloadThingsFromTheInternetReader .

Che cosa succede se vuoi cambiare l'implementazione di FileReader ? Nessun problema, cambia la classe e ricompila.

Che cosa succede se vuoi cambiare la definizione della tua astrazione Reader ? Oops, non puoi semplicemente cambiarlo, ma dovrai anche cambiare Copier , FileReader , KeyboardReader e DownloadThingsFromTheInternetReader .

Questa è la logica alla base del principio di astrazione stabile: rendere le tue concretizzazioni meno stabili rispetto alle astrazioni.

    
risposta data 10.11.2015 - 15:17
fonte
6

A causa di YAGNI .

Se al momento hai solo un'implementazione di una cosa , perché preoccuparti di un livello extra e inutile? Comporterà solo una complessità inutile. Ancora peggio, a volte fornisci un'astrazione pensando al giorno in cui arriverà una seconda implementazione ... e questo giorno non succede mai. Che spreco di lavoro!

Penso anche che la vera domanda da porsi non sia "Devo dipendere dalle astrazioni?" ma piuttosto "Ho bisogno di modularità?". E la modularità non è sempre necessaria, vedi sotto.

Nella società in cui lavoro, alcuni dei software che sviluppo sono strongmente legati a qualche dispositivo hardware con cui deve comunicare. Questi dispositivi sono sviluppati per soddisfare obiettivi molto specifici e sono tutt'altro che modulari. :-) Una volta che il primo dispositivo prodotto esce dalla fabbrica e viene installato da qualche parte, sia il firmware che l'hardware non possono mai cambiare, ever .

Quindi, posso essere sicuro che alcune parti del software non evolveranno mai. Queste parti non hanno bisogno di dipendere dalle astrazioni poiché esiste solo un'implementazione e questa non cambierà mai. Dichiarare le astrazioni su queste parti di codice confonderà tutti e richiederà più tempo (senza produrre alcun valore).

    
risposta data 10.11.2015 - 22:11
fonte
6

Penso che tu sia forse confuso dalla parola stable scelta da Robert Martin. Ecco dove penso che inizi la confusione:

This implies that if a package is less stable (more likely to change) then it should be more concrete.

Se leggi l' articolo originale , vedrai (sottolineatura mia):

The classic definition of the word stability is:”Not easily moved.” This is the definition that we will be using in this article. That is, stability is not a measure of the likelihood that a module will change; rather it is a measure of the difficulty in changing a module.

Clearly, modules that are more difficult to change, are going to be less volatile. The harder the module is to change, i.e. the more stable it is, the less volatile it will be.

Ho sempre lottato con la scelta dell'autore della parola stable , in quanto io (come te) tendevo a pensare all'aspetto "verosimiglianza" della stabilità, cioè improbabile che cambi . La Difficoltà implica che la modifica di quel modulo interromperà molti altri moduli e ci vorrà molto lavoro per sistemare il codice.

Martin usa anche le parole independent e responsible , che per me trasmettono molto più significato. Nel suo seminario di formazione, ha usato una metafora sui genitori di bambini che crescono e su come dovrebbero essere "responsabili", perché i loro figli dipendono da loro. Il divorzio, la disoccupazione, l'incarcerazione, ecc. Sono grandi esempi reali dell'impatto negativo che i genitori avranno sui bambini. Pertanto, i genitori dovrebbero essere "stabili" a beneficio dei loro figli. A proposito, questa metafora di bambini / genitori non è necessariamente legata all'eredità in OOP!

Quindi, seguendo lo spirito di "responsabile", ho trovato significati alternativi per difficile da cambiare (o non dovrebbe cambiare ):

  • Obbligatorio - il che significa che altre classi dipendono da questa classe, quindi non dovrebbe cambiare.
  • Vedi - ibid.
  • Vincolato: gli obblighi di questa classe limitano la sua capacità di cambiare.

Quindi, inserendo queste definizioni nella dichiarazione

the more stable a package the more abstract it should be

  • più obbligati un pacchetto più astratto dovrebbe essere
  • più vedi un pacchetto più astratto dovrebbe essere
  • più vincolati un pacchetto più astratto dovrebbe essere

Citiamo il principio delle astrazioni stabili (SAP), sottolineando le parole confuse stabile / instabile:

Packages that are maximally stable should be maximally abstract. Unstable packages should be concrete. The abstractness of a package should be in proportion to its stability.

Chiarimento senza queste parole confuse:

Packages that are maximally beholden to other parts of the system should be maximally abstract. Packages that can change without difficulty should be concrete. The abstractness of a package should be in proportion to how difficult it will be to modify.

TL; DR

Il titolo della tua domanda chiede:

Are there any significant disadvantages to depending upon abstractions?

Penso che se crei le astrazioni in modo corretto (ad esempio, esistono perché molto codice dipende da loro), quindi non ci sono svantaggi significativi.

    
risposta data 11.11.2015 - 17:48
fonte
0

This implies that if a package is less stable (more likely to change) then it should be more concrete. What i don't really understand is why this should be the case.

Le astrazioni sono cose che sono difficili da cambiare nel software perché tutto dipende da loro. Se il tuo pacchetto sta cambiando spesso e fornisce delle astrazioni, le persone che dipendono da esso saranno costrette a riscrivere un grosso numero del loro codice quando cambi qualcosa. Ma se il tuo pacchetto instabile fornisce alcune implementazioni concrete, molto meno codice dovrà essere riscritto dopo le modifiche.

Quindi, se il tuo pacco cambierà spesso, dovrebbe fornire meglio concrezioni, non astrazioni. Altrimenti ... chi diavolo lo userà? ;)

    
risposta data 13.11.2015 - 09:26
fonte
0

Tieni presente la metrica di stabilità di Martin e cosa intende per "stabilità":

Instability = Ce / (Ca+Ce)

o

Instability = Outgoing / (Incoming+Outgoing)

Cioè, un pacchetto è considerato completamente instabile se tutte le sue dipendenze sono in uscita: usa altre cose, ma niente lo usa. In tal caso, ha senso solo che quella cosa sia concreta. Sarà anche il tipo di codice più semplice da modificare poiché non lo usa nient'altro e quindi nient'altro può rompere se quel codice viene modificato.

Nel frattempo, quando si ha lo scenario opposto di "stabilità" completa con un pacchetto utilizzato da una o più cose ma non utilizza nulla da solo, come un pacchetto centrale utilizzato dal software, è quando Martin dice questo la cosa dovrebbe essere astratta. Ciò è anche rafforzato dalla parte DIP di SOLI (D), il principio di inversione delle dipendenze, che afferma fondamentalmente che le dipendenze dovrebbero fluire uniformemente verso le astrazioni sia per il codice di livello basso sia per quello di alto livello.

Cioè, le dipendenze dovrebbero fluire uniformemente verso la "stabilità", e più precisamente, le dipendenze dovrebbero fluire verso pacchetti con più dipendenze in entrata rispetto alle dipendenze in uscita e, inoltre, le dipendenze dovrebbero fluire verso le astrazioni. L'essenza della logica dietro a ciò è che le astrazioni forniscono respiro per sostituire un sottotipo con un altro, offrendo quel grado di flessibilità per le parti concrete che implementano l'interfaccia per cambiare senza rompere le dipendenze in arrivo a tale interfaccia astratta.

Are there any significant disadvantages to depending upon abstractions?

Beh, in realtà non sono d'accordo con Martin qui per il mio dominio, e qui ho bisogno di introdurre una nuova definizione di "stabilità" come in "mancano motivi per cambiare". In questo caso, direi che le dipendenze dovrebbero fluire verso la stabilità, ma le interfacce astratte non aiutano se le interfacce astratte sono instabili (con la mia definizione di "instabile", come incline a cambiare ripetutamente, non di Martin). Se gli sviluppatori non riescono a ottenere le astrazioni corrette e i clienti cambiano idea in modi che rendono i tentativi astratti di modellare il software incompleto o inefficace, allora non beneficiamo più della maggiore flessibilità delle interfacce astratte per proteggere il sistema da cambiamenti di dipendenza a cascata . Nel mio caso personale ho trovato i motori ECS, come quelli trovati nei giochi AAA, tra i motori più stabili a cui abbia mai lavorato e il più flessibile contro le mutevoli esigenze di progettazione e, in un ECS, il flusso delle dipendenze verso la più concreta : verso i dati grezzi, ma tali dati sono altamente stabili (come in ", improbabile che abbia sempre bisogno di essere modificati"). Ho spesso trovato la probabilità che qualcosa che richiede modifiche future sia una metrica più utile del rapporto tra efferenti e accoppiamenti totali nel guidare le decisioni SE.

Quindi modificherei un po 'il DIP e dico semplicemente "le dipendenze dovrebbero fluire verso componenti che hanno la più bassa probabilità di richiedere ulteriori cambiamenti", indipendentemente dal fatto che tali componenti siano interfacce astratte o dati grezzi. Tutto ciò che conta per me è la probabilità che possano richiedere modifiche dirette alla progettazione. Le astrazioni sono utili solo in questo contesto di stabilità se qualcosa, essendo astratto, riduce tale probabilità.

Per molti contesti che potrebbero essere il caso di ingegneri e clienti decenti che anticipano le esigenze del software in anticipo e progettano astrazioni stabili (come in, immutabili), mentre quelle astrazioni offrono loro tutto il respiro che hanno bisogno di scambiare cemento implementazioni. Ma in alcuni domini, le astrazioni potrebbero essere instabili e inclini ad essere inadeguate, mentre i dati richiesti dal motore potrebbero essere molto più facili da anticipare e rendere stabili in anticipo. Quindi, in questi casi, può effettivamente essere più vantaggioso dal punto di vista della manutenibilità (la facilità di cambiare ed estendere il sistema) affinché le dipendenze scorrano verso i dati piuttosto che le astrazioni. In un ECS, le parti più instabili (come nelle parti più frequentemente modificate) sono in genere le funzionalità che risiedono nei sistemi ( PhysicsSystem , ad esempio), mentre le parti più stabili (come è meno probabile che vengano modificate) sono le componenti che solo sono costituiti da dati non elaborati ( MotionComponent , ad esempio) utilizzati da tutti i sistemi.

    
risposta data 17.12.2017 - 20:27
fonte