Come determinare i livelli di astrazione


35

Oggi stavo leggendo un libro chiamato "Codice pulito" e mi sono imbattuto in un paragrafo in cui l'autore stava parlando dei livelli di astrazione per funzione, ha classificato un codice come livello di astrazione basso / intermedio / alto.

La mia domanda è: quali sono i criteri per determinare il livello di astrazione?

Cito il paragrafo del libro:

Al fine di assicurarci che le nostre funzioni facciano "una cosa", dobbiamo assicurarci che le dichiarazioni all'interno della nostra funzione siano tutte allo stesso livello di astrazione. È facile vedere come il Listato 3-1 viola questa regola. Ci sono concetti che sono ad un livello molto alto di astrazione, come getHtml (); altri che si trovano a un livello intermedio di astrazione, come ad esempio: String pagePathName = PathParser.render (pagePath); e altri ancora di livello notevolmente basso, come: .append ("\ n").


2
Correlati: che cos'è l'astrazione? .
Adam Lear

Risposte:


27

L'autore spiega che nella sottosezione "Leggere il codice dall'alto verso il basso" della parte che parla di astrazioni (miniera di rientro gerarchica):

[...] vogliamo essere in grado di leggere il programma come se fosse un insieme di paragrafi TO , ognuno dei quali descrive l'attuale livello di astrazione e fa riferimento ai successivi paragrafi TO al livello successivo in basso.

  • Per includere le impostazioni e gli smontaggi, includiamo le impostazioni, quindi includiamo il contenuto della pagina di test e quindi includiamo gli smontaggi.
    • Per includere le configurazioni, includiamo la configurazione della suite se si tratta di una suite, quindi includiamo la configurazione normale.
      • Per includere l'impostazione della suite, cerchiamo nella gerarchia padre la pagina "SuiteSetUp" e aggiungiamo un'istruzione include con il percorso di quella pagina.
        • Per cercare il genitore ...

Il codice che andrebbe con questo sarebbe qualcosa del genere:

public void CreateTestPage()
{
    IncludeSetups();
    IncludeTestPageContent();
    IncludeTeardowns();
}

public void IncludeSetups()
{
    if(this.IsSuite())
    {
        IncludeSuiteSetup();
    }

    IncludeRegularSetup();
}

public void IncludeSuiteSetup()
{
    var parentPage = FindParentSuitePage();

    // add include statement with the path of the parentPage
}

E così via. Ogni volta che approfondisci la gerarchia delle funzioni, dovresti cambiare i livelli di astrazione. Nell'esempio sopra, IncludeSetups, IncludeTestPageContente IncludeTeardownssono tutti allo stesso livello di astrazione.

Nell'esempio fornito nel libro, l'autore suggerisce che la funzione grande dovrebbe essere suddivisa in funzioni più piccole che sono molto specifiche e fanno solo una cosa. Se fatto bene, la funzione refactored sembrerebbe simile agli esempi qui. (La versione refactored è riportata nel Listato 3-7 del libro.)


10

Penso che per capire questa domanda, devi capire cos'è un'astrazione. (Sono troppo pigro per trovare una definizione formale, quindi sono sicuro che sto per essere oscurato, ma qui va ...) Un'astrazione è quando prendi un soggetto complesso, o un'entità e nascondi la maggior parte dei suoi dettagli mentre espone la funzionalità che definisce ancora l'essenza di quell'oggetto.

Credo che l'esempio che ti ha dato il libro fosse una casa. Se dai un'occhiata molto dettagliata alla casa, vedrai che è fatta di assi, chiodi, finestre, porte ... Ma un disegno di cartone animato di una casa accanto a una fotografia è ancora una casa, anche se manca molti di quei dettagli.

Stessa cosa con il software. Ogni volta che programmi, proprio come suggerisce il libro, devi pensare al tuo software come livelli. Un determinato programma può avere facilmente oltre cento livelli. In fondo, potresti avere istruzioni di assemblaggio che girano su una CPU, a un livello superiore queste istruzioni potrebbero essere combinate per formare routine di I / O su disco, a un livello ancora più alto, non è necessario lavorare con Disk I / O direttamente perché puoi usare le funzioni di Windows semplicemente per aprire / leggere / scrivere / cercare / chiudere un file. Queste sono tutte astrazioni anche prima di arrivare al tuo codice dell'applicazione.

All'interno del codice, i livelli di astrazione continuano. Potresti avere routine di manipolazione di stringhe / reti / dati di livello inferiore. A un livello superiore è possibile combinare tali routine in sottosistemi che definiscono la gestione degli utenti, il livello dell'interfaccia utente e l'accesso al database. Ancora un altro livello di questi sottosistemi potrebbe essere combinato in componenti server che si uniscono per diventare parte di un sistema aziendale più grande.

La chiave di ciascuno di questi livelli di astrazione è che ognuno nasconde i dettagli esposti dai livelli precedenti e presenta un'interfaccia molto pulita da consumare dal livello successivo. Per aprire un file, non dovresti sapere come scrivere singoli settori o quali interruzioni hardware elaborare. Ma se inizi a viaggiare lungo la catena del livello di astrazione, sarai sicuramente in grado di tracciare dalla chiamata della funzione Write (), fino alle esatte istruzioni che vengono inviate al controller del disco rigido.

Ciò che l'autore ti dice di fare è quando definisci una classe o una funzione, pensa a quale livello sei. Se si dispone di una classe che gestisce sottosistemi e oggetti utente, la stessa classe non dovrebbe eseguire la manipolazione di stringhe di basso livello o contenere un intero gruppo di variabili solo per effettuare chiamate socket. Sarebbe la violazione dell'incrocio dei livelli di astrazione e anche del fatto che una sola classe / funzione faccia solo una cosa (SRP - Single Responsibility Principle).


2

La mia domanda è: quali sono i criteri per determinare il livello di astrazione?

Il livello di astrazione dovrebbe essere ovvio. È astratto se fa parte del dominio problematico, non fa parte del linguaggio di programmazione. È difficile essere più chiari di "altamente astratti" == "non reali" == "dominio problematico". E "non astratto == concreto == parte della lingua". Dovrebbe essere banale decidere il livello di astrazione. Non dovrebbe esserci alcuna sottigliezza.

.append("\n")non è astratto. Mette solo un personaggio su una stringa. Sarebbe concreto. Non astratto.

String pagePathName = PathParser.render(pagePath);si occupa di stringhe. Cose concrete. In parte su funzionalità del linguaggio di programmazione concrete. Lavorare in parte con concetti astratti di "percorso" e "parser".

getHtml(); Astratto. Si occupa di "Markup" e cose che non sono banali, concrete, con funzionalità linguistiche.

Riassunto == non una funzione linguistica.

Concrete == una caratteristica della lingua.


1
Se definisci l'abstract come una qualità che descrive quelle cose che un programmatore crea, vale a dire le astrazioni generate dal programmatore, allora sono propenso a concordare con le tue definizioni di parole. Ma tutti i linguaggi di programmazione sono astrazioni su qualcosa di più concreto. La scelta del linguaggio di programmazione determina, in larga misura, a quale livello di astrazione inizi.
Robert Harvey,

1

Penso che il livello di astrazione sia semplice ... se la riga di codice non implementa direttamente la singola responsabilità del metodo, è un altro livello di astrazione. Ad esempio, se il mio nome metodo è SaveChangedCustomers () e accetta un elenco di TUTTI i clienti come parametro, l'unica responsabilità è quella di salvare tutti i clienti nell'elenco che sono stati modificati:

foreach(var customer in allCustomers)
{
    if (CustomerIsChanged(customer)
        customer.Save();
}

Spesso, invece di chiamare il metodo CustomerIsChanged (), troverai la logica per determinare se il cliente è stato modificato incorporato nel ciclo foreach. Determinare se il record del cliente è cambiato NON è responsabilità di questo metodo! È un diverso livello di astrazione. E se la logica per fare quella determinazione fosse solo una riga di codice? Non importa !!! È un diverso livello di astrazione e deve essere al di fuori di questo metodo.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.