Quanto sforzo dovrei investire nella creazione di progetti liberamente accoppiati?


10

Attualmente sto imparando sui modelli di progettazione.

Penso che la maggior parte delle persone concorderebbe sul fatto che questi schemi sono ottimi strumenti, ma dovrebbero essere usati con moderazione e non come risposta a tutto. Usarli troppo complicherebbe eccessivamente l'applicazione con pochi benefici. I pattern dovrebbero essere usati solo dove possono essere la migliore soluzione o aiuto nella creazione di una buona soluzione (sei d'accordo?).

Con questo in testa:

Il libro che sto leggendo (Head First Design Patterns) sottolinea spesso l'importanza dell'accoppiamento libero . Questo accoppiamento libero è realizzato seguendo i principi come "programma a un'interfaccia, non un'implementazione" e "incapsulare ciò che varia".

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

Comprendo l'importanza e i vantaggi dell'accoppiamento libero.

Ma la mia domanda è: quanti sforzi si dovrebbero effettivamente investire nella creazione di progetti liberamente accoppiati e flessibili?

Coloro che si oppongono ai modelli di progettazione affermano che i costi per l'utilizzo di questi modelli spesso superano i vantaggi. Investi molto tempo nella creazione di un progetto liberamente accoppiato usando un modello, in cui in realtà - l'accoppiamento lento, "la programmazione su un'interfaccia, non un'implementazione" e tutti questi principi - potrebbero non essere così importanti.

Quello che mi piacerebbe sapere è quanto sforzo dovrei effettivamente fare per creare livelli aggiuntivi di astrazione e progetti, solo per consentire alla mia applicazione di seguire i principi OO come accoppiamento libero, programmazione di un'interfaccia, ecc. Vale davvero la pena vero? Quanto sforzo dovrei fare in questo?


Alcune persone ci mettono tutta la vita, ad esempio Kent Beck, le persone che lo apprezzano vedrebbero i tuoi sforzi.
Niing

Risposte:


14

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

Fondamentalmente, la costruzione di codice liberamente accoppiato non è molto difficile. Al contrario, allenare la mente a pensare in termini di accoppiamento libero. E, beh, credo che ne valga la pena.

Supponiamo di assumere un lavoro che utilizza un approccio iterativo allo sviluppo del software, come è stato raccomandato da quasi tutti negli ultimi 20 anni. Si crea qualcosa che funziona magnificamente nell'iterazione 1. Nell'iterazione 2 ci si basa sopra, aggiungendo alcune nuove funzionalità e piegando un po 'una o due cose un po' quando non si adattano al concetto di iterazione 1 di come dovrebbero funzionare le cose . Ora arriva l'iterazione 3 e scopri i requisiti richiesti per ripensare la tua architettura di base. Come dividi il tuo codice e lo ricostruisci senza tornare al punto di partenza?

Questo succede. Un sacco. O fa ritardare i progetti 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 della responsabilità singola mitigano questi problemi in grande stile. Ecco perché i principi SOLID sono propagandati: aiutano davvero.

E scoprirai che dopo aver avuto alcuni disegni vagamente accoppiati sotto la cintura, inizia a venire naturalmente. I modelli sono cose che le persone hanno scoperto che hanno funzionato per loro, quindi le hanno documentate. Sono strumenti utili che arrivano naturalmente anche con il tempo.


5

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

La cosa da tenere a mente con schemi che aumentano la flessibilità è che costa un certo 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 non utilizzarlo mai. Se la flessibilità non viene mai flessa, potrebbe anche non esserci.

C'è una cosa che dovresti fare sempre (o il più vicino possibile ad esso): trasformare i singoli componenti del tuo software (oggetti per OOP, funzioni per programmazione funzionale o procedurale) in scatole nere. Una scatola nera è qualcosa di cui non conosciamo né ci preoccupiamo gli interni (implementazione).

Se non sappiamo o ci preoccupiamo di come funziona, allora non proveremo a usare nient'altro che l'interfaccia, quindi se l'implementazione cambia senza cambiare l'interfaccia, ciò conta solo all'interno della scatola nera - niente al di fuori di essa può essere influenzato. Inoltre, è più semplice pensare al programma, perché non è necessario tenere a mente ogni singolo dettaglio dell'intero programma. 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 di accoppiamento lento e programmazione di un'interfaccia. La mia più grande obiezione a loro è che sono presentati come una soluzione preconfezionata che non incoraggia a comprendere i principi alla base, ma piuttosto incoraggia la memorizzazione dei dettagli. Non consiglierò di non studiarli, ma quando lo fai, ricorda che comprendere i principi alla base di essi è più importante dei dettagli di ogni particolare schema.

Una delle obiezioni ai modelli progettuali è che sono "ovvi" o che "li stavo usando prima di averne sentito parlare, ma non con quel nome". Il motivo per cui le persone possono sollevare queste obiezioni, o che i creatori dei modelli di progettazione potrebbero presentarsi in primo luogo, è che hanno capito i principi alla base.

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


4

La tua domanda sembra equiparare l'accoppiamento libero con i modelli di progettazione, ma sono cose separate, ma correlate.

L'accoppiamento lento è una preoccupazione fondamentale nella programmazione. Non appena ci siamo allontanati dal codice macchina e nei linguaggi simbolici, i programmi sono diventati vagamente accoppiati alla loro esecuzione. Eccetera.

OO stesso è fondamentalmente un modello per la creazione di componenti liberamente accoppiati. L'incapsulamento rende gli interni degli oggetti liberamente accoppiati con altri oggetti. La programmazione funzionale forse lo è ancora di più, poiché l'esecuzione della funzione è liberamente associata all'esecuzione di altre funzioni all'estremo.

Quasi per definizione, qualsiasi progetto tu faccia implicherà un accoppiamento libero. Ci sono modi in cui puoi organizzare che le cose siano strettamente accoppiate inavvertitamente, ma ho visto solo alcuni casi in cui qualcuno ha effettivamente progettato un sistema per essere accoppiato più strettamente.

(Ogni tanto lavoro con qualcuno che vuole impedire ai futuri sviluppatori di fare scelte progettuali incorporando riferimenti statici a particolari artefatti del framework, forzandone l'uso - di proposito. Ma questa è davvero l'eccezione. La maggior parte del design ruota attorno alla rottura delle cose per la modularità e riutilizzare in molti contesti.)


3

I pattern dovrebbero essere usati solo dove possono essere la migliore soluzione o aiuto nella creazione di una buona soluzione (sei d'accordo?).

Vedo i modelli di progettazione rigorosamente come dettagli di implementazione. Se documentate le vostre API pubbliche e programmate tale documentazione, in generale non importa (o vi influenzerà molto) dove avete modelli di progettazione. Cioè, non vai "Ho un modello di ponte qui e implementerò un visitatore sopra di esso". Invece, è "questa classe avrà implementazioni diverse su vari sistemi operativi, quindi sarà implementata usando un modello a ponte". Quindi, quando lo usi, sei indifferente al fatto che sia implementato come un bridge, perché guardi l'API pubblica, non un modello di bridge.

quanti sforzi si dovrebbero effettivamente investire nella creazione di progetti flessibili e debolmente accoppiati?

L'accoppiamento allentato può essere ottenuto seguendo una semplice serie di regole. Se li rispetti, il tuo codice sarà (più) liberamente accoppiato, mentre lo scrivi (ovvero ogni sforzo è già parte del processo di sviluppo).

Tra le regole (non un elenco esaustivo):

  • definisci le tue interfacce pensando (o scrivendo) al codice client (come verrà usata la classe), non a ciò che farà la classe (cioè progettando l'interfaccia, non l'implementazione)
  • "dì, non chiedere"
  • costruire oggetti da parti già create
  • passa al costruttore gli oggetti reali che utilizzerai (non le fabbriche per i membri, i parametri per le fabbriche dei parametri o qualcosa del genere).
  • ASCIUTTO (se hai due linee 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, implementare la creazione delle parti intermedie come metodo / classe di fabbrica (cioè non nel corpo del costruttore).
  • YAGNI (crea le cose di cui hai bisogno, non prima).

Queste regole vengono seguite in modo diverso, a seconda della lingua, della metodologia di sviluppo seguita dal team (ad esempio TDD), dei limiti di budget di tempo e così via.

Ad esempio, in Java, è buona norma definire l'interfaccia come un interfacee scrivere codice client su quello (quindi, istanziare l'interfaccia con una classe di implementazione).

D'altra parte, in C ++ non hai interfacce, quindi puoi solo scrivere l'interfaccia come una classe base astratta; Dato che in C ++ usi l'ereditarietà solo quando hai un forte requisito (e come tale evita il sovraccarico di funzioni virtuali non necessarie), probabilmente non definirai l'interfaccia separatamente, solo l'intestazione della classe).

Coloro che si oppongono ai modelli di progettazione affermano che i costi per l'utilizzo di questi modelli spesso superano i vantaggi.

Penso che stiano sbagliando. Se si scrive codice debolmente accoppiato (e DRY), l'integrazione dei modelli di progettazione in esso viene fornita con il minimo sforzo aggiuntivo. Altrimenti, dovrai adattare il tuo codice per implementare un modello di progettazione.

Se devi implementare molte modifiche per implementare un modello di progettazione, il tuo problema non è il modello di progettazione: è la tua base di codice che è monolitica e strettamente accoppiata. Questo è un problema di progettazione non ottimale / non ottimale, non un problema di modelli di progettazione.

Quello che mi piacerebbe sapere è quanto sforzo dovrei effettivamente fare per creare livelli aggiuntivi di astrazione e progetti, solo per consentire alla mia applicazione di seguire i principi OO come accoppiamento libero, programmazione di un'interfaccia, ecc. Vale davvero la pena vero? Quanto sforzo dovrei fare in questo?

Le tue domande danno per scontato (non dichiarato) che l'unico vantaggio dell'accoppiamento libero sia la capacità di implementare facilmente i modelli di progettazione. Non è.

Tra i vantaggi dell'accoppiamento libero ci sono:

  • refactoring e riprogettazione della flessibilità
  • sforzo meno sprecato
  • testabilità
  • maggiore possibilità di riutilizzo del codice
  • semplicità progettuale
  • meno tempo trascorso nel debugger

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

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.