Questa è una domanda piuttosto vaga, ma è qualcosa a cui non ho mai sentito una risposta soddisfacente quando leggo del design corretto.
Generalmente, quando si impara sulla programmazione orientata agli oggetti, l'astrazione, il factoring, ecc., Il santo graal del design - e il motivo per cui affermano sempre che si stanno utilizzando le tecniche di sviluppo in questione - è che renderà il tuo programma "facile da cambiare" , "manutenibile", "flessibile" o uno qualsiasi dei sinonimi utilizzati per esprimere un tale concetto dal suono produttivo. Contrassegnando gli ivar come privati, suddividendo il codice in molti piccoli metodi autonomi, mantenendo le interfacce generali, si presume che si ottenga la possibilità di modificare il programma con totale facilità e grazia.
Per cambiamenti relativamente piccoli, questo ha funzionato bene per me. Le modifiche alle strutture di dati interne utilizzate da una classe per aumentare le prestazioni non sono mai state una grande difficoltà, né hanno avuto cambiamenti alla fine dell'interfaccia utente, indipendentemente dall'API, come riprogettare un sistema di immissione del testo o revisionare la grafica per un elemento di gioco .
Tutti questi cambiamenti sembrano intrinsecamente autonomi. Nessuno di essi comporta modifiche al comportamento o alla progettazione del componente del programma che viene modificato, per quanto riguarda il codice esterno in questione. Indipendentemente dal fatto che tu stia scrivendo proceduralmente o in uno stile OO, con funzioni grandi o piccole, queste sono semplici modifiche da apportare anche se hai solo un design moderatamente buono.
Tuttavia, ogni volta che le modifiche diventano grandi e pelose, ovvero modifiche all'API, nessuno dei miei preziosi "schemi" viene mai in soccorso. Il grande cambiamento rimane grande, il codice interessato rimane interessato e molte ore di lavoro di generazione di bug sono davanti a me.
Quindi, la mia domanda è questa. Quanto è grande un cambiamento che il design appropriato afferma di poter facilitare? Esiste qualche ulteriore tecnica di progettazione, che non mi è nota o che non sono riuscita a implementare, che rende davvero semplici le modifiche dal suono appiccicoso, o è quella promessa (che ho sentito fare da così tanti paradigmi diversi) semplicemente una bella idea, completamente disconnesso dalle immutabili verità dello sviluppo del software? Esiste uno "strumento di modifica" che posso aggiungere alla mia cintura?
In particolare, il problema che sto affrontando che mi ha portato ai forum è questo: ho lavorato sull'implementazione di un linguaggio di programmazione interpretato (implementato in D, ma non è pertinente) e ho deciso che gli argomenti delle mie chiusure dovrebbero essere basati su parole chiave, anziché posizionali come sono attualmente. Ciò richiede la modifica di tutto il codice esistente che chiama funzioni anonime, che, fortunatamente, è piuttosto piccolo perché sono all'inizio dello sviluppo del mio linguaggio (<2000 righe), ma sarebbe enorme se avessi preso questa decisione in un secondo momento. In una situazione del genere, esiste un modo per cui con una lungimiranza adeguata della progettazione avrei potuto rendere più semplice questa modifica o alcuni cambiamenti (la maggior parte) intrinsecamente profondi? Sono curioso di sapere se questo è in qualche modo un fallimento delle mie capacità progettuali - se lo è, io '
Per essere chiari, non sono in alcun modo scettico nei confronti di OOP o di qualsiasi altro modello comunemente usato. Per me, tuttavia, le loro virtù sono nella scrittura originale, piuttosto che nel mantenimento, delle basi di codice. L'ereditarietà ti consente di astrarre bene schemi ripetitivi, il polimorfismo ti consente di separare il codice in base alla funzione umana (quale classe) piuttosto che all'effetto compreso in macchina (quale ramo switch
dell'istruzione), e piccole funzioni autonome ti permettono di scrivere in uno stile "bottom-up" molto piacevole. Tuttavia, sono scettico sulle loro pretese di flessibilità.
foo metarg1: bar metarg2: baz
come foo.metarg1_metarg2_(bar, baz)
. Tuttavia, la mia lingua sta apportando una modifica più ampia, vale a dire i parametri basati su elenco a parametri basati su dizionario, che influisce sul tempo di esecuzione ma non sul parser, in realtà, a causa delle proprietà specifiche della mia lingua non entrerò in questo momento. Poiché non esiste una mappatura chiara tra parole chiave non ordinate e argomenti posizionali, il runtime è il problema principale.