Esistono schemi di progettazione non necessari in linguaggi dinamici come Python?


98

Ho iniziato a leggere il libro dei modelli di design della GoF. Alcuni schemi sembrano molto simili con solo differenze concettuali minori.

Pensi che tra i tanti schemi alcuni non siano necessari in un linguaggio dinamico come Python (ad esempio perché sono sostituiti da una funzione dinamica)?


1
Una specie di domanda interessante, poiché implica che la scelta della lingua può effettivamente sostituire i costrutti di codice.
joshin4colours,

3
Non una risposta, ma pertinente: pensavo che i modelli di progettazione GoF fossero rilevanti per alcuni principi generali che possono essere distinti da essi come per i modelli specifici. Non intendo l'idea di uno schema (sebbene sia certamente significativo), ma piuttosto il permesso di usare le classi in certi modi che violano i principi ingenui di OOP. Ad esempio, ci sono molti modelli in cui "la forma" chiaramente non "si disegna da sola", o almeno delega alcuni aspetti del lavoro a qualche altro oggetto. Penso che la lezione sia importante in qualsiasi lingua che supporti OOP.
Steve314,

Domanda molto interessante. Vorrei poter +5 invece di +1.
MathAttack,

1
Dai un'occhiata anche a Are Design Patterns Missing Language Features e Design Patterns Missing Language Features over at c2. Non è nemmeno un problema di "linguaggio dinamico". L'esempio più semplice è il modello iteratore che è banale in Python, Perl (e persino Java - non dinamico).

Risposte:


92

Peter Norvig dimostra che 16 dei 23 modelli di design trovati nel libro del GOF sono invisibili o più semplici nei linguaggi dinamici (si concentra su Lisp e Dylan).

Da quando hai citato Python, c'è una bella presentazione di Alex Martelli sull'argomento. Anche in relazione con Python, c'è un bel post sul blog che mostra sei modelli di design in Python idiomatico .

Tengo anche un repository github con implementazioni (da parte di altre persone) dei modelli di progettazione più comuni in Python .


Grande! Sarebbe un punto di risposta :) Avrei voluto che tutti avessero capito la domanda chiaramente.
Gerenuk,

2
Secondo Norvig, 2 dei 16 (Interprete e Iteratore) sono "invisibili o più semplici" a causa delle macro (che Python non ha).
mjs,

1
non è chiaro per me che tutti questi schemi non siano necessari perché lisp è dinamico ma piuttosto per altre caratteristiche come l'essere un linguaggio funzionale forte
jk.

Gli Iteratori @mjs sono una funzionalità integrata di Python.
sakisk,

1
Questo grande risposta può essere anche leggermente migliorata modificando le didascalie di collegamento un po 'senza senso dimostra , presentazione e repository - sono molto meglio allora qui , ma, sai ... :-)
Lupo

59

Non sono necessari modelli di progettazione. In qualsiasi lingua

Tendo a imbattermi in un sacco di codice scritto da persone che leggono sui modelli di progettazione e poi pensano che dovrebbero usarli ovunque. Il risultato è che il codice reale viene sepolto sotto tonnellate di interfacce, wrapper e layer ed è piuttosto difficile da leggere. Questo è un approccio sbagliato ai modelli di progettazione.

Esistono modelli di progettazione in modo da avere a portata di mano un repertorio di idiomi utili quando si incontra un problema. Ma non dovresti mai applicare alcun modello prima di identificare il problema. Keep It Simple Stupid dovrebbe sempre essere il principio di governo superiore.

Aiuta anche a pensare ai modelli di progettazione come a un concetto per pensare al problema piuttosto che a un codice di caldaia specifico da scrivere. E su gran parte del boilerplate come soluzione alternativa a Java mancano le funzioni gratuite e gli oggetti funzione standard che si usano nella maggior parte degli altri linguaggi che li hanno (come Python, C #, C ++ ecc.).

Potrei dire che ho un modello di visitatore, ma in qualsiasi lingua con funzioni di prima classe sarà solo una funzione che assume una funzione. Invece della classe di fabbrica di solito ho solo una funzione di fabbrica. Potrei dire che ho un'interfaccia, ma poi sono solo un paio di metodi contrassegnati con commenti, perché non ci sarebbe nessun'altra implementazione (ovviamente in Python un'interfaccia è sempre solo commenti, perché è tipizzata in duck). Parlo ancora del codice come usando il modello, perché è un modo utile di pensarci, ma in realtà non digitare tutto il materiale fino a quando non ne ho davvero bisogno.

Quindi impara tutti gli schemi come concetti . E dimentica le implementazioni specifiche. L'implementazione varia e dovrebbe variare, nel mondo reale, anche solo in Java.


28
La tua dichiarazione di apertura si sta semplificando eccessivamente all'estremo. È vero che i modelli hanno il loro costo, quindi non dovrebbero essere usati alla cieca, solo per il gusto di farlo. Ma nel posto giusto, possono essere di grande aiuto. E sì, sono specifici della lingua - alcuni schemi non sono necessari in alcune lingue perché la lingua stessa supporta un approccio migliore. Ma questo è ancora abbastanza lontano dalla tua richiesta di apertura.
Péter Török,

2
Btw Visitor non è interamente sostituito da funzioni di ordine superiore: è una soluzione per implementare il doppio invio in un linguaggio che non lo supporta nativamente (come C # e C ++). (E dovrebbe davvero essere usato con molta parsimonia - lo considero uno dei modelli più arcani e costosi il cui uso è IMHO così difficile da giustificare che io stesso non l'ho mai usato fino ad ora.)
Péter Török

14
Bene, non hai mai bisogno di uno schema. Ciò di cui hai bisogno è risolvere un problema . Se non conosci alcun modello per questo, puoi ancora risolverlo, ci vorrà più pensiero e potresti trovare una soluzione che corrisponda a uno schema o uno che non lo fa. Conoscere gli schemi semplifica le cose.
Jan Hudec,

3
@Gerenuk: Sì, ma il punto è che gli schemi non sono specifici della lingua, sono per la tua testa. Spesso scopri che alcuni pattern sono realizzati molto più facilmente e usano diversi strumenti in Python, ma di solito esiste lo stesso concetto.
Jan Hudec,

4
@ PéterTörök: il visitatore non viene sostituito da nulla. Il punto è che lo stesso concetto potrebbe essere implementato usando strumenti diversi in casi diversi, ma lo considero ancora lo stesso modello.
Jan Hudec,

13

Il modello astratto di fabbrica non è necessario in un linguaggio tipicamente anatroccolo come Python, poiché è praticamente integrato nel linguaggio.


10
bene, hai ancora bisogno di diverse fabbriche. Non hai solo bisogno della definizione dell'interfaccia.
Stefano Borini,

1
Se hai una classe, hai già una fabbrica. Le classi sono oggetti di prima classe e possono essere passate ovunque e semplicemente chiamate per creare un oggetto (a differenza di Java). Non è necessario creare nient'altro. Se vuoi qualcosa che non sia il costruttore predefinito, crea un lambda / callable di qualche tipo che avvolga il costruttore in qualche modo.
spookylukey,

13

L'unico che viene in mente è il modello Singleton.

Poiché Python non ti obbliga a utilizzare le classi per tutto , puoi semplicemente utilizzare una struttura di dati globale. Quella struttura di dati globale potrebbe essere gestita da un'istanza, ma non è necessario controllare l'istanza di quella classe, è sufficiente creare l'istanza all'importazione e lasciarla in quella posizione.

Principalmente, i Singleton in Python vengono sostituiti con un modulo. I moduli in Python sono per loro natura Singletons; l'interprete python crea questi solo una volta.

Tutti gli altri pattern in Design Patters che ho usato in Python una volta o l'altra, e ne troverai esempi in tutta la libreria standard di Python e in Python stesso.


2
Non è in realtà un anti-pattern in questi giorni?
Den

16
Il Singleton è un antipasto . In tutte le lingue È stato creato per risolvere diversi problemi non correlati e non è una buona corrispondenza per entrambi (nota che anche Java ha membri statici, che esistono una volta per classe, quindi non hai bisogno di un'istanza per quello).
Jan Hudec,

1
E in Python non ci siamo mai preoccupati perché non c'è mai stato un problema da risolvere.
Martijn Pieters,

1
"Python non ti obbliga a usare oggetti per tutto" Non è vero. Non è solo odioso come in Java, ma in Python tutto è un oggetto. Anche il modulo è un oggetto.
vartec,

3
@Darthfett: sono ben consapevole di come lenfunziona; Guido ha fatto una scelta esplicita qui . Il mio punto è mostrare che Python non è un linguaggio OOP puro; è un linguaggio pragmatico. Mi piace così.
Martijn Pieters,

8

I modelli di progettazione sono per il programmatore, non per la lingua. I programmatori tendono ad usare schemi che li aiutano a capire il problema a portata di mano. Nessun modello di progettazione è strettamente necessario, ma può essere utile per semplificare ciò che stai cercando di fare.

Python, e in particolare la tipizzazione anatra, pone fine a molti schemi e pratiche comuni e molte delle restrizioni imposte da alcuni schemi (privacy, immutabilità, ecc.) Valgono solo nella misura in cui il programmatore si impegna a non romperle . Ma ancora, essi non funzionano finché il programmatore gioca insieme. Una porta è ancora una porta, anche se è incorniciata da muri immaginari.

Python è considerato un linguaggio "multi-paradigma"; puoi usare qualunque schema tu voglia. Questo è intenzionale. Fornisce gerarchie di classi complesse, ad esempio, anche se sono completamente inutili e un po 'artificiali. Ma per alcune persone quella particolare astrazione è utile. Non perché il problema lo richieda, ma perché lo fa il programmatore. Quindi eccoti.


Questo è certamente interessante. Quindi, quali schemi in particolare vuoi dire che potresti dimenticare, perché ci sono modi migliori in Python?
Gerenuk,

4

Il libro originale "Design Patterns" documentava e nominava alcuni idiomi comuni utili in linguaggi imperativi e orientati agli oggetti come C ++ e Smalltalk. Ma Smalltalk è un linguaggio tipizzato in modo dinamico, quindi non può essere strettamente questione di essere dinamico.

Tuttavia, la risposta alla tua domanda è ancora "sì": alcuni di questi schemi di progettazione saranno irrilevanti per i moderni linguaggi tipizzati dinamicamente. Più in generale, ci saranno diversi modelli di progettazione in diverse lingue, specialmente in diversi tipi di lingue.

Per ribadire: un "modello di progettazione" è semplicemente un nome per un linguaggio di programmazione: una soluzione comune a un problema riscontrato di frequente. Lingue diverse richiedono idiomi diversi, perché ciò che è un problema per una lingua può essere banale per un'altra. In questo senso, i modelli di progettazione tendono a evidenziare punti deboli nelle lingue a cui si applicano.

Quindi, potresti cercare altre caratteristiche che rendono più moderni i linguaggi dinamici (o quelli antichi come Lisp), rendendo irrilevanti alcuni di questi modelli di design classico.


1

I modelli di progettazione sono modi per risolvere problemi particolari. Se non si riscontra un problema, il motivo per risolverlo è inutile.

Le persone stanno cercando di adattare i modelli di progettazione ovunque come se fosse una buona pratica avere modelli di progettazione nel tuo progetto. È il contrario. Hai riscontrato un problema che può essere risolto con un modello di fabbrica? Freddo. Adattalo. Non cercare il tuo codice e cerca di trovare il posto giusto per implementare un singleton (o una fabbrica, una facciata o qualsiasi altra cosa ...).

Forse Python ha i suoi modelli di progettazione non disponibili per le persone Java e .NET (a causa della natura di questi linguaggi)?


1

Direi che i modelli dipendono sempre dalla lingua. Il fatto che la maggior parte dei pattern di Python assomiglino a quelli definiti in GoF è a causa dell'OOP di Python, che detto OOP non è come OOP (non esistono due lingue che definiscono gli oggetti e la loro manipolazione al 100%).

Quindi non c'è dubbio che alcuni pattern non saranno applicabili "così come sono", alcuni potrebbero non avere senso e ci sono alcuni pattern che potrebbero essere significativi solo per Python.

Per tornare esattamente alla tua domanda: i modelli sono necessari solo se ne hai bisogno . Non devi usarli se non ce n'è bisogno (come già detto da Jan Hudec).

Inoltre, ci sono molti più schemi di quelli menzionati in GoF. Vedi in Wikipedia altri schemi

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.