PDA

View Full Version : [Generico] Progettazione software - uso del pattern abstract factory


deadlyomen17
29-04-2010, 19:03
salve a tutti

apro questo topic per discutere di alcuni miei dubbi sull'uso del pattern abstract factory nel software che devo sviluppare

l'obiettivo è di creare un software robusto e soprattutto estendibile.

il software in questione (in linguaggio java) vuol essere una interfaccia grafica dell'ambiente netkit sviluppato dall'università Roma 3 (http://wiki.netkit.org), si tratta di un emulatore di reti molto utile soprattutto a fini didattici

la mia idea è quella di strutturare il software in due layer: la gui come layer esterno per l'interazione con l'utente e la rappresentazione grafica degli elementi in gioco (host, domini di collisione etc), e la logica (core) come livello più basso per la rappresentazione logica degli stessi

per la loro comunicazione avevo pensato ad una interfaccia, implementata nel core, usata dalla gui per delegare compiti e/o impartire comandi da effettuare a livello logico.

in effetti però questa scelta porterebbe diversi problemi
ad esempio la classe logica che implementerebbe l'interfaccia sarebbe estramente grossa
così mi è stato consigliato di adottare il pattern factory (http://it.wikipedia.org/wiki/Abstract_factory)

dopo aver un po studiato questo pattern, mi è venuto il dubbio che nel mio caso avrebbe poco senso, in quanto la fabbrica astratta sarebbe in realtà implementata da una unica fabbrica concreta, così come ogni prodotto astratto

nel mio caso infatti la fabbrica astratta avrebbe i seguenti metodi

AbstractFactory
+createHost() : AbstractHost
+createCollDom() : AbstractCollDom
+createLink() : AbstractLink

dove i vari AbstractHost etc sarebbero i miei prodotti astratti

quello che mi turba è il fatto che nella praticità del mio software, non avrò domini di collisione diversi creati da fabbriche diverse, così per gli altri prodotti.

le cose che potrebbero farmi pensare che questa sia una buona scelta sono che aumenterebbe l'estendibilità del software e manterrebbe realmente indipendenti dalle rispettive implementazioni i due livelli

spero possiate aiutarmi

se qualcosa è poco chiaro sarò pronto a specificarlo meglio, purtroppo è sempre difficile sintetizzare un problema in poche parole

PGI-Bis
29-04-2010, 20:56
Il problema non è quello, relativo, di aumentare l'estendibilità.

La scelta che fai è assoluta: permettere o non permettere l'estensione del programma senza accesso al codice sorgente.

Uno dovrebbe dire che la scelta sia scontata: potendo perchè limitarsi.

Il problema è che il limite è nel linguaggio.

Tutti i linguaggi in cui i generatori sono amorfi e statici (come Java, C++, C#, Scala, direi quasi tutti quelli staticamente tipati) hanno il problema dell'hard-link ovvero della coincidenza di più parti in un'unica definizione.

Detto altrimenti, tu hai i mente i due strati, vai via liscio col new e alla fine gli strati non sono due: sono uno solo, scritto in due sorgenti diversi.

A onor del vero la questione è risolta in Java con il class loading (è lì che il linguaggio diventa orientato agli oggetti) ma il loro uso è impropriamente considerato esoterico.

Dunque se vuoi i due strati (e non uno solo che fa finta di essere due) devi separare la loro istanziazione.

Puoi farlo con i classloader (cioè senza far niente ma presupponendo che eventuali terzi che avranno a che fare col tuo codice sappiano usare un classloader), con l'abstract factory, con un dependency injection framework (non basta la dependency injection, ci vuole anche un meccanismo di composizione esterna).

In ogni caso il problema non è "analogico" (tanto o poco estendibile, tanto o poco indipendente) ma "digitale": ho un layer o due layer, posso estendere il programma senza cambiare il suo codice sorgente o non posso farlo.

deadlyomen17
30-04-2010, 09:49
Il problema non è quello, relativo, di aumentare l'estendibilità.

La scelta che fai è assoluta: permettere o non permettere l'estensione del programma senza accesso al codice sorgente.

Uno dovrebbe dire che la scelta sia scontata: potendo perchè limitarsi.

Il problema è che il limite è nel linguaggio.

Tutti i linguaggi in cui i generatori sono amorfi e statici (come Java, C++, C#, Scala, direi quasi tutti quelli staticamente tipati) hanno il problema dell'hard-link ovvero della coincidenza di più parti in un'unica definizione.

Detto altrimenti, tu hai i mente i due strati, vai via liscio col new e alla fine gli strati non sono due: sono uno solo, scritto in due sorgenti diversi.

A onor del vero la questione è risolta in Java con il class loading (è lì che il linguaggio diventa orientato agli oggetti) ma il loro uso è impropriamente considerato esoterico.

Dunque se vuoi i due strati (e non uno solo che fa finta di essere due) devi separare la loro istanziazione.

Puoi farlo con i classloader (cioè senza far niente ma presupponendo che eventuali terzi che avranno a che fare col tuo codice sappiano usare un classloader), con l'abstract factory, con un dependency injection framework (non basta la dependency injection, ci vuole anche un meccanismo di composizione esterna).

In ogni caso il problema non è "analogico" (tanto o poco estendibile, tanto o poco indipendente) ma "digitale": ho un layer o due layer, posso estendere il programma senza cambiare il suo codice sorgente o non posso farlo.

ti ringrazio per la risposta

purtroppo sono molto giovane nella programmazione, e sono praticamente zero nella progettazione, quindi scusami se ti rivolgerò domande banali o stupide o addirittura a cui mi hai già risposto

spiego meglio cosa sto facendo
il software lo sto sviluppando in java, e i due layer, core e gui, possono anche essere due progetti java diversi; in cui in particolare la gui dipende dal core, mentre il core è indipendente (come se il core fosse una libreria che offre a chi la utilizza solo alcune interfacce che dichiarano una serie di metodi)
i vari costruttori degli oggetti core sono privati, e quindi a livello gui non esiste la possibilità di usare la keyword new per crearli.
per crearli ho pensato appunto ad una interfaccia che funge da factory, implementata nel core e disponibile alla gui, che restituisce interfacce di prodotti (Interface, Host, Link, CollisionDomain), che specificano i metodi utilizzabili all'esterno di questi oggetti (ad esempio i metodi setIp(..) e getIp() in Interface)

per estendibilità intendo più che altro (forse impropriamente) la possibilità che in futuro qualcun altro possa aggiungere funzionalità a questo software senza dover modificare radicalmente ciò che è stato già fatto, soprattutto la struttura, ma avendo comunque pieno accesso al codice (sarà software libero)
per questo non credo che ci sia il bisogno di ricorrere al class loading

PGI-Bis
30-04-2010, 17:21
L'intento è chiaro e l'abstract factory può essere usato per realizzarlo.

La mia risposta riguarda il dubbio:

"mi è venuto il dubbio che nel mio caso avrebbe poco senso, in quanto la fabbrica astratta sarebbe in realtà implementata da una unica fabbrica concreta, così come ogni prodotto astratto"

Non usi l'abstract factory per avere una molteplicità di factory. Usi l'abstract factory per collegare due parti di un programma senza che questo collegamento comporti l'inclusione di una parte nell'altra.

Questa mancata inclusione ha come effetto la possibilità di estendere il sistema (dove l'estendibilità è la possibilità di aggiungere o rimuovere funzioni senza modificare il codice preesistente).

Detto altrimenti, il punto qui non è dire "uso l'abstract factory perchè ho più factory, non uso l'abstract factory se ho una sola factory per tipo" ma è dire "uso l'abstract factory perchè voglio rendere autonome due parti del programma". Da quell'autonomia discendono alcune conseguenze di cui una è l'estedibilità.

Potresti non usare l'abstract factory: qualsiasi soluzione che ti permetta di separare core e gui va bene. Il fatto è che factory e abstract factory sono idee talmente generali che "più o meno" sempre lì arrivi.

deadlyomen17
30-04-2010, 19:03
L'intento è chiaro e l'abstract factory può essere usato per realizzarlo.

La mia risposta riguarda il dubbio:

"mi è venuto il dubbio che nel mio caso avrebbe poco senso, in quanto la fabbrica astratta sarebbe in realtà implementata da una unica fabbrica concreta, così come ogni prodotto astratto"

Non usi l'abstract factory per avere una molteplicità di factory. Usi l'abstract factory per collegare due parti di un programma senza che questo collegamento comporti l'inclusione di una parte nell'altra.

Questa mancata inclusione ha come effetto la possibilità di estendere il sistema (dove l'estendibilità è la possibilità di aggiungere o rimuovere funzioni senza modificare il codice preesistente).

Detto altrimenti, il punto qui non è dire "uso l'abstract factory perchè ho più factory, non uso l'abstract factory se ho una sola factory per tipo" ma è dire "uso l'abstract factory perchè voglio rendere autonome due parti del programma". Da quell'autonomia discendono alcune conseguenze di cui una è l'estedibilità.

Potresti non usare l'abstract factory: qualsiasi soluzione che ti permetta di separare core e gui va bene. Il fatto è che factory e abstract factory sono idee talmente generali che "più o meno" sempre lì arrivi.

a questo punto ho avuto la risposta al mio dubbio

ti ringrazio

Kenger
30-04-2010, 19:27
Entro a gamba tesa nel thread per chiedere se mi potete consigliare qualche buona lettura gratuita inglese o italiana sui pattern in generale. Grazie e spero mi perdonerà il thread-starter

deadlyomen17
30-04-2010, 20:59
Entro a gamba tesa nel thread per chiedere se mi potete consigliare qualche buona lettura gratuita inglese o italiana sui pattern in generale. Grazie e spero mi perdonerà il thread-starter

a parte ovviamente wikipedia, italiano e inglese, io sto leggendo anche questo: http://eii.ucv.cl/pers/guidi/designpatterns.htm una carrellata dei design pattern principali adattati al linguaggio java, con esempi dimostrativi

altre informazioni le ho trovate qui: http://www.shedidntcome.com/cavallorama/