Discussione:
Iniezione delle dipendenze vs Service Locator
(troppo vecchio per rispondere)
alex
2018-12-16 11:52:07 UTC
Permalink
https://medium.com/@ivorobioff/dependency-injection-vs-service-locator-2bb8484c2e20

cosa ne pensate?
Alessandro Pellizzari
2018-12-16 17:28:19 UTC
Permalink
Post by alex
cosa ne pensate?
Dipende quanto controllo vuoi cedere.

Partiamo da una premessa: un SL implementato come nell'esempio è
pessimo, ma è anche vero che la maggior parte degli sviluppatori in
linguaggi dinamici tende a implementarlo così, per poi "vendere" un
framework che lo fa per te.

Il mio punto è che non serve una libreria esterna per implementare un SL:

class ServiceLocator {
static function getHouse(): House {
static $house = null;
if (is_null($house)) {
$house = new MyHouse();
}
return $house;
}

static function getWindow(): Window {
return new Window();
}
...
}

Vantaggi:
1- puoi avere strict typing
2- l'editor sa che oggetto torni e può autocompletarti i metodi
3- l'editor sa se il SL fornisce un service o meno
4- hai un errore (potenzialmente) molto prima da parte del compilatore

Svantaggi:
1- Devi modificare il SL quando aggiungi un servizio

Io non ho dubbi su cosa scegliere. :P

Ora veniamo alla DI. La DI dà allo sviluppatore controllo totale su cosa
passare a un oggetto. Invece di istanziare un oggetto e passargli il SL,
gli passi direttamente le dipendenze. Lo svantaggio è che se istanzi un
oggetto in profondità nel codice devi passare le dipendenze attraverso
tutto l'albero.

Nella mia esperienza conviene sempre tenere la struttura più piatta
possibile, ma siccome non è sempre facile, io preferisco avere un SL che
passo ai livelli più alti, i quali poi usano DI prendendo la roba dal SL
quando istanziano un oggetto.

Esempio insulso. Classico sito web "MV*".

Istanzio i vari repository (interfacce verso DB, servizi esterni,
logger, ecc.) e li infilo nel SL (o li faccio creare dal SL direttamente
passandogli i parametri di connessione, di solito via env vars).

Poi istanzio il router e passo il SL a ogni
Controller/ViewModel/Presenter/quellocheè.

Il controller può chiedere al SL la connessione al DB, il logger, il
mailer e magari il template engine e (se non li usa direttamente) può
istanziare altra roba passandola con DI. Per esempio può create uno
UserRepository passandogli il DB e il logger e prendere i dati, poi
creare un RichMailer passandogli il mailer, il logger e il template
engine, e infine creare un HtmlRenderer passandogli il template engine,
il template in HTML e i dati tornati dallo UserRepository per mostrare
il risultato all'utente.

Insomma: non è che uno esclude l'altro. :)

Bye.
alex
2018-12-17 07:50:51 UTC
Permalink
Post by Alessandro Pellizzari
Post by alex
cosa ne pensate?
Dipende quanto controllo vuoi cedere.
Partiamo da una premessa: un SL implementato come nell'esempio è
pessimo,
Perchè?
Post by Alessandro Pellizzari
class ServiceLocator {
static function getHouse(): House {
static $house = null;
if (is_null($house)) {
$house = new MyHouse();
}
return $house;
}
static function getWindow(): Window {
return new Window();
}
...
}
1- puoi avere strict typing
2- l'editor sa che oggetto torni e può autocompletarti i metodi
3- l'editor sa se il SL fornisce un service o meno
Cioè?
Post by Alessandro Pellizzari
1- Devi modificare il SL quando aggiungi un servizio
Che sarà mai.
Durante la stesura di un progetto modifiche se fanno ovunque :D
Post by Alessandro Pellizzari
Io non ho dubbi su cosa scegliere. :P
Ora veniamo alla DI. La DI dà allo sviluppatore controllo totale su cosa
passare a un oggetto. Invece di istanziare un oggetto e passargli il SL,
gli passi direttamente le dipendenze. Lo svantaggio è che se istanzi un
oggetto in profondità nel codice devi passare le dipendenze attraverso
tutto l'albero.
Anche l`SL è una dipendenza che verrebbe passata allo stesso modo, o
sbaglio?
Post by Alessandro Pellizzari
Nella mia esperienza conviene sempre tenere la struttura più piatta
possibile, ma siccome non è sempre facile, io preferisco avere un SL che
passo ai livelli più alti, i quali poi usano DI prendendo la roba dal SL
quando istanziano un oggetto.
Per non violare il principio di DI, gli istanziamenti non andrebbero
fatti solo in uno dei file principali (index.php, Controller.php, ecc.)?
Alessandro Pellizzari
2018-12-17 10:51:58 UTC
Permalink
Post by alex
Post by Alessandro Pellizzari
Partiamo da una premessa: un SL implementato come nell'esempio è
pessimo,
Perchè?
Perché mette in un calderone tutto.

In questo modo non sai che interfaccia implementa il servizio che ti
viene tornato quando lo richiedi, e soprattutto non sai se c'è un
servizio con quel nome, costringendoti a verificare ovunque se la
chiamata a ->get(NomeServizio) ha tornato null, e a gestire l'errore
ovunque usi il SL.

Se la confronti con il pezzo di codice che ho postato io, è chiaro che
se un servizio non esiste, non hai il getter per quel servizio, e hai
errore in compilazione, e se il getter esiste, il getter stesso può
gestire l'errore in caso il servizio non venga istanziato.
Post by alex
Post by Alessandro Pellizzari
1- puoi avere strict typing
2- l'editor sa che oggetto torni e può autocompletarti i metodi
3- l'editor sa se il SL fornisce un service o meno
Cioè?
Vedi sopra: se la classe SL non fornisce il metodo getHouse l'editor può
dirti che non esiste tramite semplice inspection. Ma l'editor, se chiami
->get("house") non ha idea se il SL tornerà qualcosa, quindi non ti
segnala l'errore in caso manchi.
Post by alex
Post by Alessandro Pellizzari
Ora veniamo alla DI. La DI dà allo sviluppatore controllo totale su cosa
passare a un oggetto. Invece di istanziare un oggetto e passargli il SL,
gli passi direttamente le dipendenze. Lo svantaggio è che se istanzi un
oggetto in profondità nel codice devi passare le dipendenze attraverso
tutto l'albero.
Anche l`SL è una dipendenza che verrebbe passata allo stesso modo, o
sbaglio?
Può esserlo. Io preferisco essere esplicito e passarla con DI, ma
potrebbe essere un singleton (o un borg, per i pignoli :P) e lo istanzi
dove ti serve.
Post by alex
Per non violare il principio di DI, gli istanziamenti non andrebbero
fatti solo in uno dei file principali (index.php, Controller.php, ecc.)?
Gli istanziamenti li fai o nel index.php (e poi li infili nel SL) o nel
SL stesso. In questo modo hai tutto nello stesso posto. Nei controller
chiedi al SL di darti l'istanza, e lui sa se deve dartene una già fatta
o deve crearne una al volo.

Questo è uno dei modi. Non è detto che sia il migliore. Spero non sia il
peggiore, visto che è quello che uso di solito. :D

Bye.
alex
2018-12-18 13:36:33 UTC
Permalink
Post by Alessandro Pellizzari
Post by alex
Per non violare il principio di DI, gli istanziamenti non andrebbero
fatti solo in uno dei file principali (index.php, Controller.php, ecc.)?
Gli istanziamenti li fai o nel index.php (e poi li infili nel SL) o nel
SL stesso.
Oppure, per tenere ben organizzato il codice, tramite una factory
(ServiceLocationFactory)
Alessandro Pellizzari
2018-12-20 12:42:53 UTC
Permalink
Post by alex
Oppure, per tenere ben organizzato il codice, tramite una factory
(ServiceLocationFactory)
Una Factory dovrebbe servire a creare oggetti che implementano la stessa
interfaccia.

Quindi una ServiceLocationFactory creerebbe ServiceLocators, non i
servizi stessi.

Puoi avere diverse factory, una per servizio storato nel SL, ma secondo
me è un overkill inutile.

Bye.
alex
2018-12-20 13:49:39 UTC
Permalink
Post by Alessandro Pellizzari
Post by alex
Oppure, per tenere ben organizzato il codice, tramite una factory
(ServiceLocationFactory)
Una Factory dovrebbe servire a creare oggetti che implementano la stessa
interfaccia.
Ossia?
Post by Alessandro Pellizzari
Quindi una ServiceLocationFactory creerebbe ServiceLocators, non i
servizi stessi.
Addirittura creare più ServiceLocators :-|
Si perderebbe la centralità :D
Alessandro Pellizzari
2018-12-20 17:39:37 UTC
Permalink
Post by alex
Post by Alessandro Pellizzari
Una Factory dovrebbe servire a creare oggetti che implementano la
stessa interfaccia.
Ossia?
function loggerFactory($pippo: int): LoggerInterface {
switch ($pippo) {
case 0: return new StubLogger();
case 1: return new ConsoleLogger();
case 2: return new SuperLogger();
default: throw new Exception("Unknown logger");
}
}

Come vedi, avere un ServiceLocatorFactory non ha senso.

Bye.
alex
2018-12-20 18:06:53 UTC
Permalink
Post by Alessandro Pellizzari
Post by alex
Post by Alessandro Pellizzari
Una Factory dovrebbe servire a creare oggetti che implementano la
stessa interfaccia.
Ossia?
function loggerFactory($pippo: int): LoggerInterface {
  switch ($pippo) {
    case 0: return new StubLogger();
    case 1: return new ConsoleLogger();
    case 2: return new SuperLogger();
    default: throw new Exception("Unknown logger");
  }
}
Come vedi, avere un ServiceLocatorFactory non ha senso.
Bye.
E questa cosa cos'è?
Poi i logger, gli gnomi, i folletti?

Senti, per come la intendo io, guarda qua

class ServiceLocatorFactory {
function crate(): ServiceLocator {
$a = ...;
$b = ...;
$c = ...;
return new ServiceLocator($a,$b,$c);
}
}
}
alex
2018-12-20 18:28:05 UTC
Permalink
Post by alex
class ServiceLocatorFactory {
 function crate(): ServiceLocator {
    $a = ...;
    $b = ...;
    $c = ...;
    return new ServiceLocator($a,$b,$c);
  }
 }
}
Altro esempio

class ServiceLocatorFactory {
function crate(): ServiceLocator {
$x = new ServiceLocator();

$x->setServiceA(new A);
$x->setServiceB(new B);
$x->setServiceC(new C);

return $x;
}
}
}
Alessandro Pellizzari
2018-12-21 09:42:30 UTC
Permalink
Post by alex
Senti, per come la intendo io, guarda qua
class ServiceLocatorFactory {
function crate(): ServiceLocator {
$a = ...;
$b = ...;
$c = ...;
return new ServiceLocator($a,$b,$c);
}
}
}
Questa non e` una Factory. Al massimo e` un Builder, ma nemmeno quello.

Una Factory (fabbrica, in italiano) produce piu` di un oggetto.

Se devi costruirne solo uno, tanto vale farlo nel costruttore del
ServiceLocator (o nell'istanziatore, se e` un singleton).

Bye.
alex
2018-12-21 13:47:44 UTC
Permalink
Post by Alessandro Pellizzari
Questa non e` una Factory. Al massimo e` un Builder, ma nemmeno quello.
Differenza tra factory e builder?
f***@gmail.com
2018-12-21 23:45:54 UTC
Permalink
Post by alex
Post by Alessandro Pellizzari
Questa non e` una Factory. Al massimo e` un Builder, ma nemmeno quello.
Differenza tra factory e builder?
Un factory costruisce un oggetto al volo e lo ritorna, solitamente è giusto
un wrapper per un costruttore.
Un builder restituisce un oggetto non costruibile in un singolo step, e.g.
quando solo il costruttore non da un oggetto utilizzabile.

Risposta a parte, non capisco perché parti per la tangente quando qualcuno
ti cerca di spiegare in dettaglio qualcosa che chiedi. Per questo thread,
ad esempio, questa era l'ultima domanda che sarebbe venuta in mente a
qualsiasi altra persona. Così, anche se magari non è vero, sembra che
scrivi per scrivere, e non leggi con attenzione chi s'impegna regalandoti
il suo tempo. M2C.


Ciao!
alex
2018-12-22 10:55:11 UTC
Permalink
Post by f***@gmail.com
Un factory costruisce un oggetto al volo e lo ritorna, solitamente è giusto
un wrapper per un costruttore.
O restituisce una specifica versione di un oggetto che però implementa
sempre la stessa interfaccia (come ha illustrato Alessandro)?
Post by f***@gmail.com
Un builder restituisce un oggetto non costruibile in un singolo step, e.g.
quando solo il costruttore non da un oggetto utilizzabile.
Ad esempio?
Alessandro Pellizzari
2018-12-22 16:12:49 UTC
Permalink
Post by alex
Post by f***@gmail.com
Un factory costruisce un oggetto al volo e lo ritorna, solitamente è giusto
un wrapper per un costruttore.
O restituisce una specifica versione di un oggetto che però implementa
sempre la stessa interfaccia (come ha illustrato Alessandro)?
Per definizione, un oggetto implementa sempre la stessa interfaccia. Non
esistono "versioni di un oggetto".

Una factory restituisce oggetti di classi diverse, che implementano la
stessa interfaccia.

Se una factory torna sempre lo stesso oggetto della stessa classe, che
implementa la stessa interfaccia, puoi eliminare la factory e
l'interfaccia, che non servono a niente, e ti rimane solo la classe col
suo costruttore.
Post by alex
Post by f***@gmail.com
Un builder restituisce un oggetto non costruibile in un singolo step, e.g.
quando solo il costruttore non da un oggetto utilizzabile.
Ad esempio?
Ad esempio

$controller = ControllerBuilder::create()
->withRequest($req)
->withOutput(new HtmlRenderer())
->withDb($contentDb)
->build();

Il controller non può funzionare senza una Request, senza una
connessione al DB e senza sapere dove mandare l'output.

Se, per qualsiasi motivo, non hai tutte le informazioni disponibili
quando lo crei, puoi creare un builder e passarlo alle varie fasi della
pipeline, che aggiungono i pezzi che mancano, e alla fine chiami
`build()` che costruisce il Controller vero e proprio, da usare nel Router.

Se chiami `build` senza aver settato tutte le parti richieste, torna un
errore e non ti restituisce il controller. Se non chiami `build` alla
fine, hai un ControllerBuilder e non un Controller, quindi non hai
l'interfaccia adatta al Router.

È praticamente Dependency Injection fatta a passi successivi, invece che
passare tutto nel costruttore dell'oggetto.

Sono tecniche che si usano spesso in linguaggi strictly typed, e in PHP
perdono un po' di senso, ma sono comunque utili per catturare errori in
certe circostanze.

Bye.
alex
2018-12-22 16:33:53 UTC
Permalink
Post by Alessandro Pellizzari
Se chiami `build` senza aver settato tutte le parti richieste, torna un
errore e non ti restituisce il controller
Quindi naturalmente all'interno di build() bisogna prima di tutto
verificare che tutto sia stato settato a dovere?
Alessandro Pellizzari
2018-12-22 16:46:07 UTC
Permalink
Post by alex
Post by Alessandro Pellizzari
Se chiami `build` senza aver settato tutte le parti richieste, torna un
errore e non ti restituisce il controller
Quindi naturalmente all'interno di build() bisogna prima di tutto
verificare che tutto sia stato settato a dovere?
Normalmente la `build()` chiama semplicemente il costruttore
dell'oggetto che sta generando, passandogli tutte le dipendenze.

A quel punto è il costruttore stesso che deve verificare che le
dipendenze siano valide (tramite strict-typing e `if !is_null(...)`, se
serve).

In questo modo hai i controlli in un posto solo (il costruttore
dell'oggetto finito) e non importa come lo crei, avrai comunque gli errori.

I Builder solitamente sono abbastanza "stupidi" come classi.

Bye.
alex
2018-12-22 17:37:13 UTC
Permalink
Post by Alessandro Pellizzari
Normalmente la `build()` chiama semplicemente il costruttore
dell'oggetto che sta generando, passandogli tutte le dipendenze.
Appunto, quindi il metodo create() cosa fa?
Alessandro Pellizzari
2018-12-23 15:18:37 UTC
Permalink
Post by alex
Post by Alessandro Pellizzari
Normalmente la `build()` chiama semplicemente il costruttore
dell'oggetto che sta generando, passandogli tutte le dipendenze.
Appunto, quindi il metodo create() cosa fa?
Te lo spiego con un esempio:

class Controller {
private $request;
private $output;
private $logger;

public function __construct($req, $out, $logger) {
if (is_null($req) || is_null($out) || is_null($logger)) {
throw new Exception('Missing dependencies');
}
$this->request = $req;
$this->output = $out;
$this->logger = $logger;
}
}

class ControllerBuilder {
private $request;
private $output;
private $logger;

public static function create() {
$builder = new ControllerBuilder();
$builder->logger = new ConsoleLogger();
}

public function withRequest($req) {
$this->request = $req;
return $this;
}

public function withoutput($out) {
$this->output = $out;
return $this;
}

public function withLogger($logger) {
$this->logger = $logger;
return $this;
}

public function build() {
return new Controller($this->request, $this->output, $this->logger);
}
}

Come dicevo: assolutamente stupido. Il suo unico scopo è di permetterti
di costruire un oggetto a step, ed eventualmente di definire dei valori
di default.

Bye.
alex
2018-12-23 17:43:01 UTC
Permalink
Post by Alessandro Pellizzari
public static function create() {
$builder = new ControllerBuilder();
$builder->logger = new ConsoleLogger();
}
??????????????????????????????????????????
bohhhhhhhhhh :D

$builder a chi ed a che serve????
Alessandro Pellizzari
2018-12-23 17:52:19 UTC
Permalink
Post by alex
Post by Alessandro Pellizzari
public static function create() {
$builder = new ControllerBuilder();
$builder->logger = new ConsoleLogger();
}
??????????????????????????????????????????
bohhhhhhhhhh :D
$builder a chi ed a che serve????
Complimenti per aver trovato un bug in 70 righe di codice che ho scritto
di getto per aiutarti.

Buon Natale anche a te.
alex
2018-12-23 17:58:05 UTC
Permalink
Post by Alessandro Pellizzari
Complimenti per aver trovato un bug in 70 righe di codice che ho scritto
di getto per aiutarti.
Hai voluto tu scriverle :D
La domanda che ho fatto era abbastanza semplice.
La risposta poteva essere semplicemente: create() non serve a un bel niente.
Ma siccome te le vai cercando :D
Post by Alessandro Pellizzari
Buon Natale anche a te.
Direi che una pausa natalizia ci serve proprio.
Buon Natale anche a te!!!
f***@gmail.com
2018-12-24 12:22:52 UTC
Permalink
ma con che faccia e che coraggio...
altro che buon natale :(
alex
2018-12-30 13:38:05 UTC
Permalink
Post by f***@gmail.com
ma con che faccia e che coraggio...
altro che buon natale :(
C'è qualche problema?
Non capisco?

alex
2018-12-22 12:04:23 UTC
Permalink
Post by f***@gmail.com
Un builder restituisce un oggetto non costruibile in un singolo step, e.g.
quando solo il costruttore non da un oggetto utilizzabile.
In pratica:

$pizza = new Pizza($farina_adatto, $lievito_adatto);
$pizza->metti($olive_scelte_dal_cliente1);
$pizza->metti($olio_scelto_dal_cliente1);
return $pizza;

$pizza = new Pizza($farina_adatto, $lievito_adatto);
$pizza->metti($olive_scelte_dal_cliente2);
$pizza->metti($olio_scelto_dal_cliente2);
return $pizza;

????
alex
2018-12-20 15:18:54 UTC
Permalink
Post by Alessandro Pellizzari
Post by alex
Post by Alessandro Pellizzari
Ora veniamo alla DI. La DI dà allo sviluppatore controllo totale su cosa
passare a un oggetto. Invece di istanziare un oggetto e passargli il SL,
gli passi direttamente le dipendenze. Lo svantaggio è che se istanzi un
oggetto in profondità nel codice devi passare le dipendenze attraverso
tutto l'albero.
Perchè istanziare in profondità (preferisco farlo solo in index.php o
nell'SL)?
Post by Alessandro Pellizzari
Post by alex
Anche l`SL è una dipendenza che verrebbe passata allo stesso modo, o
sbaglio?
Può esserlo. Io preferisco essere esplicito e passarla con DI, ma
potrebbe essere un singleton (o un borg, per i pignoli :P) e lo istanzi
dove ti serve.
Post by alex
Per non violare il principio di DI, gli istanziamenti non andrebbero
fatti solo in uno dei file principali (index.php, Controller.php, ecc.)?
Gli istanziamenti li fai o nel index.php (e poi li infili nel SL) o nel
SL stesso. In questo modo hai tutto nello stesso posto.
Appunto.
Post by Alessandro Pellizzari
Nella mia esperienza conviene sempre tenere la struttura più piatta
possibile, ma siccome non è sempre facile, io preferisco avere un SL >che
passo ai livelli più alti, i quali poi usano DI prendendo la roba dal >SL
quando istanziano un oggetto.
In profondità suppongo.
Prima dici che vuoi instanziare in profondità, poi in superfice (SL),
poi di nuovo in profondità, boh :D
Alessandro Pellizzari
2018-12-20 17:37:11 UTC
Permalink
Post by alex
Post by Alessandro Pellizzari
Nella mia esperienza conviene sempre tenere la struttura più piatta
possibile, ma siccome non è sempre facile, io preferisco avere un SL che
passo ai livelli più alti, i quali poi usano DI prendendo la roba dal SL
quando istanziano un oggetto.
In profondità suppongo.
Prima dici che vuoi instanziare in profondità, poi in superfice (SL),
poi di nuovo in profondità, boh :D
Il SL è "parallelo", non in profondità.

Il SL viene creato da index.php (profondità 0), e passato ai controller
(via router o via singleton)

I servizi vengono creati alla bisogna dal SL.

Siccome è il controller (profondità 1) che invoca i servizi dal SL, si
istanziano quasi in superficie.

Poi il controller può passare i servizi più giù, se necessario, via DI.
Per esempio passando il logger alla view (prof. 2) che lo passa al
template engine (prof. 3), che magari usa un minificatore (prof. 4), che
magari ha un DOM parser (prof. 5), ecc. ecc.

Bye.
alex
2018-12-20 18:21:48 UTC
Permalink
Post by Alessandro Pellizzari
Il SL è "parallelo", non in profondità.
Il SL viene creato da index.php (profondità 0), e passato ai controller
(via router o via singleton)
I servizi vengono creati alla bisogna dal SL.
Siccome è il controller (profondità 1) che invoca i servizi dal SL, si
istanziano quasi in superficie.
Poi il controller può passare i servizi più giù, se necessario, via DI.
In che modo?
La DI dovrebbe essere fatta (tramite costruttore o setter) solo in
superfice dall'index.php o dall'SL.
Post by Alessandro Pellizzari
Per esempio passando il logger alla view (prof. 2) che lo passa al
template engine (prof. 3), che magari usa un minificatore (prof. 4), che
magari ha un DOM parser (prof. 5), ecc. ecc.
Bye.
alex
2018-12-20 19:19:52 UTC
Permalink
Post by alex
La DI dovrebbe essere fatta (tramite costruttore o setter) solo in
superfice dall'index.php o dall'SL.
O dall'SLF (ServiceFactoryLocator), vedi l'altro post.

$x = new ServiceLocator();// te lo ricordi?

// iniezione di A, B, C (vedi l'altro post)

$tester = new Tester;
// iniettiamo un debbugger nel tester (ecco la DI di cui parlavo)
$tester->setDebugger(new Debugger);
$x->setServiceTest($tester);

return $x;// esattamente come nell'altro post
Alessandro Pellizzari
2018-12-21 09:45:08 UTC
Permalink
Post by alex
$x = new ServiceLocator();// te lo ricordi?
// iniezione di A, B, C (vedi l'altro post)
$tester = new Tester;
// iniettiamo un debbugger nel tester (ecco la DI di cui parlavo)
$tester->setDebugger(new Debugger);
$x->setServiceTest($tester);
return $x;// esattamente come nell'altro post
Stai usando la DI per iniettare dipendenze nel Service Locator.

Per definizione il SL dovrebbe essere quello che gestisce TUTTE le
dipendenze.

Lo stai facendo al contrario.

Bye.
f***@gmail.com
2018-12-17 02:46:07 UTC
Permalink
Post by alex
cosa ne pensate?
La fine:

"Hope this article cleared some things up for you and you enjoyed reading it.
If not, then you must be already smartest programer out there"
Well maybe not, Igor "software developer since 2010" you can just ... .. .
'nuf said.
Ha solo scritto in breve come si usano.

Alessandro in un post ha scritto meglio e più chiaramente quello di cui
voleva parlare.

Quindi niente, se conosci Igor di persona puoi dirgli che, visto che ho un
ad-blocker, oltre la figura meschia, nemmno si prenderà il centesimo del
mio click.

Ah, ma prima o poi tutti 'sti poveracci spariranno, mica che no.


Ciao!
Loading...