giovedì 31 gennaio 2008

argv[0]

Ho ricevuto spesso da parte di studenti richieste di chiarimento circa il parametro argv[0] di un programma C/Java e la loro differenza. Cerco di riassumere brevemente in questo post il loro significato.


Programmi C

Un programma C ha solitamente il prototipo:

int main( int argc, char** argv )

dove argv rappresenta un array di stringhe (array di array di char) e argc fornisce il numero di stringhe effettivamente passate al programma (ad es. dalla shell). Nel caso del C argv[0] è la stringa contenente il nome del programma stesso.
Ad esempio, se un programma C viene invocato come:

prog_c par1 par2 par3

allora si avrà che

argv[0] = prog_c
argv[1] = par1
argv[2] = par2
argv[3] = par3

argc = 4

La motivazione per la quale argv[0] rappresenta il nome del programma stesso, invece del primo parametro posizionale, deriva dal forte legame fra C e Unix. In Unix è possibile linkare due file residenti sullo stesso file system facendo in modo, tramite gli i-node, che effettivamente i due file creati non esistano, ma ne esista uno solo con due (o più) nomi. Questo significa che prog_c potrebbe essere linkato con un altro nome, ad esempio prog.exe, e potrebbe venir lanciato con entrambi i nodi, poiché di fatto l'i-node punta sempre allo stesso dato fisico su disco.

Il linking di programmi veniva usato in passato per legare programmi con comportamenti simili risparmiando spazio su disco. Ad esempio, il programma cp (copia) e il programma mv (sposta) hanno comportamenti simili. E' quindi possibile creare un solo programma base che implementi un comportamento differente a seconda del nome con il quale è stato invocato. Ecco perché è importante, per un programma C, riuscire a recuperare il nome con il quale è stato invocato.

Programmi Java

Un programma Java ha il seguente prototipo:

public static void main( String argv[] )

con il metodo main che deve essere contenuto in una classe. Anzitutto si noti la similarità con il prototipo C: entrambi accettano un array di stringhe, che sono i parametri passati da riga (ad es. dalla shell). Tuttavia qui è assente il contatore del numero di argomenti, poiché è implicitamente inglobato nell'array argv stesso (argc = argv.length).

A differenza del C, in Java argv[0] rappresenta il primo argomento reale passato al programma. Ad esempio, se si invoca il programma:

java prog_java par1 par2 par3

si avrà che

argv[0] = par1
argv[1] = par2
argv[2] = par3

argv.length = 3
La motivazione di questa differenza dipende da come un programma Java viene invocato. In Java, non si invoca un file eseguibile (come avviene in C), bensì si chiede all'interprete Java di caricare una classe (nell'esempio di cui sopra prog_java) che deve contenere il main. La JVM cerca la classe nel classpath, e la carica. Successivamente ricerca al suo interno il metodo main e lo manda in esecuzione. Siccome in Java una classe pubblica di nome A deve risiedere in un file A.class, e non si può fare altrimenti (la JVM non saprebbe più come trovare le classi), è evidente che non è possibile creare un alias di una classe. Ne consegue che il metodo main ha sempre la certezza di eseguire nella classe nel quale è definito, e quindi l'informazione sul nome del programma (classe) invocato è inutile.

mercoledì 30 gennaio 2008

Test compatti in shell

Il comando expr(1)
Il comando expr(1) consente di valutare espressioni aritmetiche, e il suo uso in generale è il seguente:

var=`expr val1 op val2`


dove var è la variabile alla quale sarà assegnato il valore calcolato, val1 e val2 sono i due operandi e op e l'operatore. Ad esempio:

var=`expr 10 + 20` var=`expr $var + 1`
che assegna prima a var il valore 30, e successivamente incrementa di 1 il valore calcolato, riassegnandolo nuovamente a var. Indubbimante expr è un comando molto potente, ma la shell ci mette a disposizione un modo molto più conveniente per eseguire operazioni matematiche: (( )). Ogni espressione racchiusa fra (( )) viene valutata nel suo contesto aritmetico direttamente. L'esempio precedente viene quindi riscritto come:
(( var = 10 + 20 )) (( var = $var + 1 ))
o ancora meglio
(( var = 10 + 20 )) (( var++ ))
A parte la maggiore compattezza del codice, bisogna considerare come (( )) non tenga conto degli spazi extra nell'assegnamento a variabile, cosa invece non tollerata dalla shell. Inoltre, expr restituisce il proprio risultato su stdout, e quindi deve essere catturato con i backtick per essere assegnato ad una variabile, mentre (( )) non restituisce nulla su stdout e assegna direttamente il valore calcolato alla variabile contenuta nell'espressione di assegnamento. Per entrambi il codice di ritorno ha la stessa semantica: 0 se il valore calcolato non è uguale a zero, 1 se il valore calcolato è uguale a zero.

Il comando test(1)

Il comando test(1) viene utilizzato per verificare determinate condizioni, ad esempio l'esistenza di un file, i permessi o il confronto fra valori stringhe e numerici. Il coamndo test(1) è un eseguibile presente su disco, ad esempio sulla mia macchina ho:
ls -l `which test`
-rwxr-xr-x 1 root root 23036 2007-09-29 14:51 /usr/bin/test

ls -l `which [`
-rwxr-xr-x 1 root root 25024 2007-09-29 14:51 /usr/bin/[

Il secondo programma, la parentesi quadra [, rappresenta una sorta di sinonimo per il comando test(1). In realtà non è un vero sinonimo, visto che i due programmi sono indipendenti (e non linkati). Tuttavia il comando test(1) può essere sostituito con la coppia di parentesi quadre, ad esempio:
if test -f $file
then
....
fi

diventa:
if [ -f $file ]
then
....
fi

L'equivalenza fra i due programmi si ha perfino dalla pagina man di test(1), dove i due sono presentati come equivalenti. Attenzione però che il comando [ da solo non funziona: la shell necessita che le parentesi siano bilanciate, e quindi [ deve essere sempre seguito da un ].


Test con operatori logici

Qualora si vogliano effettuare dei test usando [ al posto di test(1), si può ricorrere alla forma [[ e usare anche operatori logici e parentesi tonde per separare meglio i test. Ad esempio:


[[ (-f $file) && ( (-d data) || (-d tmp) ) ]]


questo test controlla l'esistenza di un file e l'esistenza di una directory fra data e tmp. Si noti la compattezza di una simile espressione, che sarebbe risultata invece molto più complessa con il solo uso dell'operatore test(1).


Un buon tutorial sugli operatori [ ] , [[ ]] e (( )) si può trovare presso la libreria IBM.

Controllo del numero di argomenti di uno script shell

In molti esercizi di programmazione shell (Bourne Shell) proposti nei corsi di Sistemi Operativi dell'Università degli Studi di Modena e Reggio Emilia si richiede agli studenti di testare il numero di argomenti passati da linea di comando. Il controllo, chiaramente, dovrebbe essere implementato in ogni buon programma (non solo in quelli Shell) per assicurare che lo stesso possa eseguire con le corrette informazioni. Ovviamente, questo controllo da solo non è sufficiente, poiché deve essere seguito da un controllo sul tipo (ossia la validità) degli argomenti stessi. Tuttavia in questo articolo mi concentro solo sul controllo relativamente il numero degli argomenti.

La Bourne Shell (così come la Bash) utilizzano la variabile speciale $# per memorizzare il numero di argomenti passati da riga di comando. In particolare $# memorizza il numero di argomenti realmente passati allo script, ossia il numero di argomenti posizionali che seguono il nome dello script stesso (questo si differenzia dal C, dove il primo argomento è sempre il nome del programma stesso).

Molte soluzioni proposte ai corsi di cui sopra implementano il controllo sul numero di argomenti con un costrutto case:

case $# in
0 | 1 | 2 | 3) echo "Troppi pochi argomenti"; exit 1;;
4) ;;
*) echo "Errore nel numero di argomenti"; exit 2;;
esac
Nell'esempio riportato si fa il caso di uno script che accetta esattamente 4 parametri. In questo caso occorre scrivere un ramo del case per un numero di parametri inferiori a 4 (0,1,2,3), uno per il caso corretto (un ramo che non fa nulla) e uno per gli altri casi (che per esclusione risultano essere quelli con $# maggiore di 4).

Questo tipo di soluzione è a mio avviso errata e non dovrebbe essere proposta per i seguenti motivi:
  • è una soluzione goffa: se il numero esatto di parametri fosse alto, ad esempio 10, occorrerebbe enumerare singolarmente tutti i valori inferiori. Infatti, l'utilità del '*' è usata solo per un numero di parametri troppo evelato, ma non esiste il suo duale per pochi parametri;
  • è una soluzione lunga da scrivere: prevede la scrittura di almeno tre rami del case, quando le condizioni da testare sono solo due (maggiore e minore);
  • è una soluzione incline ad errori: inserire un ramo nel case che non opera nessuna operazione è pericolosa e mina la manutenibilità dello script stesso. Operazioni vitali potrebbero erroneamente finire nel ramo vuoto, o ci si potrebbe dimenticare del ';;' che segna la fine del case.
La soluzione basata su if risulta come segue:

if test $# -le 3
then
echo "Troppi pochi argomenti"
exit 1
else
if test $# -gt 4
then
echo "Troppi argomenti"
exit 2
fi
fi

Apparentemente questa soluzione è più lunga della precedente, ma è una pura questione stilistica, visto che sarebbe possibile comprimere il codice come segue:

if test $# -le 3; then  echo "Troppi pochi argomenti";  exit 1;
else
if test $# -gt 4; then echo "Troppi argomenti"; exit 2; fi
fi

così da risparmiare una riga rispetto al case. Ad ogni modo, le cose importanti da notare nella soluzione che sfrutta l'if sono:
  • è una soluzione flessibile: è possibile preimpostare con una variabile il numero esatto di argomenti attesi e lasciare inalterato il test;
  • è una soluzione compatta;
  • modella bene il caso che si vuole testare: troppi pochi parametri (if) o troppi parametri (else);
  • non richiede nessuna enumerazione dei casi non utilizzati (0,1,2,3);
  • non presenta rami vuoti, se il test viene superato il programma prosegue normalmente.
Per rendere ancora più flessibile la soluzione, è possibile usare la forma:


ARGC=4
if test $# -lt $ARGC; then echo "Troppi pochi argomenti"; exit 1;
else
if test $# -gt $ARGC; then echo "Troppi argomenti"; exit 2; fi
fi

Così facendo, eventuali evoluzioni dello script che prevedano un diverso numero di argomenti richiederanno la sola modifica del valore in ARGC.

Da ultimo, si tenga presenta che tutte le soluzioni che prevedono un if sono da usarsi quando il numero delle casistiche da trattare non è eccessivamente elevato, mentre il case (o lo switch di Java/C) è da preferirsi quando si devono implementare comportamenti diversi in risposta a molte casistiche.

STOP alle dispense protette da password

Noto con disappunto che sempre più spesso i professori universitari proteggono le dispense dei loro corsi mediante password. L'idea è semplice: tutti i lucidi e le dispense sono resi pubblici e messi on-line (in vari formati, PDF, PPT, RTF,...), ma per poterli aprire è necessario conoscere la password comunicata dal docente a lezione. Viene data una duplice giustificazione di questo atteggiamento:
  • si tutela il lavoro del docente stesso (la produzione dei lucidi) in modo che nessun altro docente/studente possa rielaborarlo senza autorizzazione;
  • si tutela la diligenza degli studenti, che solo partecipando alle lezioni possono entrare in possesso della password.
Questa pratica ha visto protagonista anche me, che spesso acconsentivo al rilascio di dispense e lucidi protetti da password. In realtà io ho sempre cercato di rilasciare le dispense senza protezione di lettura, ma solo di modifica. Questo permetteva a chiunque di leggere/stampare le mie dispense, senza però poterle modificare, riutilizzare in lavori personali o addirittura rilasciarne di nuove versioni. Tuttavia, spesso mi veniva chiesto dal docente stesso di rilasciare le dispense proteggendole da password, e quindi anche io cadevo nel tranello dei documenti protetti da password.

Parlo di tranello perché in realtà la protezione dei documenti con password è a mio avviso controproducente. Nell'era dell'informazione libera (si pensi solo a Wikipedia) l'accesso alle informazioni non dovrebbe essere limitato ai soli studenti in corso. E' facile immaginare studenti di altre facoltà o semplicemente già laureati che, per meglio apprendere o ripassare determinati argomenti, siano interessati a documenti di altri corsi/professori. Non consentire la condivisione della conoscenza rappresenta, in particolare per le università, una forte limitazione nonché un controsenso. Inoltre il valore aggiunto per gli studenti non dovrebbero essere le dispense, ma le spiegazioni e la disponibilità del docente. In altre parole, le tasse pagate dagli studenti dovrebbero tutelare la presenza dei docenti e la loro disponibilità, nonché la disponibilità di supporti didattici particolari (computer, proiettori, ecc.), e non di semplici dispense.

Sarebbe quindi opportuno che i docenti, qualora volessero tutelare le proprie dispense, iniziassero a rilasciare le stesse con licenze appropriate (ad es. Creative Commons, GNU, ecc.). Questo garantisce ai docenti la proprietà delle dispense, nonché permette di limitare gli eventuali usi di porzioni delle stesse, e allo stesso tempo permette agli studenti di avere accesso libero alle stesse.
Così facendo si arriverebbe ad una situazione ove:
  • il lavoro dei docenti è correttamente tutelato da una appropriata licenza;
  • la diligenza degli studenti viene comunque premiata: gli studenti vogliosi di apprendere e che non esitano a consultare materiali didattici differenti risulteranno meglio preparati di altri.
Da non sottovalutare poi che, rilasciando il proprio lavoro sotto un'appropriata licenza, stimola e abitua gli studenti a ragionare in termini di materiale pubblicamente disponibile e a scegliere la licenza per i propri lavori. In particolare, per gli studenti di informatica, questo si traduce in una predisposizione all'OpenSource.

Ci sono poi degli effetti collaterali nel rilasciare pubblicamente le proprie dispense: i docenti risultano più stimolati a produrre documenti completi, chiari e accattivanti, cosa che chiaramente è meno sentita nel caso di documenti mantenuti privati all'interno di un corso. E, nella migliore tradizione OpenSource, un simile approccio favorisce una maggiore produzione di commenti e correzioni da parte degli studenti.

Invito quindi gli studenti degli atenei dove vengono rilasciate dispense protette da password a ribellarsi e a richiedere la disponibilità del materiale didattico sotto licenze che ne tutelino gli autori ma che non vincoli la fruibilità del materiale stesso.

lunedì 28 gennaio 2008

Impostazione modulare delle variabili di ambiente Shell

Diversi software richiedono l'impostazione di variabili di ambienti per il loro utilizzo, specialmente quando si opera direttamente con la shell. Invece di memorizzare tutte le variabili di ambiente in un unico file, io propongo un approccio più modulare. In sostanza le variabili di ambiente sono raggruppate in base alla loro correlazione (es. quelle legate a Java, quelle legate a PostgreSQL, ecc.); ogni gruppo viene memorizzato all'interno di un proprio file con estensione .env (environment).
Ad esempio, ecco un file relativo a Java:

#!/bin/bash
if test -z "${JAVAHOME}"
then
JAVAHOME=/sviluppo/java/
JAVA_HOME=${JAVAHOME}/jdk
JDK_HOME="${JAVAHOME}/jdk"
JRE_HOME="${JDK_HOME}"
JAR_HOME="${JAVAHOME}/jars"
ANT_HOME="${JAVAHOME}/ant"
ECLIPSE_HOME="{JAVAHOME}/eclipse"


PATH="${JDK_HOME}/bin":"${PATH}":"${ANT_HOME}/bin"

# tengo conto di tutti i jar file messi nella jar home
for jarFile in "${JAR_HOME}"/*.jar
do
JAR_CLASSPATH="${jarFile}":"${JAR_CLASSPATH}"
done

CLASSPATH="${JAR_CLASSPATH}":"${CLASSPATH}"
classpath="${CLASSPATH}"


export JAVA_HOME
export JDK_HOME
export JRE_HOME
export JAR_HOME
export PATH
export CLASSPATH
export classpath
fi

Il file è piuttosto semplice: anzitutto si controlla se la definizione delle variabili è già stata fatta, nel qual caso non la si sovrascrive. Ciò viene controllato grazie alla variabile ${JAVAHOME}, dalla quale molte delle altre dipendono. In seguito, si definiscono i valori per le variabili di ambiente richieste (non tutte le variabili sono effettivamente richieste dal sistema, alcune sono definite per praticità o coerenza). Si noti la definizione di ${JAR_HOME}, che rappresenta una cartella che contiene i jar relativi a librerie esterne; tutti i jar sono aggiunti al classpath in modo da rendere le librerie accessibili. Infine si effettua l'esportazione delle variabili per renderle visibili anche ai sottoshell.

Per effettuare il caricamento automatico di questo file (e degli altri simili), occorre poi modificare il proprio .profile o .bash_profile aggiungendo il blocco che segue:

if [ -d $HOME/bin ]
then
for envFile in $HOME/bin/*.env
do
. $envFile
done
fi


Il blocco di codice qui sopra è piuttosto semplice: supponendo che i file .env si trovino nella cartella bin della home utente, si provvede al loro caricamento mediante l'operatore . (source).

Tramite questa soluzione è abbastanza semplice mantenere anche grosse quantità di variabili di ambiente senza perdere in modularità e semplicità di configurazione. Basterà dare un'occhiata al file .env relativo ad un sottosistema per ottenere la relativa configurazione.

Ricerca diretta nella documentazione di PostgreSQL da Konqueror

Gli utenti di Konqueror sono abituati alla potenza di questo browser web, che consente la configurazione di scorciatoie per la ricerca rapidi di contenuti internet. La più utilizzata, almeno da me, è la gg: che consente la ricerca diretta tramite Google.

Ebbene se siete utenti PostgreSQL, potete configurare una scorciatoia anche per la ricerca nella documentazione ufficiale del progetto. I passi per ottenere questo sono semplici:
1) aprite la finestra di configurazione di Konqueror, dal menù Settings, Configure Konqueror
2) selezionate la voce Web Shortcuts a sinistra
3) cliccate sul pulsante New per inserire un nuovo motore di ricerca

4) nella finestra di dialogo che appare inserite un nome per il servizio (Search Provider Name), ad esempio "PostgreSQL documentation"
5) inserite l'indirizzo di ricerca (Search URI):

http://search.postgresql.org/search?q=\{ @ }

dove la @ rappresenta il parametro di ricerca, ossia la stringa che verrà passata al motore di ricerca
6) inserite le abbreviazioni per la ricerca (URI Shortcut), che rappresenta il prefisso da inserire nella barra dell'indirizzo per ordinare a Konqueror di cercare il testo con il motore di ricerca definito. Ad esempio, inserendo pg come shortcut, allora ogni volta che si digiterà pg:testo_da_cercare Konqueror contatterà direttamente il servizio di ricerca della documentazione passando la stringa testo_da_cercare al motore



A questo punto riavviate Konqueror, e troverete il motore di ricerca della documentazione PostgreSQL fra quelli disponibili nella barra di ricerca. Inoltre, con lo shortcut pg: cercherete direttamente il testo nella documentazione on-line.

Questo amato/odiato cellulare...

Assisto sempre più spesso a scene veramente patetiche impersonate da utilizzatori di cellulari.

Molti sono ormai assuefatti, e per loro il cellulare è l'equivalente delle sigarette per i fumatori incalliti. Lo portano ovunque, lo hanno sempre in mano o sul tavolo a fianco a loro, ogni minuto lo controllano con una gestualità ormai precisa e perfetta. Altri invece, ormai invasi oltre ogni limite nella propria quotidianità, arrivano addirittura a non rispondere se non sanno in anticipo chi sia il chiamante. Sembra che la gente abbia perfino perso il senso di controllo sul proprio cellulare: una volta che hai risposto non sei obbligato a sostenere la conversazione, puoi sempre riagganciare (educatamente), quindi perché nascondersi?

Ma non è finita: si è spesso costretti ad ascoltare le conversazioni altrui, il più delle volte perché la gente non parla al telefono, urla! E questo a discapito della propria privacy, nonché di quella altrui.

Anche un po' di educazione non guasterebbe; ricordarsi che il cellulare non viene prima di tutto sarebbe un buon principio. Già, perché spesso si vedono persone che sentendo suonare il cellulare lasciano qualunque cosa stiano facendo per rispondere. E allora si resta in fila al supermercato perché invece che pagare, la gente si mette a telefonare. I commessi dei negozi devono aspettare i comodi dei loro clienti maleducati, che in questo caso non hanno ragione poiché non mostrano alcun rispetto per le persone che stanno lavorando. Per non parlare di quello che si vede in macchina.

Io non dico che il cellulare non debba essere usato, ma che debba essere usato con criterio e rispetto.

"...ti regalerò un cellulare così
potremo dirci frasi più dolci di Remì
che non c'è nulla che sbrindella le cervella più di
telefonate notte e dì in tariffa you&me..."
da Sono troppo stitico per fare lo stronzo, Habemu Capa di Caparezza

domenica 27 gennaio 2008

Gigetto: il treno che costa più di quello che da

Da più di un anno ormai sono abituato a recarmi in ufficio in treno, utilizzando il famoso Gigetto, il treno che serve la tratta Modena-Sassuolo.

Mi piace usare il treno, arrivo a destinazione senza lo stress dell'automobile, posso leggere e ascoltare musica, e in generale distrarmi durante il tragitto. Non da meno, questa mia scelta rappresenta un modesto contributo al rispetto ambientale. Certo a volte è scomodo non disporre dell'auto, principalmente a causa del maltempo o per l'essere costantemente legato ad orari precisi (o presunti tali). Però mi piace, credo fermamente in questo modo di trasporto e non sono intenzionato a riconvertirmi alla stressante ed inquinante automobile facilmente.

Tuttavia, con l'inizio dell'anno nuovo l'azienda dei trasporti sembra essere intenzionata a farmi cambiare idea. Tutto è iniziato lunedì scorso, quando la macchinetta obliteratrice ha marcato il tragitto Casinalbo-Sassuolo a 2,07 euro (il sabato precedente mi ero recato a Bologna, con biglietto di andata e ritorno di 5,10 euro!). La mattina però, ancora addormentato e infreddolito, non ho realizzato bene cosa fosse successo. Poi finalmente mi sono ricordato che ogni anno, gli abbonamenti vengono "resettati" e quindi tutti gli sconti accumulati con i viaggi precedenti vengono persi. Ebbene, avendo un abbonamento Modena-Sassuolo, e facendo adesso il ben più breve tragitto Casinalbo-Sassuolo (che è confinato in un'unica zona), ho capito come fosse necessario cambiare la tipologia di abbonamento.
Approfittando della coincidenza serale a Formigine, mi sono quindi recato in biglietteria chiedendo di cambiare le zone relative al mio abbonamento. L'operatore mi ha chiesto di ricaricare anche la tessera contestualmente, cosa che ho fatto senza troppi problemi. Terminata l'operazione, dopo essermi raccomandato e aver chiesto nuovamente conferma della modifica per la tratta Casinalbo-Sassuolo, ho messo in tasca la tesserina e sono salito nuovamente sul treno.
La mattina dopo, con mio notevole disappunto, l'obliteratrice alla stazione di Casinalbo, marcava nuovamente il biglietto a 2,07 euro. Avendolo fatto controllare al personale di bordo, non ho avuto alternativa che ritornare a Formigine la sera stessa per controllare come mai la modifica da me richiesta non fosse stata effettuata.
Ebbene, presentando la tessera al medesimo operatore della sera precedente, e ribadendo ancora una volta la mia intenzione di modificare l'abbonamento da Modena-Sassuolo a Casinalbo-Sassuolo, mi sono prima sentito rispondere che la tessera era in ordine; successivamente mi è stato detto che la modifica in oggetto era da pagare con una cifra di euro 10 o con l'emissione di un nuovo abbonamento. Ho chiesto così di fare un nuovo abbonamento trasferendovi il credito residuo di quello in mio possesso, cosa che l'operatore disse essere impossibile. Ho chiesto quindi spiegazioni sul perché la sera prima non mi erano state date queste informazioni e, anzi, mi era perfino stato chiesto di ricaricare la tessera.
L'operatore mi ha risposto che aveva pensato mi convenisse mantenere l'abbonamento attuale e digitare prima di ogni obliterazione Nuovo Viaggio, così da modificare manualmente ogni volta l'itinerario. Tralascio l'ira con la quale ho attaccato questo povero operatore, che trascurando il detto "il cliente ha sempre ragione", ha pensato non solo di farmi i conti in tasca (non ho mai espresso la mia volontà di non pagare 10 euro per la modifica), ma ha ritenuto non importante fornirmi i dettagli del servizio, e anzi che fosse più semplice per me cambiare manualmente ad ogni viaggio l'itinerario. Eppure l'ATCM, o meglio la FER visto che da inizio anno il servizio è in mano alla ferrovia regionale, ha intascato i miei soldi (i biglietti sovra-prezzati e la ricarica) in anticipo! Non solo: se per errore non riesco a modificare la destinazione di un tragitto, e quindi mi viene scalato un prezzo errato, come mi dovrei comportare io? Non pagare il tragitto successivo? Farmi rimborsare perché l'operatore di sua iniziativa non ha fatto quello che gli era stato chiesto?
Ma non è finita qui: durante la discussione con il malaugurato operatore, quest'ultimo mi ha invitato a marcare in sua presenza il biglietto a dimostrazione di come fosse semplice selezionare manualmente la destinazione con Nuovo Viaggio. E questa, francamente, mi sembra la dimostrazione di come l'operatore sia un'assunzione obbligatoria! Ebbene si, perché oltre ad avere meno soldi nel mio abbonamento, oltre alla rabbia e alla presa in giro di non essere stato informato e ascoltato la prima volta, dovevo pure marcare un biglietto per prova!
Pura follia!

Eppure il passaggio da ATCM a FER dovrebbe fornire grandi novità:
gli Enti locali modenesi hanno ritenuto di dover aderire a tale volontà, per il bene stesso della ferrovia, per la quale si apre una stagione nuova con prospettive di più ampio respiro


Speriamo veramente che ci sia questa stagione di ampio respiro, o anche le persone desiderose di sfruttare questo sistema di trasporto, come me, arriveranno a cedere a malincuore e a tornare all'automobile.

Nel frattempo io devo ricordarmi ogni volta di modificare manualmente la destinazione del mio tragitto, almeno fino a quando non avrò il tempo di recarmi in una biglietteria (evitando quella di Formigine) per il sospirato cambio di abbonamento