Quanto impegno dovrei investire nella creazione di design liberamente accoppiati?

9

Attualmente sto imparando a conoscere i modelli di design.

Penso che la maggior parte delle persone sarebbe d'accordo sul fatto che questi modelli siano strumenti eccezionali, ma dovrebbero essere usati con moderazione e non come risposta a tutto. Usarli troppo complicherebbe eccessivamente l'applicazione con poco beneficio. I pattern dovrebbero essere usati solo dove possono essere la soluzione migliore o aiutare nella creazione di una buona soluzione (siete d'accordo?).

Con questo in mente:

Il libro che sto leggendo (Head First Design Patterns) sottolinea spesso l'importanza di loose coupling . Questo accoppiamento libero viene perseguito seguendo principi come "programma su un'interfaccia, non un'implementazione" e "incapsula ciò che varia".

Fondamentalmente, la maggior parte dei pattern che ho imparato finora esistono principalmente per consentire ai progetti di essere accoppiati liberamente e quindi più flessibili.

Comprendo l'importanza e i vantaggi di un accoppiamento lento.

Ma la mia domanda è, quanto sforzo si dovrebbe effettivamente investire nella creazione di design flessibili e accoppiati?

Chi si oppone ai modelli di progettazione afferma che i costi per l'utilizzo di questi modelli superano spesso i benefici. Investisci molto tempo nella creazione di un design liberamente accoppiato usando un modello, dove in realtà - l'accoppiamento lento, "la programmazione di un'interfaccia, non un'implementazione", e tutti questi principi - potrebbero non essere effettivamente così importanti .

Quello che mi piacerebbe sapere, è quanto impegno dovrei effettivamente mettere nella creazione di ulteriori livelli di astrazione e design, solo per consentire alla mia applicazione di seguire i principi OO come l'accoppiamento libero, il programmign su un'interfaccia, ecc. ne vale davvero la pena? Quanto sforzo dovrei inserire in questo?

    
posta Aviv Cohn 20.03.2014 - 00:09
fonte

4 risposte

13

Risposta fasulla: più lo fai, meno lo sforzo è.

Fondamentalmente, la costruzione di un codice liberamente accoppiato non è davvero molto difficile. Allenare la tua mente a pensare in termini di accoppiamento lento, d'altra parte, lo è. E, beh, credo che ne varrà la pena.

Supponiamo che tu prenda un lavoro che usa un approccio iterativo allo sviluppo del software, come è stato raccomandato dalla maggior parte di tutti negli ultimi 20 anni. Costruisci qualcosa che funzioni magnificamente in iterazione 1. In iterazione 2 ti costruisci sopra, aggiungendo alcune nuove funzionalità e un po 'piegando un paio di cose un po' quando non rientrano nella tua iterazione 1 concetto di come le cose dovrebbero funzionare . Ora arriva l'iterazione 3 e scopri che i requisiti richiedono un ripensamento della tua architettura di base. Come fai a strappare il tuo codice e ricostruirlo senza tornare al punto di partenza?

Questo succede. Un sacco. Rende i progetti in ritardo o rende tutti troppo spaventati per fare ciò che deve essere fatto nelle iterazioni successive. Nel migliore dei casi, ottieni una Big Ball of Mud. Cose come l'accoppiamento lento e il principio di responsabilità unica mitigano questi problemi in modo significativo. Ecco perché i principi SOLIDI sono propagandati - aiutano davvero.

E scoprirai che, dopo aver indossato un paio di disegni sciolti sotto la cintura, inizia a venire naturalmente. I pattern sono cose che le persone hanno trovato che hanno funzionato per loro, quindi le hanno documentate. Sono strumenti utili che vengono anche naturalmente con il tempo.

    
risposta data 20.03.2014 - 01:31
fonte
5

La quantità di sforzi richiesti non ti dirà mai abbastanza; Penso che una misura migliore sarebbe lo sforzo per il rapporto di pagamento. Ma capire quale potrebbe essere la ricompensa non è sempre semplice e privo di errori.

La cosa da tenere a mente con i modelli che aumentano la flessibilità è che costa qualche sforzo per inserirli e, a meno che tu non riesca a vedere esattamente perché ne hai bisogno, potresti finire per avere la complicazione nel codice, ma mai e poi mai usandolo. Se la flessibilità non è mai flessa, potrebbe anche non esserci.

C'è una cosa che dovresti fare sempre (o vicino a ciò che puoi ragionevolmente ottenere): rendere i singoli componenti del tuo software (oggetti per OOP, funzioni per la programmazione funzionale o procedurale) in scatole nere. Una scatola nera è qualcosa il cui interno (implementazione) non conosciamo o non ci interessa.

Se non sappiamo o non ci interessa come funziona, allora non tenteremo di usare altro che l'interfaccia, quindi se l'implementazione cambia senza cambiare l'interfaccia, ciò conta solo all'interno della scatola nera - nulla al di fuori può essere influenzato. Rende anche più facile pensare al programma, perché non devi tenere tutti i dettagli dell'intero programma nella tua testa. Più dettagli puoi legittimamente dimenticare, più spazio c'è nella tua testa per i dettagli che contano.

Penso che tu abbia frainteso le obiezioni ai modelli di progettazione; Non ne sono un fan, ma mi piace molto il principio dell'accoppiamento lento e della programmazione dell'interfaccia. La mia più strong obiezione a loro è che sono presentati come una soluzione preconfezionata che non incoraggia la comprensione dei principi che stanno dietro di loro, ma piuttosto incoraggia la memorizzazione dei dettagli. Non ho intenzione di raccomandare che non li studi, ma quando lo fai, ricorda che capire i principi che stanno dietro di loro è più importante delle specifiche di un particolare modello.

Una delle obiezioni ai modelli di progettazione è che sono "ovvi" o che "li stavo usando prima di averne sentito parlare, ma non con quel nome". La ragione per cui le persone possono fare quelle obiezioni, o gli ideatori dei modelli di progettazione, potrebbe in primo luogo farle emergere, è che hanno compreso i principi dietro di loro.

L'uso di scatole nere organizza il codice in modo sano e generalmente non costa molto (se non altro); usali ovunque Usare un modello di progettazione o qualche altra tecnica che aggiunge uno strato di astrazione o complica le cose ha un costo; non usarli mai solo perché sono belli o puliti o intelligenti; usali quando si adattano al problema e il costo vale la pena pagare per ottenere il beneficio.

    
risposta data 20.03.2014 - 05:14
fonte
4

La tua domanda sembra equiparare l'allentamento dell'accoppiamento con Design Patterns, ma sono cose molto separate, ma correlate.

L'accoppiamento lento è una preoccupazione fondamentale nella programmazione. Non appena ci siamo spostati dal codice della macchina e in linguaggi simbolici, i programmi sono stati associati liberamente alla loro esecuzione. Ecc.

OO stesso è fondamentalmente un modello per la creazione di componenti liberamente accoppiati. L'incapsulamento rende l'interno degli oggetti liberamente accoppiato ad altri oggetti. La programmazione funzionale forse lo è ancora di più, perché l'esecuzione della funzione è strettamente connessa con l'esecuzione di altre funzioni in modo estremo.

Quasi per definizione, qualsiasi progetto che fai coinvolgerà l'accoppiamento lento. Ci sono modi in cui puoi sistemare le cose in modo accoppiato inavvertitamente, ma ho visto solo alcuni casi in cui qualcuno ha effettivamente progettato un sistema per più strettamente accoppiato.

(Ogni tanto lavoro con qualcuno che vuole impedire ai futuri sviluppatori di fare scelte di progettazione incorporando riferimenti statici a particolari artefatti del framework, forzandone l'utilizzo, apposta, ma è davvero un'eccezione. per modularità e riutilizzo in molti contesti.)

    
risposta data 20.03.2014 - 09:44
fonte
3

Patterns should be used only where they can be the best solution or help in the creation of a good solution (do you agree?).

Vedo i modelli di progettazione rigorosamente come dettagli di implementazione. Se si documentano le API pubbliche e il programma su tale documentazione, in generale non importa (o si influisce molto su di voi) in cui si hanno schemi di progettazione. Cioè, tu non vai "Ho un modello di bridge qui, e attuerò un visitatore su di esso". Invece, "questa classe avrà implementazioni differenti su vari sistemi operativi, quindi verrà implementata usando un modello di bridge". Quindi, quando lo si utilizza, si è indifferenti al fatto che venga implementato come bridge - perché si guarda l'API pubblica, non un pattern di bridge.

how much effort should one actually invest in creating loosely coupled, flexible designs?

È possibile ottenere un accoppiamento lento seguendo una semplice serie di regole. Se li rispettate, il vostro codice sarà (più) liberamente accoppiato, come lo scrivete (cioè ogni sforzo è già parte del processo di sviluppo).

Tra le regole (non una lista esaustiva):

  • definisce le tue interfacce pensando (o scrivendo) al codice client (come verrà usata la classe), non a quello che farà la classe (cioè, desing per l'interfaccia, non implementazione)
  • "racconta, non chiedere"
  • costruisci oggetti da parti già create
  • passare nel costruttore gli oggetti reali che userai (non le fabbriche per i membri, i parametri per le fabbriche dei parametri, o qualcosa del genere).
  • DRY (se hai due righe che appaiono nello stesso ordine in due punti, estraile in una funzione separata e così via).
  • Se la creazione di un oggetto è un'operazione più complessa, implementa la creazione delle parti intermedie come metodo / classe di fabbrica (cioè non nel corpo del costruttore).
  • YAGNI (crea le cose quando ne hai bisogno, non prima)

Queste regole sono seguite in modo diverso, a seconda della lingua, della metodologia di sviluppo seguita dal tuo team (ad es. TDD), dei vincoli di budget e così via.

Ad esempio, in Java, è buona norma definire la tua interfaccia come interface e scrivere su tale codice client (quindi creare un'istanza dell'interfaccia con una classe di implementazione).

In C ++, d'altra parte, non hai interfacce, quindi puoi solo scrivere l'interfaccia come una classe base astratta; Poiché in C ++ si utilizza l'ereditarietà solo quando si ha un strong requisito per esso (e come tale si evita il sovraccarico di funzioni virtuali non necessarie), probabilmente non si definirà l'interfaccia separatamente, ma solo l'intestazione della classe).

Those who oppose design patterns say that the costs to using these patterns often outweighs the benefits.

Penso che stiano sbagliando. Se si scrive codice liberamente accoppiato (e ASCIUTTO), l'integrazione di schemi di progettazione in esso comporta uno sforzo minimo supplementare. Altrimenti, dovrai adattare il tuo codice per implementare un modello di design.

Se devi fare molte modifiche per implementare un modello di progettazione, il tuo problema è non il modello di progettazione - è il tuo codice base monolitico e strettamente accoppiato. Questo è un problema di progettazione non corretto / non ottimale, non un problema di progettazione.

What I'd like to know, is how much effort should I actually put in creating additional levels of abstraction and designs, only to allow my application to follow OO principles such as loose coupling, programmign to an interface, etc. Is it really worth it? How much effort should I put in this?

Le tue domande fanno presupposto (non dichiarato) che l'unico vantaggio di un accoppiamento libero è la capacità di implementare facilmente modelli di progettazione. Non lo è.

Tra i vantaggi di un accoppiamento libero ci sono:

  • refactoring e riprogettazione della flessibilità
  • meno sforzi inutili
  • testability
  • maggiore possibilità di riutilizzare il codice
  • semplicità del design
  • meno tempo trascorso nel debugger

... e alcuni altri che non mi vengono in mente in questo momento.

    
risposta data 20.03.2014 - 12:59
fonte

Leggi altre domande sui tag