Cosa significa "scrivere il codice per i modelli nei problemi" e non "per le istanze"?

7

Stavo leggendo questo post su quello che serve per diventare uno sviluppatore d'élite: link

Dice: "Scrivi il codice per i pattern, non per le istanze specifiche". Cosa significa? Scrivi sempre il tuo programma utilizzando un modello di progettazione predefinito piuttosto che la soluzione personalizzata per il problema?

    
posta johnsimer 02.07.2016 - 04:21
fonte

5 risposte

18

Questo è chiaramente un fraintendimento, l'autore non significa "modello" nel senso di "modello di progettazione GOF". Non parla nemmeno di "pattern nel tuo codice", ma modelli nei problemi che stai per risolvere con il tuo codice.

Quindi, per esprimere la sua raccomandazione in altre parole: si dovrebbe provare a scrivere codice che risolva un'intera categoria di problemi invece di scrivere codice che risolva solo un caso molto specifico di un problema.

Ecco un esempio banale: non scrivere codice per riempire un array di dimensione 10 con i numeri da 1 a 10, anche se questo è attualmente il requisito che hai. Meglio scrivere una funzione che riempie un array arbitrario con numeri da 1 a sizeof (array). Quel pezzo di codice avrebbe le stesse dimensioni e non è più complicato, ma può essere riutilizzato molto più facilmente, può essere testato più facilmente e risolve la "più ampia categoria di problemi".

Naturalmente, in situazioni reali, per trovare la categoria corretta (o "pattern") è necessaria una certa esperienza e un po 'di talento, questo è ciò di cui parla l'articolo. Si dovrebbe aggiungere a quel paragrafo che esiste un certo rischio di overgeneralization, ed è importante che si cerchi di generalizzare solo quando non rende il codice inutilmente complicato (le migliori generalizzazioni rendono il codice più semplice).

    
risposta data 02.07.2016 - 10:02
fonte
6

Questo è piuttosto vago e l'autore non fornisce alcuna indicazione specifica. Sono abbastanza sicuro che non intenda la codifica implementando uno schema di progettazione dopo l'altro. Penso che significhi che è spesso più facile scrivere il caso generale rispetto al caso specifico.

Ecco un esempio recente del mio lavoro. Stiamo elaborando i dati da una fonte esterna. Vi sono più fasi di elaborazione e in ogni fase alcuni dei dati di input possono essere rifiutati. Dobbiamo raccogliere tutti i record errati.

Il codice precedente contiene più implementazioni di questo patten, e non è facile ottenere correttamente un caso. Così uno dei membri del mio team ha estratto questo modello in un metodo generale che esegue le funzioni in sequenza e raccoglie tutte le eccezioni per i rapporti successivi. Il caso generale è stato facile da scrivere e testare, e quindi tutti i casi specifici sono stati notevolmente semplificati. Spesso è più facile scrivere e testare codice più generale, perché essendo generale, non ha dipendenze.

Gli sviluppatori con esperienza solo nei linguaggi OO / procedurali spesso perdono queste opportunità per generalizzare i modelli di controllo comuni. Vedono la duplicazione nei calcoli, ma mancano la duplicazione nel controllo.

    
risposta data 02.07.2016 - 05:32
fonte
2

La maggior parte dei programmi ha schemi di codice che saranno richiesti più volte, possibilmente con variazioni. Se è possibile scrivere codice per gestire il modello, si semplifica notevolmente lo sviluppo in quanto non è necessario riscrivere codice simile. Considera questi esempi:

Un'applicazione legge e scrive file di testo in diversi punti dell'esecuzione. Hai un paio di opzioni:

  1. Aggiungi il codice per aprire e leggere il file pertinente ovunque sia necessario il codice.
  2. Scrivi funzioni che leggono o scrivono un file con il parametro nomefile e testo (in qualunque formato venga utilizzato dall'applicazione). Usali dove devi leggere o scrivere un file.

Il secondo caso è più semplice da codificare (dopo il primo file). È anche molto più facile da testare.

L'applicazione deve presentare molti moduli su un terminale di testo (potrebbe essere generalizzata). I moduli devono fornire la capacità di navigare da qualsiasi campo.

  1. Codifica ogni modulo e ogni convalida del campo come richiesto.
  2. Crea una funzione che presenta il modulo basato su una struttura di dati contenente dati rilevanti (prompt, tipo di campo (carattere, numero), dimensione del campo, ecc.) e restituisce una struttura contenente i campi. La funzione contiene la logica di navigazione appropriata (campo precedente, campo #, in alto, ecc.). Crea la struttura dati per ogni modulo e usalo quando sono richiesti i dati del modulo.

Questi sono due di una serie di funzioni che riducono il tempo di sviluppo su un progetto al 25% del tempo stimato. Nessuna delle due funzionalità era prontamente disponibile al momento.

    
risposta data 04.07.2016 - 14:54
fonte
1

La formulazione di questo articolo è piuttosto sfortunata, perché potrebbe essere interpretata nel senso di "trovare modelli di software ben noti e unirli insieme per creare un'applicazione funzionante". Questo è un approccio comunemente usato dagli sviluppatori inesperti, e funziona, purché tu capisca i modelli, come applicarli correttamente e quale sia il loro caso d'uso appropriato. Gli sviluppatori inesperti spesso raggiungono questo approccio troppo presto, prima che ne comprendano appieno le implicazioni.

Gli sviluppatori esperti sono in grado di creare i propri schemi di codice.

A titolo di spiegazione, fornirò un esempio. Supponiamo che tu abbia il seguente codice:

string text;
switch (number)
{
    case 1: 
        text = "alpha";
        break;
    case 2:
        text = "bravo";
        break;
    case 3:
        text = "charlie";
        break;
    ...etc.
}

In C #, questo può essere semplificato inserendolo in una funzione, poiché le istruzioni break vengono eliminate. Quindi il codice ora diventa:

switch (number)
{
    case 1: return "alpha";
    case 2: return "bravo";
    case 3: return "charlie";
    ...etc.
}

Ovviamente, la vera vittoria è quando si riconosce che questa non deve essere necessariamente un'istruzione switch . Invece, puoi creare un dizionario:

var words = new Dictionary<int, string>
{
    { 1, "alpha" },
    { 2, "bravo" },
    { 3, "charlie" }
    ...etc 
}

e ora puoi solo dire

var word = words[2];  // bravo

Questo è più potente di un'istruzione switch, per diversi motivi:

  1. Il dizionario non deve essere hardcoded, come fa l'istruzione switch. Puoi scegliere di caricare il dizionario da qualsiasi origine dati compatibile (compresi i file di configurazione XML, un database o anche un feed di dati remoto) e continuerà a produrre valori allo stesso modo.

  2. È possibile aggiungere nuove coppie chiave / valore al dizionario o eliminare valori non più necessari in fase di runtime. Non deve essere una lista fissa.

  3. Il dizionario scalerà meglio (manterrà buone prestazioni anche se ha un gran numero di voci).

Il dizionario è un potente modello di software che ha una vasta gamma di usi. È una struttura di dati generalizzata; puoi scegliere i tipi su cui opera e garantirgli un certo livello di prestazioni. Puoi anche avere dizionari di dizionari.

Per i più grandi lavori di archiviazione e recupero dei dati, lo sviluppatore esperto sa come raggiungere un database, perché è una tecnologia collaudata che fornisce determinate garanzie sul modo in cui funziona.

Questo è ciò che il post del blog intende per "codice di scrittura per modelli, non per istanze specifiche".

    
risposta data 02.07.2016 - 05:18
fonte
1

Dall'articolo citato, uno sviluppatore elitario

Writes code for patterns, not specific instances – it’s an intuitive skill that can’t really be learned, in my opinion. You either have it or you don’t. Really talented developers infer the patterns in a system, even before a module or a piece of code is written and they code for those patterns, rather than specific instances. This skill limits technical debt and results in a tighter, more usable codebase.

È piuttosto vago.


Userò uno dei miei software preferiti e allo stesso tempo meno mi piace mai come esempio, che sarebbe git . Una delle ragioni principali per cui git ha avuto tanto successo come sistema di controllo delle versioni distribuite è che gli autori di Git hanno visto il modello. Git traccia solo quattro tipi di oggetti: commit, tag, alberi e blob. Aggiungi i concetti di rami e telecomandi e questo è git al suo nucleo. Gli autori di git hanno visto questo modello, e lo hanno fatto molto presto nello sviluppo di git. Riconoscere il modello molto presto nello sviluppo di git è stato la chiave per il successo di Git.

Uno dei motivi chiave per cui Git è così sgradito da alcuni è che gli autori non hanno visto il modello nel modo in cui le persone usano i sistemi di controllo delle versioni o nel modo in cui la struttura del comando git è modellata. Questo errore ha portato a una struttura di comando piuttosto complessa e piuttosto ampia con argomenti non intuitivi, a volte con comandi duplicati e / o incoerenti. Ciò comporta che Git UX sia piuttosto sgradevole.

    
risposta data 02.07.2016 - 17:49
fonte

Leggi altre domande sui tag