Dijkstra intendeva la modularizzazione del codice, quando scrisse sulla separazione delle preoccupazioni?


9

In primo luogo, ho letto un estratto del saggio di Edsger W. Dijkstra del 1974 "Sul ruolo del pensiero scientifico":

Lascia che provi a spiegarti, quali sono i miei gusti caratteristici di tutto il pensiero intelligente. È che uno è disposto a studiare in profondità un aspetto della propria materia in isolamento per il bene della propria coerenza, sapendo sempre che si sta occupando solo uno degli aspetti. Sappiamo che un programma deve essere corretto e possiamo studiarlo solo da quel punto di vista; sappiamo anche che dovrebbe essere efficiente e possiamo studiarne l'efficienza un altro giorno, per così dire. In un altro stato d'animo possiamo chiederci se, e se sì: perché, il programma è desiderabile. Ma non si ottiene nulla - al contrario! - affrontando questi vari aspetti contemporaneamente. È ciò che a volte ho chiamato "la separazione delle preoccupazioni", che, anche se non perfettamente possibile, è ancora l'unica tecnica disponibile per l'ordinamento efficace dei propri pensieri, che io conosca. Questo è ciò che intendo per "focalizzare la propria attenzione su un aspetto": non significa ignorare gli altri aspetti, è solo rendere giustizia al fatto che dal punto di vista di questo aspetto, l'altro è irrilevante. Si tratta di essere pensati per una o più tracce contemporaneamente.

Vedo una moderna separazione delle preoccupazioni parlare della modularizzazione del codice. Tuttavia, leggendo la citazione sopra, capisco che focalizzare la tua mente su un compito specifico alla volta, senza concentrarsi su altri aspetti. Questo non significa necessariamente che il codice debba essere separato in blocchi modulari.

Cioè, supponiamo che ci sia un codice davanti a te che in un file ha i concetti di vista, repository, controller, gestione degli eventi, factory, ecc. In un unico file.

Per un breve esempio, ecco un po 'di codice che ha accesso ai dati e visualizza (output):

$sql = "SELECT * FROM product WHERE id = " . db_input($id);
$row = db_fetch_array(db_query($sql)); 
<option value="<?=$row['id']?>"<?= $row['ver'] == $row['ver'] ? '  selected="selected"' : '' ?>>Version <?=$row['ver']?></option>

Usando la OO moderna, potrei inserire l'accesso ai dati nel suo file usando il modello Repository, il codice View può andare nel suo modello di file e posso collegarli insieme per comunicare tramite un controller (o Action o Request Handler), e posso aggiungere una fabbrica per creare e collegare varie dipendenze. E posso avere un file di configurazione che definisce quelle fabbriche. Sicuramente è a un passo dal single-file-tutto.

La mia domanda sulla separazione delle preoccupazioni è così: leggendo la citazione di Dijkstra, ho avuto l'idea che forse non intendeva necessariamente che la separazione delle preoccupazioni fosse "separazione modulare del codice (in file o le loro funzioni / metodi / ecc."), e che intendeva di più concentrare la propria mente su un aspetto del programma, senza appesantire se stessi concentrandosi su altri aspetti importanti ma al momento non da considerare, indipendentemente dal fatto che siano fisicamente separati nel codice o meno.

Perché allora ci stiamo caricando con la separazione del codice modulare fisico e i modelli di progettazione? Non basterà concentrarsi su un aspetto, indipendentemente da come è strutturato il codice?

Non sto parlando di scrivere il più orribile codice di spaghetti e quindi solo di considerarne un aspetto, sarebbe probabilmente un peso. Ma alla fine, quello che sto andando verso, è, perché eseguire la separazione del codice fisico, perché dividere il codice in file o blocchi separati (metodi), quando non è necessario per focalizzarsi mentalmente su un aspetto?

La separazione delle preoccupazioni dovrebbe rimanere un esercizio mentale, piuttosto che fisico?
In altre parole, dovrebbe esserci una disconnessione tra gli aspetti mentali (focus on) e quelli fisici (code on paper) della programmazione?


5
Sono abbastanza sicuro che nel 1974 abbia visto la programmazione modulare come un dato ovvio, ed è per questo che non ne ha discusso esplicitamente in quel documento. L'articolo di Parnas su come modularizzare era nel 1972 e a quel punto se la modularizzazione non era più una questione. In effetti, ciò che descrivi non è nemmeno una programmazione modulare, è una programmazione strutturata , che lo stesso Dijkstra ha fortemente sostenuto a favore già nel 1968 nel suo classico documento "Go To Considered Harmful".
Jörg W Mittag,

va bene così forse posso capire la "separazione delle preoccupazioni" più come un esercizio di concentrazione mentale e la modularizzazione come un modo per incapsulare un aspetto del codice sulla carta. Tuttavia ora vedo la separazione delle preoccupazioni e la modularizzazione più come concetti separati.
Dennis,

@ JörgWMittag, puoi definire la distinzione tra programmazione strutturata e modulare? Alcuni link su Google suggeriscono che sono uguali.
Dennis,

Strutturato = IF, WHILE, FORanziché GOTO. Modular = moduli con un'API pubblica ben definita rigorosamente separata da un'implementazione e una rappresentazione interne nascoste. (Ad esempio Modula, Mesa, Modula-2, Modula-3, poi dialetti Pascal ( UNIT).)
Jörg W Mittag

Risposte:


2

Dijkstra sta facendo una dichiarazione esplicita su come pensare. La modularizzazione del programma (e del processo) - ed è la sua desiderabilità - è forse il risultato di quel pensiero, ma il punto chiave che sta facendo è come valutare un problema. Il programma è in genere la soluzione a un problema e, sostenendo una "separazione delle preoccupazioni", offre saggi consigli. Il miglior esempio di questo è forse "ottimizzazione". La battuta era: "Quando pianifichi di ottimizzare un programma, la tua prima strategia dovrebbe essere: No." In altre parole, devi prima concentrarti sul rendere corretto il programma. Renderlo veloce e fantasioso è una preoccupazione che dovrebbe essere separata - ma anche non completamente rimossa.


14

La separazione delle preoccupazioni è un modo di pensare astratto che consiste nel considerare separatamente le cose che non devono essere correlate.

Modularizzazione (che separa un gruppo di funzioni non correlate in moduli), incapsulamento (che nasconde i dettagli interni dei moduli) e astrazione (che separa il generale dallo specifico e l'idea dalla sua implementazione) sono tutti mezzi per implementare questo modo di pensare nel dominio di progettazione software.


9

Suggerirei che, sebbene l'articolo sia di interesse storico, ciò che Dijkstra intendeva con il termine "separazione delle preoccupazioni" oltre 40 anni fa non è particolarmente rilevante oggi. Oggi è ampiamente utilizzato in riferimento alla modulizzazione.

Esistono numerose prove del fatto che la modulazione è estremamente benefica e che tali benefici superano di gran lunga i "pesi" che ci gravano. Qualunque cosa Dijkstra intendesse allora, non cambia il fatto che piccoli blocchi di codice, ognuno incentrato su una sola cosa, portano a un codice che è più facile da scrivere, leggere, comprendere, mantenere e testare.


5
Penso che si dovrebbe notare che gran parte del pensiero moderno sulla separazione delle preoccupazioni proviene dai primi documenti che alla fine hanno generato la programmazione orientata agli aspetti da IBM. Penso che i documenti iniziali (fine anni '90-inizio anni 2000) abbiano avuto la maggiore influenza lì. È passato un po 'di tempo e tutti i siti web sono cambiati. Non sono sicuro di riuscire a ritrovarli.
Berin Loritsch,

2
La parte difficile è cercare di definire cosa significhi "una cosa". Senza questo, l'idea è inutile in termini di scrittura pratica del codice, e sbagliarla ha immediatamente effetti dannosi sulla difficoltà di scrivere, leggere, comprendere, mantenere e testare il codice.
jpmc26,

1
Ci aiuterebbe davvero a capire la tua posizione se (a) spiegassi cosa pensi che Dijkstra intendesse per "separazione delle preoccupazioni" e (b) spieghi PERCHÉ pensi che ciò che intendeva dire non è più rilevante.
John R. Strohm,

2

Posso darti un esempio personale di separazione delle preoccupazioni che ritengo paragonabile ai concetti di Dijkstra. Quando analizzo un determinato argomento nel software, costruisco tre viste.

  1. Per prima cosa considero i dati. I dati rappresentano i predicati logici del problema. Le classi sono costruite per astrarre entità nel mondo reale, con i loro attributi come parametri dell'astrazione. Le associazioni tra classi rappresentano mappature funzionali tra le istanze di classe. Non vi è alcun codice coinvolto nel pensiero a questo punto e nessuna nozione di elaborazione. Solo una visione statica della logica coinvolta nell'argomento.
  2. Secondo, considero la dinamica. Ogni classe che ha un ciclo di vita non banale è modellata come una macchina a stati finiti. Ciò comporta considerazioni sull'esecuzione e la sincronizzazione del sequenziamento. Ancora una volta, nessun codice sta solo lavorando su come le cose interagiscono e la sequenza.
  3. Terzo, considero l'elaborazione. Qui, l'effettivo lavoro algoritmico che deve essere fatto su transizioni di stato o in altre operazioni sincrone.

Alla fine, si ottiene una visione a tre facce della materia che può quindi essere formulata come codice in qualunque raggruppamento sia conveniente per il codice stesso e per la sua manutenzione. Le tre sfaccettature non sono solo un esercizio mentale. Produco descrizioni scritte di tutte le sfaccettature. Perché? Perché se l'argomento è abbastanza grande, non posso contenere nemmeno un aspetto completo nella memoria a breve termine. Se l'argomento è piccolo, quasi ogni approccio funzionerà perché puoi tenerlo tutto in testa.

La motivazione per separare le preoccupazioni è quella di soddisfare i limiti di memoria a breve termine degli esseri umani. Semplicemente non possiamo portare tutto in testa contemporaneamente, anche se i programmatori di computer tendono ad essere più capaci della maggior parte delle altre persone per il numero di concetti che possono manipolare nella loro memoria a breve termine. Per essere efficace, separare le preoccupazioni deve sistematicamenteescludere uno o più aspetti di un problema al fine di concentrarsi su un altro aspetto particolare. Naturalmente, escludere un aspetto non lo fa scomparire dalla considerazione. Ci deve essere un mezzo per combinare tutti gli aspetti problematici per ottenere una soluzione. L'esperienza dimostra che spesso il risultato finale della separazione e ricombinazione produce una soluzione più comprensibile di un singolo salto gigante in cui molti aspetti potrebbero essere confusi. Ciò è particolarmente vero quando la dimensione del problema è grande o complessa.


1

La separazione delle preoccupazioni è un concetto logico che si propaga nel modello di organizzazione del codice indipendentemente da come lo si implementa. È vero che un file di codice è solo un dettaglio tecnico, un modo per mantenere gestibile il software. Un singolo file con un buon editor che consente di comprimere un'espansione delle regioni potrebbe funzionare anche per te (per un po '). Oppure un database relazionale che archivia classi e metodi in modo padre-figlio in tabelle separate potrebbe funzionare come supporto di memorizzazione. Ma i file di testo sono difficili da battere in un mondo in cui il codice sorgente deve essere

  • portatile
  • accessibile da molti strumenti esterni diversi
  • accessibile da più programmatori
  • versione e comparabile
  • scalare bene con i sistemi operativi che risultano essere molto bravi nella gestione dei file

La linea di fondo è che noi umani non siamo molto bravi a pensare o affrontare cose diverse contemporaneamente. Quindi abbiamo bisogno di un modello che consenta di pensare e lavorare su una cosa alla volta senza il pericolo di rovinare qualche altra parte che non stiamo prendendo in considerazione in quel momento. Quindi costruiamo, posando un mattone alla volta, assicurandoci che i mattoni che abbiamo posato prima non interferiscano con i mattoni posati in seguito. E se vogliamo cambiare un mattone più tardi, le cose non devono crollare. Questo è un modello che funziona per le nostre menti a senso unico.

Non è così che crescono i funghi o le alghe ... Come può essere un fatto umiliante?


-1

Credo che la risposta specifica alla citazione di Dijkstra sia stata indirizzata, tuttavia, dal momento che affermi "Usando la OO moderna potrei mettere l'accesso ai dati nel suo file" e chiedere "La separazione delle preoccupazioni dovrebbe rimanere un esercizio mentale, piuttosto che fisico?" lascia che attiri la tua attenzione su dove ci dirigono i moderni responsabili OO.

Uno dovrebbe seguire i principi SOLID nello sviluppo usando OO. Ecco un bel link per loro, ma il TLDR sulla "separazione delle preoccupazioni" è principalmente nella S in SOLID: The Single Responsibility Principle o SRP.

Questo, sicuramente, è un esercizio fisico, non mentale. Per il tuo esempio specifico, MVC (oi suoi fratelli MVVM e MVP) indirizzano uno a separare fisicamente i concerti di Model, View e Controller / Presenter / ViewModel in file separati. Ho visto alcune implementazioni MVVM in cui queste sono implementate in assiemi separati per limitare ulteriormente la tendenza di "confondere i concetti".

Ma. Va oltre il semplice "questa è una visione e questo è un modello", se segui la visione dello zio Bob su questo.

Bisogna anche considerare la fonte dei requisiti per ogni particolare elemento OO. Se stai mescolando, per esempio, ciò che il Cliente desidera con ciò che desidera il Personale delle Operazioni, stai anche violando la SRP. Oppure, per dirla come fa lo zio Bob: una classe dovrebbe avere uno e un solo motivo per cambiare.

Consiglio vivamente di effettuare ulteriori ricerche utilizzando i collegamenti forniti o di effettuare una ricerca Web per "principi solidi".


No. I principi SOLID sono così lontani dalla realtà della scrittura del codice (= filosofico) che possono essere compresi in qualsiasi modo remotamente utile una volta che sai già come scrivere un buon codice, a quel punto sono superflui. Usarli come principi guida senza avere già esperienza e abilità produce un codice estremamente scarso.
jpmc26,
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.