martedì 28 febbraio 2017

Pervasività dei linguaggi di programmazione: l'esempio di Python

Chi mi conosce sa che non mi interesso di Python.
Il linguaggio è sicuramente notevole, e secondo me ha alcuni punti di forza, in particolare la sintassi "blindata" che rimuove in partenza molte discussioni (chi pensa a style(9)?).
Ad ogni modo fa molto piacere vedere a che livello di pervasività tecnologica si sta giungendo, se addirittura Walt Disney sponsorizza pesantemente PyCon 2017

domenica 26 febbraio 2017

KDE @ school

Articolo molto interessante sull'adozione di KDE nelle scuole.
Come spiega l'articolo, al giorno d'oggi gli studenti non sono molto interessati all'interfaccia grafica che gli si presenta, basta che funzioni e gli permetta di essere connessi in modo veloce ed efficiente. Ma il risparmio per l'amministrazione può risultare importante.
Perché almeno le nostre università non prendono esempio?
Perché i professori, per primi, continuano a scrivere articoli con strumenti proprietari?

sabato 25 febbraio 2017

PHP anonymous functions and closures: is it smart?

As many other modern lagnuages, PHP is evolving and allows the usage of so called "closures": the idea is to define a function on the fly and use it as an "handler". More than that, a closure is a special function closed on a context, in particular the context that defined itself.
This is very useful, because the function should reference variables that are going to be out of scope, in a certain way as if they have been hardcoded into the function definition itself.

PHP closures don't work really this way, and I don't get the point: a PHP anonymous function can reference instance variable (i.e., members of the class where the function is defined) but not scoped variables (e.g., a variable in the function that is defining the anonymous function). More in general, it seems to me that PHP anonymous functions can reference global variables, and this is true also for class members, but not outer scope variables.
In other words this is not going to work:

function foo( $param ){
  ...
  $closure = function( $event ){
   if ( $event == $param ) { ... }
 };
}

because the $param variable is not visible within the anonymous function.
Now, there's a solution as reported in the documentation : you can specify which variables of the outer scope the anonymous function is going to "use":

function foo( $param ){
   ...
   $closure = function( $event ) use ( $param ){
    if ( $event == $param ) { ... }
   };
}


Now PHP has the opportunity to see that $param is needed inside the anonymous function, that becomes a "real" closure.
This is just another feature I don't like in the PHP language: why is what every developer expects to be a closure not being such? Moreover the abuse of the word "use" (needed also for namespaces handling) produce an operator overload I don't like very much.
Last but not least, while I get the idea of forcing a developer to declare what he is going to use and do, why not simplifying his life declaring what is using as local (e.g., local in Perl)?

giovedì 23 febbraio 2017

Quali parte sono "colpite" dalle statistiche PostgreSQL?

Ecco una interessante immagine che rende l'idea di quali parti del complesso e completo sistema di statistiche PostgreSQL. L'immagine mostra quali viste usare a seconda della parte di backend/stack che si vuole monitorare.
Per l'articolo originale si veda qui:


mercoledì 22 febbraio 2017

Kate, sudoedit ed essere suid

Nelle prossime versione Kate (e anche KEdit mi pare di capire) non permetterà piu' di essere eseguito in modalità SUID, ovvero con permessi di root abilitati. Questo prevenie molti inconvenienti legati piu' all'antico stack di X Windows invece che a KDE stesso.
Ora, come si potrà fare a editare file dove occorrano permessi elevati? La soluzione pare essere quella di usare una combinazione di warning e sudoedit.
Sebbene la soluzione sia interessante e quantomeno mirata alla buona educazione degli utenti, vedo alcuni problemi legati alla scelta di "sudoedit" stesso. Ci sono infatti sistemi che stanno/hanno abbandonato sudo a favore di qualcosa piu' compatto e installabile nella base (ad esempio OpenBSD e doas(1)). Legarsi quindi ad un programma esterno, seppur diffuso, rischia quindi di diventare una difficoltà per il porting su altre piattaforme.

Ah, giusto come nota, per gli utenti Emacs si può utilizzare TRAMP con url /sudo::/path/to/file (richiede un accesso SSH alla macchina, che è un po' un collo di bottiglia iniziale, ma tutto sommato sicuramente valido).

for Perl else ?

Aggiungere un "else" ad un ciclo for?
Tutto nasce dall'esigenza di eseguire del codice qualora un ciclo non venga mai eseguito...ma andiamo con ordine.
I cicli for (e foreach) di Perl si sono sempre comportati come ci si aspetta (dwim): se non ci sono iterazioni da fare non viene fatto nulla. Può sembrare stupefacente, ma Java, ad esempio, non è stato capace di fare la stessa cosa quando nella versione 5 ha inserito i "foreach":
Consideriamo una lista "objects" di oggetti di qualche tipo, ebbene il seguente blocco Java solleva una NullPointerException se la lista è nulla

for ( Object item : objects ){ ... }

mentre lo stesso ciclo Perl semplicemente non fa nulla

for my $item ( @objects ) { ... }

Ma il problema della discussione non è sulla nullità della lista, quanto sul fatto che la lista sia vuota. Nel caso la lista di oggetti sia "empty" (e/o non definita in Perl), il ciclo for non viene mai eseguito. Questo porta gli sviluppatori a scrivere codice "di guardia" per iniettare codice da eseguire qualora la lista non contenga valori:

if ( objects == null || objects.isEmpty() ){
  System.out.println( "Nessun elemento" );
}
else
  for ( Object item : objects ) { ... }

che in Perl diventa ovviamente piu' compatto:

if ( ! @objects ){ say "Nessun elemento"; }
for my $item ( @objects ) { ... }

Tralasciando l'eleganza degli operatori postfissi, l'idea Perl è quella di testare la bontà della lista: se la lista non è valida viene eseguito un blocco di codice, e comunque a seguire sempre il ciclo (che in realtà non viene mai eseguito). In sostanza in Perl non c'è l'esigenza della guardia attorno al ciclo, e questo è quello a cui mi riferivo quando intendevo dire che il ciclo for in Perl è DWIM!

Tuttavia, il dover testare la bontà della lista è una fatica doppia: viene fatta (da Perl) nel ciclo iterativo, e nel "catch" implementato dallo sviluppatore. Siccome Perl sa esattamente se la lista è buona o meno, dovendo eseguire o no il ciclo, è possibile demandare a lui questo ragionamento?
Entra nella stanza For::Else.
For::Else è un filtro sorgente (quindi che riscrive un blocco di codice) che si occupa di mettere la guardia if..else attorno al ciclo iterativo. La sintassi che ne risulta è come la seguente:

for my $item ( @objects ){ ... }
else { say "Nessun elemento"; }


ossia, come il nome suggerisce, viene fuori un for..else.
Bello?
Brutto?
Utile?
Da qui si apre un dibattito agguerrito su chi vuole una funzionalità simile e chi la ritiene inutile. In generale, diversi programmatori Perl vorrebbero un "catch" per gli iteratori, ma l'argomento è molto controverso (si veda qui e qui).

Un momento di pausa: potrebbe unless fungere allo scopo? Ovviamente no, perché sempre di una guardia attorno ad una iterazione si tratterebbe:

unless( @objects ){ say "Nessun elemento"; }
else{ for my $item ( @objects ) { ... } }


Come è noto l'uso di un unless..else è molto poco leggibile, e in generale io penso che l'unless non postfisso sia sostanzialmente inutile.

Un chiarimento per chi proviene da Python: questo linguaggio prevede una versione for..else ma il suo utilizzo appare contorto anche agli amanti dei serpenti. Anzitutto l'uso abbastanza infelice delle parole (e questo vale anche per For::Else): "else", ovvero "altrimenti", indica qualcosa da fare al posto di un'altra cosa. Nel caso del for..else di Python la clausola "else" invece indica qualcosa da eseguire quando il ciclo for termina regolarmente: il ciclo non deve eseguire del tutto o non deve essere terminato in mezzo ad una iterazione (uso di break). Uhm...

Chiarito che Python usa un for..else semanticamente differente da quello di cui si sta parlando qui, si torni alle considerazioni riguardo Perl.

Io personalmente penso non sia una buona idea implementare la clausola else in un iteratore.
Dovendo programmare con differenti linguaggi, spesso molto piu' stupidi che Perl, mi trovo comunque costretto a ricordarmi di dover inserire delle guardie, e quindi non è per me uno sforzo insormontabile "pensare" il mio codice con un test e un caso dedicato a liste "non buone".
Ma questo ovviamente vale per me.
Tuttavia considero che un simile operatore possa confondere chi si avvicina a Perl, che già risulta abbastanza complesso (chi si ricorda che for esegue un aliasing e while no? chi si ricorda che i cicli while sono pigri e i for no?), e ne uscirebbe probabilmente appesantito da un idioma poco utilizzabile.
Anzi poco usato.
Eh si, perché questo è il problema: dove si utilizzerebbe questo caso? A me personalmente viene in mente solo nella reportistica. Un caso che io affronto di frequente è quello di popolare una tabella di visualizzazione (html, o in altro formato) con tuple che provengono da un database, e in questo caso il for si comporta bene: se non ci sono tuple la tabella non viene popolata. Ma l'utente si spaventa se invece che vedere la lista dei pagamenti che deve effettuare vede uno spazio bianco, meglio quindi stampargli una stringa che dica "non ti resta nulla da pagare", e qui scatta il codice di guardia. Ma a parte questi casi, ce ne sono altri in cui si potrebbe avere una utilità pratica del costrutto for..else? A me non ne vengono in mente, e comunque anche il caso d'uso che ho citato prima riguarda piu' che altro il templating che non l'esecuzione del codice stesso, e quindi se proprio vogliamo inserire il for..else pensiamolo per il motore di template.
E se proprio si vuole utilizzare una bruttura, come forse for..else risulta, perché non usare map?

map { my $item = $_; ... } @objects or say "Nessun elemento";

In Perl 6 la situazione infatti è leggermente migliore: il ciclo for si comporta molto similmente all'operatore map, ritornando la lista degli elementi che hanno iterato correttamente, e quindi, a pena di qualche parentesi in piu', si può implementare un else mediante un or e l'idioma di map di cui sopra:

( for @objects -> $item { ... } ) || say "Nessun elemento";

Ancora una volta però è bene considerare la sanità mentale di chi dovrà mettere le mani su questo pezzo di codice, e che probabilmente proveniendo da altri linguaggi, sarà abituato al ben piu' diffuso idioma della guardia.

martedì 21 febbraio 2017

Eclipse 4 è migliore di Eclipse 3?

Per quelli che, come me, ritengo che Eclipse 4 sia stato un pessimo IDE (e lo sia ancora, mannaggia!), un interessante articolo che spiega dove si era giunti con la versione 3.8 e dove si è tornati con le varie versioni 4 che si sono dovute rilasciare per fornire un IDE nuovamente degno del marchio di Eclipse.
Spero vivamente che le prossime versioni pongano fine a tutti i micro-problemi che hanno decisamente fatto scendere Eclipse nella classifica dei miei ambienti preferiti...

PostgreSQL @ Python

Il legame tra Python e PostgreSQL appare sempre piu' forte.
Se da un lato ITPUG sarà anche per questa edizione media partner della conferenza italiana PyCon 8 , la community PostgreSQL viene citato nella sezione Community per l'internazionale PyCon 2017.

My, myself and PHP namespaces...

I'm starting to hate PHP with a passion.
I don't like its syntax, that I find often quite odd. The "foreach" loop is an example, I like much more the Perl or Java like idiom.
Another feature I'm trying to adapt myself to, and that incresead my hate for this language, is namespace.
The namespace definition is awkward: as first it looks like Perl's or Java's package, but it something really much orrible.
While imposing a filesystem layout (similar to Perl or Java), PHP namespaces does not provide a quick way to isolate code, or better, they isolate too much code at a time.
Let's start from the end: consider a class defined in a namespace as follows

namespace NS1\NS2\NS3;

class Foo { .. }


and now the code that should use it

use NS1\NS2\NS3;
$foo = new NS3\Foo();

Yes, you still need to partially qualify the simbol name. This is due to the fact that "use" without an alias argument is equivalent to aliasing the last part of the namespace, that is the two following lines are the same:


use NS1\NS2\NS3;
use use NS1\NS2\NS3 as NS3;

So in order to reference your symbols without any namespace prefix you have to use them all, that is:

use NS1\NS2\NS3\Foo as Foo;
$foo = new Foo();


I clearly don't get the point of using the above in a productive way: namespaces are a common way to avoid name clashing, and therefore they willc contain a set of related objects (I mean, symbols), so why would I need to use them one at a time?

Luckily (or stupidly), since PHP 7 it is possible to import a namespace the way Perl does, that is:

use NS1\NS2\NS3\{ Foo, Bar, Baz} ;

that is the same as

use NS1\NS2\NS3\Foo as Foo;
use NS1\NS2\NS3\Bar as Bar;
use NS1\NS2\NS3\Baz as Baz;

and that allows for the usage of symbol relative name (I mean, really relative name).

The syntax seems to me a crappy copy of the C++ namespace one, except that the latter has an easy way to reference relatively all symbols in an used namespace.

Now, another ugly detail of the PHP namespaces is that every class referenced within a namespace has to belong to the namespace itself or an used namespace. Why is this ugly? Because of the following:


class Logger { ... }

namespace NS1;
class Foo{
  public function __construct(){
    $this->logger = new \Logger();
    ...
  }
}


As you can see, since the Logger class does not belong to any namespace (let's say it belongs to the "main" namespace), it has to be refenced by a leading slash, that is a way to indicate the "main namespace". This is pretty much ugly because PHP could be smart enough to figure out when a symbol is found in the current and used namespaces, and if it is not it can search for it in the "\" main namespace.
Moreover, the above kindof syntax, makes it very hard to refactor existing code into namespaces; suppose you want to move the Logger class into its own namespace: you have to (i) place it into a namespace, (ii) use such namespace and (iii) remove each call to the main "\" namespace as follows

// (i)
namespace Log;

class Logger { ... }

namespace NS1;
// (ii)
use Log\{ Logger };

class Foo{
  public function __construct(){
    // (iii)
   $this->logger = new Logger();
   ...
 }
}


but step (iii) could have been removed if the original call to the Logger-in-main-namespace had been avoided. Think about Perl and its main:: package (pretty much the same as a PHP namespace), that can be omissed if not necessary:

my $x = "hello"; say $x;
$main::x = "hello"; say $x;


Last but not least: the choice of the backslash is terrible to me!
It reminds me the package separator used in Perl 4: $main'x ...
While I accept that a double colon is not optimal, due to some difficulties in editors to render it properly without any confusion with the switch C++ statement, I take it for granted it is a better established approach and makes it a lot more visible the separation.

mercoledì 8 febbraio 2017

How to destroy my fossil repository in one step!

Fossil and Git are two great softwares, and I use them day by day.
Unluckily the former has less support by integrated environment, IDE, and this makes a little easier to deal with Git when working with mainstream development frameworks. But luckily, Fossil has a way to export to Git and, much more itneresting, to do a bidirectional import/export that is to export and re-import a git repository. In other words, you can work on a repository with both git and fossil pretty much at the same time.

Today I decided to realign my fossil repo to a git one, so to have the same logs and timeline available both from command like (i.e., fossil) and IDE tools. But I messed up everything:

fossil export 
  --git 
 --export-marks /sviluppo/fossil/luca.fossil.marks 
  /sviluppo/fossil/luca.fossil
  | git fast-import 
    --export-marks=/sviluppo/fossil/luca.fossil

Who catch the error?
Well, the git mark points to the fossil repository file, not the mark file!
Boom!
A whole repository destroyed in a few seconds.

The only thing that can save in such a situation is a backup, but, shame on me, I didn't have a fully recent one, so I lost part of the history.
Lesson learned: always do a backup before acting on a repository, even if you are supposed to only read from it (as in an export phase).
Lesson learned: do not trust the shell to complete paths and filenames for you.

Oracle SQL Developer: crash all'avvio

Ahimé mi sono trovato, non so per quale motivo, a non avere piu' funzionante il mio Oracle SQL Developer 4.15 su una macchina ubuntu 16.10.
Il problema era un crash, spesso immediato, casuale dell'applicativo, con messaggi e frame di errore ogni volta differenti:

Oracle SQL Developer
Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.



LOAD TIME : 286#
# A fatal error has been detected by the Java Runtime Environment:
#
# SIGSEGV (0xb) at pc=0xe76ab451, pid=23989, tid=0xa82ffb40
#
# JRE version: Java(TM) SE Runtime Environment (8.0_111-b14) (build 1.8.0_111-b14)
# Java VM: Java HotSpot(TM) Server VM (25.111-b14 mixed mode linux-x86 )
# Problematic frame:
# J 6797 C2 oracle.dbtools.util.Array.merge([I[I)[I (225 bytes) @ 0xe76ab451 [0xe76ab2c0+0x191]
#
# Failed to write core dump. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
#
# An error report file with more information is saved as:
# /home/luca/Downloads/sqldeveloper/sqldeveloper/bin/hs_err_pid23989.log
#
# If you would like to submit a bug report, please visit:
# http://bugreport.java.com/bugreport/crash.jsp
#
/home/luca/Downloads/sqldeveloper/sqldeveloper/bin/../../ide/bin/launcher.sh: line 1286: 23989 Aborted (core dumped) ${JAVA} "${APP_VM_OPTS[@]}" ${APP_ENV_VARS} -classpath ${APP_CLASSPATH} ${APP_MAIN_CLASS} "${APP_APP_OPTS[@]}"


o dei blocchi all'avvio:

LOAD TIME : 259Uncaught error fetching image:
java.lang.NullPointerException
at org.netbeans.modules.netbinox.JarBundleFile$CachingEntry.getInputStream(JarBundleFile.java:342)
at org.eclipse.osgi.framework.internal.core.BundleURLConnection.connect(BundleURLConnection.java:53)
at org.eclipse.osgi.framework.internal.core.BundleURLConnection.getInputStream(BundleURLConnection.java:99)
at sun.awt.image.URLImageSource.getDecoder(URLImageSource.java:127)
at sun.awt.image.InputStreamImageSource.doFetch(InputStreamImageSource.java:263)
at sun.awt.image.ImageFetcher.fetchloop(ImageFetcher.java:205)
at sun.awt.image.ImageFetcher.run(ImageFetcher.java:169)



Preso dalla disperazione ho cercato di ovviare con la perspective Database di Eclipse, ma questa è a mio avviso molto insoddisfacente per l'interazione con il database (mentre è valida per lo sviluppo iniziale). Così ho dovuto cercare un modo per aggiustare sqldeveloper, e la soluzione è apparsa molto semplice: rimuovere la variabile di ambiente GNOME_DESKTOP_SESSION_ID:

% unset GNOME_DESKTOP_SESSION_ID
% sh ./sqldeveloper.sh

e io non ho nemmeno Gnome installato (ok le librerie, ma avere un session-id non me lo sarei mai aspettato).
Comunque dopo un po' il problema si è riverificato insistentemente, così ho applicato le seguenti due modifiche al file ~/.sqldeveloper/4.1.5/product.conf:

SetJavaHome /usr/lib/jvm/java-8-openjdk-amd64
SetSkipJ2SDKCheck true

Haiku talk

François Revol ha reso disponibili un set di slide molto interessanti circa il suo talk a Fosdem 2017.
In particolare in queste slide si mostrano alcune delle caratteristiche di Haiku che lo rendono un sistema molto avvincente, anche se a mio avviso ancora molto immaturo (sia per la community, ridotta, che per le integrazioni con software pensati per altri sistemi operativi).
Una delle carattistiche del desktop che personalmente troverei piu' utile è la X-ray navigation.

domenica 5 febbraio 2017

Don't write your own template engine!

We all have done it at least one time: we designed our very-own sucking not-scalable template engine!

I remember when I was a young stupid developer, during my very first job as a contractor, I had to extract some data out of a database (not relational!) and to produce a well formatted PDF letter.
At that time my knowledge was really tiny, but luckily I had in my bag of tools both Perl and LaTeX, so I decided to use both of them (and by the way it was years before OpenOffice too).

As I said I was young, and therefore as pretty much every "green" developer does, I refused to search for and reuse some production ready module or extension (Template Toolkit, just to name it), considering myself enough smarter to develop each required functionality by myself.

So I started developing a Perl engine able to read an INI-like file format: I was extracting data out of the database and placing each record as a set of sections into the file, with special sections used to control the engine itself. Having to deal with text, why not using Perl?
Having done the above, the second phase consisted of producing LaTeX compatible output and run a controlled process to compile the output and produce the result. Again, Perl could do of course the job.

And you can see a recurring error here: as I was not using an engine template on the "reading" side (parsing my very own INI-like file format), I was not using it in the "writing" side too (outputting each single LaTeX command one by one).

So far, so bad, I had a fully working system in less than two days (thank you Perl for regexp!), and my boss was happy with that, the check was in the incoming mail, and I was enough happy too.

I have to confess that the script resulted in around 500+ lines, due also to the fact I was not using "short" comparison operators as I do today (thank you '?:'), and of course maintaining the script was a really pain.

Anyway, I learnt the lesson and since those days I never started developing my very own template engine unless really forced to.
A few years after I had enough experience to recognize the very same error I did in code provided by other developers, and this let me thought that the problem was a cultural one. I cannot say if it is due to impatience or a lack in the preparation of young developers, I tend to balme the latter most since, having worked a few years in the academic field, I had seen too less time spent explaining the importance of a language ecosystem (thank you CPAN!).

sabato 4 febbraio 2017

sysadmin panics: usare X dal terminale...

Il protocollo X-Window, con tutte le sue pecche di sicurezza ed efficienza, risulta comunque uno strumento molto utile per il lavoro da postazioni remote.
Fortunatamente Unix basa tutta la sua configurazione su file di testo, ma a volte questi sono veramente difficili da editare per un umano. Capita allora che per aggiornare il vecchio printcap si usasse una utility grafica. Si noti che sto parlando di printcap, quindi l'era prima di cups, tmux e altre utility che hanno agevolato ulteriormente il lavoro remoto.
Ma non è questo il problema, il vero problema è che il sysadmin inesperto non sa di poter usare X a suo vantaggio. E così, invece che far eseguire l'applicativo grafico sulla macchina remota e visualizzarlo sulla propria, scende alcuni piani di un edificio per andare fisicamente ad agire sulla console della macchina!
Nulla di grave, se non fosse che quando non si trova fisicamente nell'edificio il sysadmin deve prendere la macchina...

perlbrew will have a little of me!

I had a little time to study one of my favorite Perl too: perlbrew
While reading the source code I decided to add a little extra-information on the output of the available command. Such command provides the list of available (i.e., downloadable) Perl versions, but not from where it is going to download them. 
Therefore I applied a patch to show to the outer world the donadloadable links.
And after a few days and a little embarassement for a forgotten failing test, it has been merged!

Hey students, don't buy the teachers' lies!

When I was an university student I had a teacher in the Operating Systems subject that teached me (and a lot of others) to program so bad in shell scripting! I will not name her, but I had to say that today I find the very same errors around the scripts that my colleagues write every day, and this is a kind of watermark of the damage she did.

Luckily I find my way out, studying on other books and practicing on my own (Linux) computer.

So what were the problems?
To understand it must be clear the exercise schema the teacher was adopting, and that was pretty much always the same: a main script (let's call "coordinator" which aim is to parse the argument list and invoke, using recursion, a "worker" script.
Something that can be shown as the following code:

#!/bin/sh
# coordinator

# argument validation...

# export the current directory
# in the path to invoke the worker script
PATH=$PATH:`pwd`
export PATH

# first call of the worker
worker



#!/bin/sh
# worker

# recursion on myself
for f in *
do
if [ -d $f ]
then
worker f
fi
done

# do other work...



The first problem, in my opinion, is the usage of relative paths to invoke the worker script, and therefore the need for exporting the PATH variable. First of all, launching a script with a relative path makes it a little slower to launch, since the shell itself has to search for the script against each PATH entry. Second, and much more important, it is the key to exploitation: not having the control over the full path of the script it is possible to inject a malicious script somewhere in the PATH and use it as a worker.
When I objected the above to the teacher, the answer was to simply invert the PATH manipulation order:

PATH=`pwd`:$PATH
export PATH

But again, this is a kick in the ass of security: what if I name my script as another system wide command? I can alter the behaviour of this and other programs...
So what is the solution? Of course invoke the worker script with an absolute path and to not manipulate the PATH variable. After all, what is the point in showing (to the teacher) you can export a variable?

Another problem is the recursion on the worker script: usually such script was scanning a directory content, invoking itself each time a subdirectory was found. Now, while this can work in theory, you can easily imagine the worker script becoming a fork-bomb. It is quite easy to see how find(1), xargs(1) and friends can help in this situation.

Another oddity that comes into my mind is the way students were forced to test if an argument was an absolute path or a relative one:

case $1 in
/*) # absolute
;;
*) # relative
;;
esac


Do you believe the above is easy to read? Is it efficient and does it scale well? Why not using Unix tools and pipes, regular expressions and awk? even better, getopt anyone?

So, dear ex-teacher, what is the whole point in teaching such shit?

venerdì 3 febbraio 2017

GitLab, PostgreSQL, e la perdita accidentale dei dati

Un socio di ITPUG ha indicato un articolo interessante riguardante un incidente informatico capitato a GitLab. A parte il tecnicismo e l'errore, forse grossolano e sicuramente dettato dallo stress e la fretta (chi è senza peccato scagli la prima pietra...), la parte interessante dell'articolo è l'apertura e la documentazione che GitLab ha voluto fornire a seguito dell'accaduto.
Sicuramente questo atteggiamento ha permesso a GitLab di uscire "meglio" dal disastro, poiché quasi tutti gli sviluppatori hanno apprezzato la documentazione fornita, che ha consentito uno studio postumo utile a chi si troverà in simili situazioni.

mercoledì 1 febbraio 2017

phishing tramite le risposte di subito.it (?)

Sempre piu' spesso ricevo delle risposte "bizzarre" ai miei pochi annunci, e solitamente tutte sono fatte piu' o meno così':


Ciao Luca, ti contatto per l'annuncio xxx.


Ok, se non ne avessi ricevuti molteplici avrei pensato che l'autore andava di fretta. Ora che invece il numero aumenta a dismisura ritengo che si tratti di un tentativo di phishing. Infatti forse si vogliono collezionare numeri di telefono, oppure verificare se tali annunci siano ancora attivi e qualcuno stia rispondendo (magari fornendo il proprio indirizzo email privato, cosa da non fare mai!).
Io ormai tendo a rispondere con una email preconfezionata:

Chiedimi pure quello che vuoi, se ti interessa puoi anche venire a visionare la merce.

Risposta generica, priva di dettagli e che apre la strada ad un ulteriore dialogo.
Che non avviene mai.

Lettera aperta a HERA

Cara HERA,
mi rifiuto di riconoscerti come entità autonoma ed efficiente, adibita, fra le altre cose, alla corretta gestione dei rifiuti urbani.
Succede che devo buttare via dei rifiuti ingombranti, e quindi, da buon utente che PAGA REGOLARMENTE, prenoto il ritiro di tali rifiuti. Da utente "ben pensante" mi rifiuto di seguire alla lettera le disposizioni che vogliono che i rifiuti ingombranti siano posti in strada.
Lo dice l'aggettivo stesso: "ingombranti", che ingombrano, in altre parole che portano via spazio. E quindi posizionarli anzitempo nella strada significa portare via posti auto, creare intralcio e magari anche pericolo (specialmente al buio), per non parlare dell'immagine veramente poco edificante.
Tengo quindi i rifiuti nel mio cortile, pronto a posizionarli in strada appena gli operatori incaricati sarebbero passati con appuntamento diligentemente preso e che coinvolge la fascia oraria 8-13! E già qui si potrebbe avere da dire: chissà quanti clienti perderebbero i professionisti (dentisti, avvocati, geometri) se dessero appuntamenti con simili fasce orarie...
Ma ahimé nessuno passa...fortuna che i miei rifiuti non hanno letto la pubblicità di HERA "a Modena i rifiuti non si sentono abbandonati".

Sollecito una prima volta, e mi viene risposto che i rifiuti avrebbero dovuto trovarsi in strada dalle ore 6 alle ore 20. Ok, a parte il disagio e il degrado già sopra descritto, a cosa serve dare una fascia oraria per il ritiro che è ridotta rispetto a quella effettiva?
Ma inutile porsi domande, occorre obbedire come degli automi, e così piazzo i rifiuti in strada.

Passano 2 giorni, così faccio un ulteriore sollecito, e mi viene risposto che il sollecito impiega da 24 a 48 ore per essere evaso.
Ma stiamo scherzando? Un SOLLECITO invece che accelerare lo smaltimento implica altre 48 ore di attesa?
Finalmente, al terzo giorno, i rifiuti sono stati portati via.

Evviva la gestione dei rifiuti "intelligente", evviva l'essere "green", evviva il servizio offerto a fronte degli euro sborsati!