NOME

perlmodstyle - Guida alla scrittura con stile di moduli Perl

INTRODUZIONE

Questo documento contiene un tentativo di fornire delle linee guida della comunità Perl per scrivere moduli. Estende le raccomandazioni che si trovano in perlstyle, che è da considerarsi propedeutico alla lettura di questo documento.

Sebbene questo documento sia destinato ad ogni autore di moduli, esso è dedicato particolarmente a quegli autori che desiderino pubblicare i loro moduli su CPAN.

L'attenzione è posta più su elementi di stile che sono visibili agli utenti di un modulo, che su quelle parti che sono visibili esclusivamente dagli sviluppatori del modulo. Ad ogni modo, molte delle linee guida presentate in questo documento possono essere estrapolate e applicate con successo al codice interno di un modulo.

Questo documento differisce da perlnewmod in quanto contiene consigli di stile piuttosto che una guida introduttiva alla creazione di moduli CPAN. Contiene una lista di requisiti da verificare affinché i moduli siano conformi alla miglior pratica, senza necessariamente descrivere in dettaglio il metodo per ottenere ciò.

Tutti i consigli contenuti in questo documento sono stati racimolati da lunghe conversazioni con esperti autori CPAN e utenti. Ogni consiglio che troverete è il risultato di precedenti errori. Queste informazioni sono qui raccolte per aiutarvi ad evitare di ripetere gli stessi errori ed il lavoro aggiuntivo che sarebbe inevitabilmente necessario per aggiustarli.

La prima parte di questo documento fornisce una lista di verifica da consultare punto per punto; le parti successive forniscono una descrizione più dettagliata degli oggetti inclusi nella lista. La parte finale, "I tranelli più comuni", descrive alcuni dei più comuni errori commessi dagli autori CPAN.

RAPIDA LISTA DI VERIFICA

Per i dettagli a proposito delle singole voci in questo elenco, si veda sotto.

Prima di iniziare

  • Non reinventate la ruota

  • Correggete, estendete o fornite una sottoclasse per un modulo esistente quando ciò è possibile

  • Fate una cosa e fatela bene

  • Scegliete un nome appropriato

Le API

  • Le API dovrebbero essere comprensibili da un programmatore di medie capacità

  • Metodi semplici per compiti semplici

  • Separate le funzionalità dall'output

  • Date nomi consistenti a subroutine e metodi

  • Date dei nomi ai parametri (in hash o hashref [riferimenti ad hash, NdT]) quando ci sono più di due parametri

Stabilità

  • Assicuratevi che il vostro modulo funzioni con use strict e -w

  • Moduli stabili dovrebbero garantire la compatibilità all'indietro

Documentazione

  • Scrivete la documentazione in POD

  • Documentate lo scopo, l'ambito e le destinazioni d'uso.

  • Documentate ogni metodo o subroutine pubblicamente accessibile, compresi parametri e valori restituiti

  • Fornite degli esempi di utilizzo nella vostra documentazione

  • Fornite un file README [LEGGIMI, NdT] e possibilmente anche note di realizzazione, changelog [registro dei cambiamenti, NdT], ecc

  • Fornite dei link per ulteriori informazioni (URL, email)

Considerazioni sulla distribuzione

  • Specificate i prerequisiti nel Makefile.PL o nel Build.PL

  • Specificate i requisiti della versione del Perl con use

  • Includete dei test nel vostro modulo

  • Utilizzate uno schema di numerazione per le versioni sensato e consistente (X.YY è l'usuale schema di numerazione dei moduli Perl)

  • Incrementate il numero di versione per ogni cambiamento, non importa quanto sia piccolo

  • Preparate il modulo per la distribuzione utilizzando "make dist"

  • Scegliete una licenza appropriata (GPL/Artistic è una buona scelta di default)

PRIMA DI INIZIARE A SCRIVERE UN MODULO

Provate a non buttarvi a capofitto nello sviluppo del vostro modulo senza aver speso un po' di tempo in precedenza a pensarci su. Un minimo di precauzione può evitarvi un sacco di lavoro in seguito.

È già stato fatto in precedenza?

Potreste anche non aver bisogno di scrivere un modulo. Controllate che non sia già stato fatto in Perl ed evitate di reinventare la ruota a meno che non abbiate una buona ragione per farlo.

Buoni punti di partenza per cercare moduli già esistenti includono http://search.cpan.org/ e la lista modules@perl.org

Se un modulo già esistente fa quasi quello che volete, prendete in considerazione la possibilità di scrivere voi stessi una patch, una sottoclasse, o una estensione per il modulo esistente anziché riscriverlo.

Fate una cosa e fatela bene

A rischio di dichiarare ovvietà, i moduli sono fatti per essere modulari. Uno sviluppatore Perl dovrebbe essere in grado di utilizzare moduli come componenti per costruire la propria applicazione. Ad ogni modo, è importante che i componenti siano della forma giusta, e che lo sviluppatore non debba usare un componente grande quando ne basta uno piccolo.

Il vostro modulo dovrebbe avere uno scopo chiaramente definito, descrivibile da non più di una semplice frase. È possibile scomporre il vostro modulo in un gruppo di moduli correlati?

Cattivo esempio:

"PippoPluto.pm provvede a implementare il protocollo PIPPO e lo standard correlato PLUTO."

Buon esempio:

"Pippo.pm provvede a implementare il protocollo PIPPO. Pluto.pm implementa lo standard correlato PLUTO."

Ciò significa che se uno sviluppatore necessita solamente di un modulo per lo standard PLUTO, non dovrebbe essere obbligato a installare ulteriori librerie per PIPPO.

Di cosa è composto un nome?

Assicuratevi di scegliere in anticipo un nome appropriato per il vostro modulo. Questo sarà utile per trovare e ricordare il vostro modulo, e renderà più intuitivo programmarci.

Quando date un nome al vostro modulo, prendete in considerazione i seguenti accorgimenti:

  • Siate descrittivi (cioè descrivete accuratamente le finalità del modulo).

  • Verificate la consistenza con moduli già esistenti.

  • Descrivete le funzionalità del modulo, non l'implementazione.

  • Evitate di iniziare una nuova gerarchia dal livello più alto, specialmente se è già presente una gerarchia apposita sotto la quale potreste inserire il vostro modulo.

Dovreste contattare modules@perl.org per chiedere opinioni sul nome del vostro modulo prima di renderlo pubblico. Dovreste inoltre provare a chiedere consiglio a chi ha già familiarità con il dominio delle applicazioni del modulo e con il sistema dei nomi di CPAN. Gli autori di moduli simili o moduli con nomi simili potrebbero essere un buon punto di partenza.

PROGETTARE E SCRIVERE IL VOSTRO MODULO

Considerazioni per la progettazione e la stesura di moduli:

OO o non OO?

Il vostro modulo può essere orientato agli oggetti (OO) oppure no, o può disporre di entrambi i tipi di interfacce. Ci sono pro e contro per le due tecniche, che devono essere presi in considerazione quando progettate le vostre API.

È opinione di Damian Conway [autore di "Object Oriented Perl", NdT] che l'utilizzo di Perl OO debba essere preso in considerazione:

  • Quando il sistema è di grandi dimensioni o è probabile che lo diventi

  • Quando i dati sono aggregati in strutture distinte che diventeranno oggetti

  • Quando i tipi dei dati formano una gererchia naturale che può trarre beneficio dal concetto di ereditarietà

  • Quando le operazioni sui dati variano a seconda del tipo dei dati (rendendo praticabile la chiamata polimorfica di metodi)

  • Quando è plausibile che nuovi tipi di dato siano introdotti in seguito nel sistema e dovranno essere manipolati da codice esistente

  • Quando interazioni tra dati sono meglio rappresentati da operatori in overload

  • Quando l'implementazione dei componenti del sistema è suscettibile di cambiamento nel tempo (e di conseguenza dovrebbe essere incapsulata)

  • Quando il progetto del sistema è di per sé orientato agli oggetti

  • Quando il software verrà utilizzato da una parte considerevole del codice utente. (e l'incapsulazione sarà utile per cambiamenti nell'implementazione)

  • Quando molte operazioni distinte dovranno essere compiute sullo stesso insieme di dati.

Valutate con attenzione se lo stile OO è appropriato per il vostro modulo. Programmazione OO gratuita genera API complesse che sono difficili da capire o utilizzare per il programmatore di medie capacità.

Progettare le vostre API

Le vostre interfacce dovrebbero essere comprensibili per un programmatore di medie capacità. Le seguenti linee guida possono aiutarvi a giudicare se le vostre API sono sufficientemente chiare:

Scrivete routine semplici che fanno cose semplici.

È meglio scrivere molte routine semplici che poche monolitiche. Se la vostra routine si comporta in maniera significativamente diversa a seconda dei suoi parametri, è un segno che dovreste avere due (o più) routine separate.

Separate le funzionalità dall'output.

Restituite i dati in output nella forma più generica possibile e permettete all'utente di scegliere come utilizzarli. La forma più generica possibile è di solito una struttura dati del Perl che può essere usata per generare un report testuale, HTML, XML, una query per database, o qualsiasi altra cosa di cui i vostri utenti abbiano bisogno.

Se la vostra routine esegue una iterazione attraverso un certo tipo di lista (tipo una lista di file, o record di un database) potreste prendere in considerazione di fornire una "callback" [richiamo, NdT] in modo tale che l'utilizzatore possa manipolare a turno ogni elemento della lista. File::Find ne fornisce un esempio con la sintassi find(\&wanted, $dir).

Fornite scorciatoie e valori di default sensati.

Non costringete ogni utilizzatore del modulo a fare le stesse acrobazie per raggiungere risultati semplici. Potete sempre includere dei parametri opzionali o routine per i comportamenti più complessi oppure non standard. Se la maggior parte degli utilizzatori devono digitare le stesse poche identiche linee di codice quando iniziano ad utilizzare il vostro modulo, è segno che avreste dovuto considerare quel particolare comportamento come default. Un altro buon indicatore del fatto che dobbiate utilizzare comportamenti di default è quando la maggior parte dei vostri utenti invocano le vostre routine con gli stessi parametri.

Convenzioni per i nomi

Dovreste dare nomi in maniera consistente. Per esempio, è meglio avere:

mostra_giorno();
mostra_settimana();
mostra_anno();

che

mostra_giorno();
settimana_mostra();
visualizza_anno();

Questo vale parimenti per nomi di metodi, parametri, e qualsiasi altra cosa che sia visibile all'utilizzatore (e molte cose che non lo sono!).

Passaggio dei parametri

Utilizzate parametri con nome. È più facile utilizzare un hash come questo:

    $oggetto->fai_qualcosa(
	    nome => "ciccio",
	    tipo => "testo",
	    dimensioni => 1024,
    );

... che avere una lunga lista di parametri senza nome come questo:

$oggetto->fai_qualcosa("ciccio", "testo", 1024);

Sebbene la lista di parametri funzioni bene per uno, due o anche tre parametri, più parametri sono difficili da ricordare per l'utilizzatore del modulo e ardui per la gestione da parte dell'autore dello stesso. Se volete aggiungere un nuovo parametro, dovrete aggiungerlo alla fine della lista per retrocompatibilità, e questo probabilmente renderà non intuitivo l'ordinamento della lista. In più, se diversi elementi possono essere indefiniti potreste imbattervi nella seguente poco attraente invocazione di metodo:

$oggetto->fai_qualcosa(undef, undef, undef, undef, undef, undef, 1024);

Fornite valori di default sensati per quei parametri che possono averne. Non forzate l'utente a specificare parametri che avranno quasi sempre lo stesso valore.

Il discorso sul passare gli argomenti in un hash o in un riferimento ad un hash è in definitiva una questione di gusti.

L'utilizzo di chiavi di hash che iniziano con un trattino (-name) o completamente maiuscole (NAME) è una reliquia di vecchie versioni del Perl nelle quali delle normali stringhe di caratteri minuscoli non erano gestite correttamente dall'operatore =>. Sebbene alcuni moduli conservino il maiuscolo o il trattino per ragioni storiche o per ragioni di gusti personali, la maggior parte dei nuovi moduli dovrebbero utilizzare semplici chiavi minuscole. Qualsiasi cosa scegliate, siate consistenti!

Strict e messaggi di warning

Il vostro modulo dovrebbe funzionare con successo con la direttiva strict e senza generare alcun messaggio di warning. Il vostro modulo dovrebbe inoltre gestire il controllo di dati potenzialmente dannosi (taint-checking) quando ciò è appropriato, sebbene ciò possa causare difficoltà in molti casi.

Retrocompatibilità

Moduli "stabili" non dovrebbero interrompere la retrocompatibilità senza che passi almeno una lunga fase di transizione e un cambiamento di primaria importanza nel numero di versione.

Gestione degli errori e messaggi

Quando il vostro modulo si imbatte in un errore dovrebbe fare una o più cose delle seguenti:

  • Restituire un valore indefinito.

  • Impostare $Modulo::errstr o simili (errstr è un nome comune utilizzato da DBI e da altri moduli usati di frequente; se scegliete qualcos'altro, assicuratevi di documentarlo chiaramente).

  • Utilizzate warn() o carp() per inviare messaggi su STDERR.

  • Utilizzate croak() solamente quando il vostro modulo non può in alcun modo gestire la situazione. (croak() è una versione migliore di die() per l'utilizzo all'interno di moduli, che riporta i suoi errori dal punto di vista del chiamante. Si veda Carp per dettagli su croak(), carp() e altre utili routine).

  • In alternativa a quanto detto sopra, potreste preferire di lanciare eccezioni utilizzando il modulo Error.

Una gestione dell'errore configuarbile può essere molto utile per gli utenti. Si prenda in considerazione di offrire una scelta per i livelli di warning e messaggi di debug, un'opzione per spedire messaggi a un file esterno, un modo per specificare una routine di gesione di errore, o altre caratteristiche simili. Per queste opzioni, siate sicuri di garantire comportamenti di default legati agli utilizzi più frequenti.

DOCUMENTARE IL VOSTRO MODULO

POD

Il vostro modulo dovrebbe includere della documentazione destinata agli sviluppatori Perl. Dovreste utilizzare la "plain old documentation" (POD) [semplice vecchia documentazione, NdT] per la vostra documentazione tecnica generale, sebbene potreste voler scrivere documentazione aggiuntiva (white papers [libri bianchi, NdT], guide introduttive, ecc) in qualche altro formato. Dovrete includere i seguenti argomenti:

  • Una sinossi degli utilizzi comuni del modulo

  • Lo scopo, l'ambito e le destinazioni d'uso del vostro modulo.

  • L'utilizzo di ogni metodo o subroutine pubblicamente accessibile, compresi parametri e valori restituiti

  • Esempi di utilizzo

  • Fonti per ulteriori informazioni

  • Un indirizzo di posta elettronica per l'autore/curatore

Il livello di dettaglio nella documentazione dei moduli Perl va da meno dettagliata a più dettagliata. La vostra sezione SINOSSI dovrebbe contenere un esempio di utilizzo minimale (forse così piccolo da consistere di una sola linea di codice; tralasciate i casi di utilizzo non comuni o qualsiasi cosa che non sia necessaria per la maggior parte degli utenti); La sezione DESCRIZIONE dovrebbe descrivere il vostro modulo a grandi linee, di solito in pochi paragrafi; maggior dettaglio sui metodi e sulle routine del modulo, lunghi esempi di codice, o altro materiale approfondito dovrebbero essere localizzati in sezioni seguenti. Idealmente, coloro che hanno un po' di familiarità con il vostro modulo dovrebbero essere in grado di rinfrescarsi la memoria senza muovere la pagina in basso. Il vostro lettore, proseguendo con la lettura del documento, dovrebbe carpire una progressivamente maggior quantità di informazione.

L'ordinamento consigliato per le sezioni per la documentazione di un modulo Perl è il seguente:

  • NAME

    [NOME, NdT]

  • SYNOPSIS

    [SINOSSI, NdT]

  • DESCRIPTION

    [DESCRIZIONE, NdT]

  • Una o più sezioni o sottosezioni che forniscano ampi dettagli sui metodi o subroutine pubblicamente accessibili, e su ogni altra informazione rilevante.

  • BUGS/CAVEATS/etc

    [BUG/CAVEAT-AVVERTENZE/ecc, NdT]

  • AUTHOR

    [AUTORE, NdT]

  • SEE ALSO

    [SI VEDA ANCHE, NdT]

  • COPYRIGHT and LICENSE

    [COPYRIGHT e LICENZA, NdT]

Mettete la vostra documentazione vicino al codice che essa va a documentare (documentazione "inline"). Includete la documentazione POD per un dato metodo subito sopra alla subroutine del metodo. Ciò rende più semplice mantenere la documentazione aggiornata, e vi evita di dover documentare ogni porzione di codice due volte (una volta nel POD e una volta nei commenti).

README, INSTALL [INSTALLAZIONE, NdT], note di realizzazione, changelog

Il vostro modulo dovrebbe inoltre includere un file README che descriva il modulo e contenga riferimenti a ulteriori informazioni (sito web, indirizzo di posta elettronica dell'autore). Dovrebbe essere incluso un file INSTALL, e dovrebbe contenere semplici istruzioni per l'installazione. Nel caso in cui utilizziate ExtUtils::MakeMaker di solito saranno:

perl Makefile.PL
make
make test
make install

Nel caso in cui utilizziate Module::Build, di solito saranno:

perl Build.PL
perl Build
perl Build test
perl Build install

Dovreste produrre delle note di rilascio o dei changelog per ogni versione del vostro software, al fine di descrivere cambiamenti visibili all'utilizzatore, in termini rilevanti per l'utente.

CONSIDERAZIONI SUL RILASCIO

Numerazione di versioni

La numerazione delle versioni dovrebbe denotare almeno le distribuzioni principale e secondaria, e al limite le distribuzioni di ordine gerarchico inferiore. Una distribuzione principale è tale per cui la maggior parte delle funzionalità ha subito un cambiamento, o nella quale sono state aggiunte importanti nuove funzionalità. Un rilascio minore si ha quando sono state aggiunte, o modificate, poche funzionalità. Di solito si utilizzano dei numeri di distribuzioni gerarchicamente inferiori per quei cambiamenti che non alterano la funzionalità, come le aggiunte alla documentazione.

Lo schema di numerazione più comune delle versioni per CPAN è del tipo:

1.00, 1.10, 1.11, 1.20, 1.30, 1.31, 1.32

Una corretta numerazione di una versione per CPAN è un numero in virgola mobile con almeno due cifre dopo la virgola. Potete verificare la conformità con CPAN utilizzando

perl -MExtUtils::MakeMaker -le 'print MM->parse_version(shift)' 'Pippo.pm'

Se volete distribuire una versione 'beta' o 'alpha' di un modulo, ma non desiderate che CPAN.pm la includa nella lista come più recente, utilizzate il trattino basso dopo il normale numero di versione seguito da almeno due cifre, per esempio 1.20_01. Se fate ciò, è consigliato il seguente idioma:

$VERSION = "1.12_01";
$XS_VERSION = $VERSION; # necessario solamente se avete codice XS
$VERSION = eval $VERSION;

Con questo trucco MakeMaker leggerà solamente la prima linea e poi il trattino basso, mentre l'interprete Perl valuterà $VERSION e convertirà la stringa in un numero. Operazioni successive che tratteranno $VERSION come un numero, saranno quindi in grado di farlo senza generare un messaggio di warning a proposito del fatto che $VERSION non sia un numero.

Mai distribuire (anche una singola parola aggiunta alla documentazione) senza incrementare il numero. Anche una singola parola di documentazione aggiunta dovrebbe risultare in un cambiamento di versione a livello gerarchico inferiore.

Prerequisiti

Gli autori di moduli dovrebbero valutare attentamente se affidarsi ad altri moduli ed a quali.

È fondamentale scegliere moduli che siano il più possibile stabili. In ordine di preferenza:

  • Moduli base del Perl

  • Moduli di CPAN stabili

  • Moduli di CPAN instabili

  • Moduli non disponibili su CPAN

Specificate i requisiti di versione per i moduli Perl richiesti nei prerequisiti nel vostro Makefile.PL o Build.PL.

Assicuratevi di specificare i requisiti della versione de Perl in Makefile.PL o in Build.PL e con require 5.6.1 o simile. Si veda la sezione use VERSIONE di "require" in perlfunc per i dettagli.

Test

Ogni modulo dovrebbe essere testato prima di essere distribuito (utilizzando "make disttest"), ed i test dovrebbero anche essere disponibili per coloro che installano i moduli (utilizzando "make test"). Per Module::Build dovrete utilizzare l'equivalente di make test: perl Build test.

L'importanza di questi test è proporzionale alla presunta stabilità di un modulo -- un modulo che pretende di essere stabile o che ambisce ad essere largamente utilizzato dovrebbe aderire il più possibile ad uno stretto regime di test.

Moduli che possono risultare utili per i vostri test (con impatto minimo sul vostro processo di sviluppo o il vostro tempo) includono Test::Simple, Carp::Assert e Test::Inline. Per strumenti di test più sofisticati si vedano Test::More e Test::MockObject.

Packaging [Pacchettizzazione, NdT]

I moduli dovrebbero essere preparati per la distribuzione [Pacchettizzati, NdT] utilizzando uno degli strumenti di pacchettizzazione standard. Al momento potete scegliere tra ExtUtils::MakeMaker e Module::Build (quest'ultimo più indipendente dalla piattaforma), per permettere di installare i moduli in maniera consistente. Se utilizzate ExtUtils::MakeMaker, potete usare "make dist" per creare il vostro pacchetto. Esistono strumenti per aiutarvi a fare la build del modulo in uno stile compatibile con MakeMaker. Questi includono ExtUtils::ModuleMaker e h2xs. Si veda anche perlnewmod.

Fornire una licenza

Assicuratevi che il vostro modulo abbia una licenza, e che la sua versione integrale sia inclusa nella distribuzione (a meno che sia di un tipo comune ed i termini di licenza non richiedano di includerla).

Se non sapete che licenza utilizzare, la cosiddetta "dual licensing" [doppia licenza, NdT] sotto GPL e licenza Artistica (la stessa del Perl) è una buona idea. Si veda perlgpl e perlartistic.

I TRANELLI PIÙ COMUNI

Reinventare la ruota

Ci sono alcune aree di applicazione che sono già molto, molto ben supportate da CPAN. Un esempio sono i sistemi di template, un altro sono i moduli per date e ore, e ce ne sono molti altri. Benché sia un rito di passaggio scrivere la vostra versione di queste cose, valutate attentamente se il mondo del Perl abbia veramente bisogno del vostro contributo.

Provare a strafare

Il vostro modulo farà parte del toolkit di uno sviluppatore. Non sarà, di per se, l'intero toolkit. Aggiungere nuove funzionalità puà essere una tentazione fino a quando il vostro codice non diventa un sistema monolitico invece che un insieme modulare di blocchi base.

Documentazione inappropriata

Non cadete nella trappola di scrivere per il lettore sbagliato. Il vostro principale destinatario è uno sviluppatore con una ragionevole esperienza e con almeno una moderata conoscenza a proposito del dominio di applicazione del vostro modulo, che ha solo scaricato il modulo e vuole iniziare ad usarlo al più presto possibile.

Guide rapide, documentazione orientata all'utilizzo, pubblicazioni scientifiche, FAQ [domante poste di frequente, NdT] non sono appropriate nella documentazione principale di un modulo. Se proprio volete includerle, fatelo in un sotto-documento del tipo Vostro::Modulo::GuidaRapida o Vostro::Modulo::FAQ e fornite un link nella sezione SI VEDA ANCHE della documentazione principale.

SI VEDA ANCHE

perlstyle

Guida generale alla programmazione con stile in Perl

perlnewmod

Come creare un nuovo modulo

perlpod

Documentazione POD

podchecker

Verifica la correttezza del vostro POD

Programmi di utilità per il packaging [Pacchettizzazione, NdT]

ExtUtils::MakeMaker, Module::Build

Strumenti per effettuare test

Test::Simple, Test::Inline, Carp::Assert, Test::More, Test::MockObject

http://pause.perl.org/

Perl Authors Upload Server [Server di archiviazione per autori Perl, NdT]. Contiene riferimenti a informazioni utili per gli autori dei moduli.

Qualsiasi buon libro sull'ingegneria del software

AUTORE

Kirrily "Skud" Robert <skud@cpan.org>

TRADUZIONE

Versione

La versione su cui si basa questa traduzione è ottenibile con:

perl -MPOD2::IT -e print_pod perlmodstyle

Per maggiori informazioni sul progetto di traduzione in italiano si veda http://pod2it.sourceforge.net/ .

Traduttore

Traduzione a cura di Raffaello Galli <galliraf at googlemail punto com>.

Note del traduttore

Se per caso si verificasse l'evenienza che qualche sviluppatore di lingua italiana voglia pubblicare il proprio modulo Perl su CPAN, ma per sua sfortuna non abbia sufficiente familiarità con la lingua inglese per scrivere una documentazione decente, il team di pod2it si offre per consulenza e revisione.

Revisore

Revisione a cura di dree.