Durante la scrittura di codice orientato agli oggetti, dovrei sempre seguire uno schema di progettazione?

37

Esiste un modello di progettazione concepibile per qualsiasi programma orientato agli oggetti? Lo chiedo perché recentemente ho visto un'implementazione di una classe Door con Lock . Era parte di un test e la risposta diceva che il codice segue il modello Null Object:

class Lock
{
public:
    virtual void close() = 0;
    virtual void open() = 0;
    virtual bool is_open() const = 0;
    virtual ~Lock() { }
};

class DummyLock
    : public Lock
{
private:
    DummyLock();
    DummyLock(const DummyLock&) = delete;
    DummyLock& operator=(const DummyLock&) = delete;

private:
    void close() { }
    void open() { }
    bool is_open() const { return true; }

public:
    static DummyLock m_instance;
};

class Door
{
public:
    Door() : m_lock(DummyLock::m_instance) { }
    Door(Lock &lock) : m_lock(lock) { }

public:
    Lock& get_lock() const { return m_lock; }

private:
    Lock &m_lock;
};

Questo mi ha fatto riflettere: questo codice segue un buon modello di progettazione anche se la descrizione è così semplice (questa classe sta progettando una classe di porte con un lucchetto), quindi se sto scrivendo codice più complesso, dovrei sempre essere un modello di progettazione che sto seguendo?

    
posta user2030677 02.10.2014 - 19:56
fonte

9 risposte

143

should there always be some design pattern that I am following?

Caro Dio NO!

Voglio dire, puoi andare avanti e dire che qualsiasi codice casuale sta seguendo un modello casuale XYZ, ma non è più utile di me che pretende di essere il re della sedia del mio computer. Nessun altro sa veramente cosa significa e anche quelli che lo fanno non rispetteranno esattamente la mia richiesta.

I modelli di progettazione sono uno strumento di comunicazione in modo che i programmatori possano dire agli altri programmatori cosa è stato fatto o cosa dovrebbe essere fatto senza spendere un po 'di tempo a ripetersi. E poiché sono cose che vengono fuori un sacco di volte, sono concetti utili per i programmatori per imparare "hey, facendo apparire XYZ sempre perché è buono / utile".

Loro non sostituiscono la necessità per te di pensare da soli, di adattare i modelli per il problema unico di fronte a te o di gestire tutto l'inevitabile cose che non si adattano a bei secchi.

    
risposta data 02.10.2014 - 20:04
fonte
37

No.

Questo è ciò che la Gang of Four (che in origine ha reso popolare i modelli di design) ha dovuto dire al riguardo in il loro libro :

"No discussion of how to use design patterns would be complete without a few words on how not to use them. Design patterns should not be applied indiscriminately. Often they achieve flexibility and variability by introducing additional levels of indirection, and that can complicate a design and/or cost you some performance. A design pattern should only be applied when the flexibility it affords is actually needed."

L'esempio che mostri in realtà non fa granché (non penso che fosse destinato a farlo, penso che fosse solo un esempio). Di per sé, non ha bisogno del modello di oggetto nullo. Nel contesto di un programma più ampio, potrebbe.

L'approccio sbagliato presuppone che solo perché sia stato etichettato come un "modello di progettazione" deve essere buono, e quindi cercare altri posti in cui inserire più schemi. Usali quando si adattano al programma e risolvono effettivamente un problema per te.

    
risposta data 02.10.2014 - 23:11
fonte
29

if I am writing more complex code, should there always be some design pattern that I am following?

No. I design pattern sono proprio questo: pattern nelle relazioni tra oggetti. In altre parole, le relazioni che vengono utilizzate e riutilizzate spesso bastano a far dire a qualcuno "Ehi, sembra che stiamo facendo molto, diamo un nome". L'elenco dei modelli di progettazione non è stato determinato contemporaneamente all'inizio di OOP e quindi trasmesso da GOF ! Sono stati scoperti e infine documentati, e poi resi popolari dal libro.

Detto questo, una grande parte del vantaggio dei modelli di progettazione è che rendono più facile pensare al design del software a un livello più alto. Ti permettono di evitare di preoccuparti dei dettagli di implementazione e di pensare di più al quadro generale. In questo senso ti liberano dalla minuzie, ma possono anche limitarti nello stesso modo in cui il modo in cui ti esprimi può essere limitato dalle parole che conosci. Quindi, potrebbe venire un momento in cui è un modello di progettazione per la maggior parte di ciò che fai semplicemente perché i modelli che conosci sono i termini in cui pensi. Tieni gli occhi aperti per i casi in cui potresti abusare di un modello e in cui potresti dover riflettere in modo più approfondito sui modi migliori di fare le cose.

Inoltre, ti rendi conto che in pratica spesso non implementa un determinato modello di design tanto da riconoscere il modello in qualche codice esistente, come un framework di oggetto. Conoscere i modelli di progettazione comuni rende molto più facile imparare come si intende utilizzare un framework perché è possibile vedere le relazioni tra le classi in termini già comprensibili.

    
risposta data 02.10.2014 - 20:12
fonte
10

Gli schemi di progettazione hanno due vantaggi

  1. Sono facili da descrivere agli altri sviluppatori, perché le persone generalmente concordano su quali sono i pattern
  2. Tendono ad essere picchiati in modo piuttosto premuroso dai nostri predecessori, quindi i loro punti di forza e di debolezza sono ben compresi.

Gli obiettivi di ogni programma dovrebbero essere

  1. Funziona. Deve fare qualunque sia l'obiettivo finale, o non importa quanti schemi di design usi. I modelli di progettazione OO facilitano il calcolo del problema in bit di facile comprensione, quindi è più facile dimostrare che funziona.
  2. È facile da leggere. È qui che i modelli di design sono belli. I problemi OO che risolvono sono complicati. Se li risolvi in un modo "standard", è più facile con il prossimo sviluppatore
  3. È facile crescere. Quasi 0 programmi moderni finiscono dove tutti li hanno pianificati. Ogni programma cresce dopo la sua versione iniziale. I modelli OO sono noti per essere curiosamente bravi a crescere.

Ciò detto, ogni riferimento ai modelli di progettazione OO è "sono bravi nel lavoro". Non sono perfetti, ma riempiono molto bene una nicchia. Usali quando lavorano, evitalo quando non lo fanno.

Ad esempio, di "codice complesso", come hai detto nella tua domanda, prendi un linguaggio di scripting che ho scritto. La maggior parte è OO con schemi di design ovunque. Tuttavia, quando si trattava di scrivere al netturbino, ho dimenticato senza tante cerimonie tutte le pretese di OO, perché le cose particolari che dovevo fare erano meglio modellate come un buon vecchio stile. Non c'è un pattern OO nell'intera cosa fino a quando non si arriva a scrivere finalizzatori, dove ancora una volta OO ha iniziato a essere di nuovo un modello utile. Senza alcun fasto o circostanza, il codice tornò all'improvviso a utilizzare nuovamente le tecniche OO.

Usa modelli di design ogni volta che migliorano il tuo prodotto; evitali quando peggiorano il tuo prodotto.

    
risposta data 02.10.2014 - 23:02
fonte
5

Perderò un po 'la tendenza, perché la risposta è più sottile di quanto altre risposte si stiano lasciando intendere. Ogni classe che scrivi non dovrebbe utilizzare un modello di progettazione, ma la maggior parte dei programmi non banali che scrivi probabilmente dovrebbero.

Un programma non banale senza modelli di progettazione indica:

  • Il tuo programma è così unico che nessuna parte di esso è simile ai problemi comuni che i programmatori hanno dovuto affrontare in precedenza. O
  • Il tuo programma contiene quei problemi comuni, ma li hai risolti in un modo migliore a cui nessuno aveva mai pensato prima.

Entrambi gli scenari sono altamente improbabili, senza offesa.

Questo non significa che il modello di progettazione dovrebbe guidare il tuo design, o che dovresti inserirne uno indiscriminatamente perché pensi che sembrerà cattivo se non lo fai. Il modello di progettazione sbagliato è peggiore di nessuno.

Che cosa significa è che dovresti considerare la mancanza di schemi di progettazione nel tuo programma generale come un odore di codice. Qualcosa che ti fa dare una seconda occhiata e rivalutare se il tuo design non potrebbe essere più pulito. Se a quel punto decidi di lasciare schemi di progettazione fuori da un programma, questa dovrebbe essere una decisione deliberata e consapevole, non casuale.

Ad esempio, non dici "Devo modellare una porta e una serratura, quale modello di progettazione dovrei usare?" Tuttavia, se l'hai progettato per primo senza utilizzare alcun modello di progettazione, questo dovrebbe suggerirti in seguito di dire qualcosa del tipo: "Ho un sacco di verifiche nulle in questo codice, mi chiedo se c'è un modello di progettazione che potrebbe aiutare a gestirli."

Vedi la differenza? È una distinzione sottile ma importante.

    
risposta data 03.10.2014 - 19:21
fonte
4

Domanda interrotta. Permettetemi di darvi una nuova definizione del modello di progettazione che annullerebbe molti danni rilasciati da GoF: un modello di progettazione è una buona pratica di codifica . Questo è tutto.

Ogni modulo ragionevolmente complesso avrà diversi schemi di progettazione. Ogni volta che si memorizza nella cache, è probabile che si tratti di un modello di peso mosca, ma non ho intenzione di revocare il livello di programmazione se non lo si chiama così. Ogni volta che hai una richiamata, ti trovi in una specie di sequenza evento / fuoco / richiamata. ecc. Se hai la parola "statico" hai un singleton. Se hai un costruttore statico hai un modello di fabbrica. Se una risorsa viene passata al tuo modulo, stai utilizzando l'integrazione delle dipendenze.

"Motivo di progettazione" è un termine spezzato male divulgato da GoF, che fa sembrare che tutti i pattern siano sullo stesso livello o che dovresti usare il medico consigliato da 3 a 5 per classe. Ogni volta che fai qualcosa di giusto che qualcun altro ha fatto bene, è un modello di design . Un for(;;) è un modello comune utilizzato per rappresentare un ciclo infinito, per esempio.

Non dovresti provare a imparare un sacco di modelli di design. Le conoscenze di programmazione non sono indicizzate dai modelli di progettazione! piuttosto dovresti imparare come scrivere un buon codice leggendo libri, blog e partecipando a conferenze nel tuo campo. Ad esempio, se stai già utilizzando l'iniezione di dipendenze ma non l'hai etichettato, potresti trarre vantaggio da sempre usando DI o utilizzando un framework IoC. Oppure, se stai cercando di codificare il codice giusto negli eventi e nei callback, impara Haskell per familiarizzare con i modelli di progettazione funzionale e diventa facile.

E se tutta la tua classe si legge come una cosa importante qualcun altro ha fatto bene, perché stai reinventando la ruota? Usa le loro cose.

    
risposta data 03.10.2014 - 03:35
fonte
0

I modelli sono soluzioni comuni a problemi comuni. Seguiamo sempre alcuni schemi, i modelli di GoF affrontano quelli più ricorrenti. Questo, per avere una comprensione condivisa e un approccio condiviso noto agli ingegneri del software.

Detto questo, la mia risposta è no, ma sì, stai sempre seguendo un tuo schema. Come dice giustamente il GoF -

One person's Pattern is another person's primitive building block.

Grande citazione.

    
risposta data 17.11.2014 - 05:39
fonte
0

Quando scrivo codice, non ho intenzione di usare deliberatamente il maggior numero possibile di schemi di progettazione. Ma, suppongo, inconsciamente, quando ho un problema di codifica, uno dei modelli di progettazione sembra adattarsi, e io lo uso. E a volte niente si adatta. Ciò che è più importante per me è scrivere codice che faccia il lavoro ed è facile da mantenere e crescere.

Questo è un articolo sull'applicazione dei principi OOD utilizzando modelli di progettazione, e ha esempi di codice (in C ++). Mostra come e quando applicare alcuni dei modelli di progettazione per scrivere codice pulito.

    
risposta data 12.01.2015 - 17:10
fonte
0

Dovresti sempre seguire i principi di progettazione OO (ad es. modularità, nascondimento delle informazioni, alta coesione, ecc.). Gli schemi di progettazione sono una nicchia relativamente raffinata dei principi di progettazione OO, specialmente se si considera il principio KISS .

I pattern sono soluzioni a problemi di progettazione comuni. Questi problemi derivano da uno dei due luoghi (o da una combinazione di entrambi): lo spazio problematico (ad es. Software per la gestione delle risorse umane in un'azienda) e lo spazio soluzione . Un programma OO è un'istanza all'interno dello spazio della soluzione (ad esempio, uno dei molti modi in cui è possibile progettare un programma OO per facilitare la gestione delle risorse umane).

Non è così facile sapere quando usare un modello. Alcuni modelli sono di basso livello, più vicini alla codifica e allo spazio della soluzione (ad es. Singleton, Null object, Iterator). Altri sono motivati dai requisiti nello spazio del problema (ad esempio, Command pattern per supportare undo / redo, Strategy per supportare più tipi di file input / output).

Molti modelli derivano dalla necessità di supportare variazioni del software in futuro. Se non hai mai bisogno di fare quelle variazioni, un pattern potrebbe essere over-design. Un esempio potrebbe essere l'utilizzo del modello dell'adattatore per lavorare con il database HR esterno esistente. Decidi di applicare Adapter perché il database corrente funziona con Oracle e potresti voler supportare NoSQL in futuro. Se NoSQL non viene mai alla tua organizzazione, quel codice dell'adapter potrebbe benissimo essere inutile. Vedi YAGNI . Il supporto per le varianti che non arrivano mai è un uso improprio di un modello di progettazione.

    
risposta data 05.10.2014 - 15:55
fonte