<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Dev-Iadicola</title>
    <description>The latest articles on DEV Community by Dev-Iadicola (@dev_iadicola).</description>
    <link>https://dev.to/dev_iadicola</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2138925%2F6dd30c44-71a1-4568-a668-759ac9486600.png</url>
      <title>DEV Community: Dev-Iadicola</title>
      <link>https://dev.to/dev_iadicola</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dev_iadicola"/>
    <language>en</language>
    <item>
      <title>Factory Method: creare senza conoscere</title>
      <dc:creator>Dev-Iadicola</dc:creator>
      <pubDate>Tue, 11 Aug 2026 17:00:12 +0000</pubDate>
      <link>https://dev.to/dev_iadicola/factory-method-creare-senza-conoscere-1nb5</link>
      <guid>https://dev.to/dev_iadicola/factory-method-creare-senza-conoscere-1nb5</guid>
      <description>&lt;h2&gt;
  
  
  new e una dipendenza concreta
&lt;/h2&gt;

&lt;p&gt;Ogni volta che scrivi &lt;code&gt;new MysqlSchemaBuilder()&lt;/code&gt;, stai creando una &lt;strong&gt;dipendenza concreta&lt;/strong&gt;. Il codice chiamante ora sa esattamente quale classe istanziare — e se domani devi supportare PostgreSQL, devi trovare e modificare ogni punto dove quel &lt;code&gt;new&lt;/code&gt; compare. Il &lt;strong&gt;Factory Method&lt;/strong&gt; risolve questo problema delegando la creazione a un metodo che le sottoclassi possono sovrascrivere, o che una logica interna può personalizzare in base al contesto.&lt;/p&gt;

&lt;p&gt;Il pattern e sottilmente diverso dall'&lt;strong&gt;Abstract Factory&lt;/strong&gt;: non crea famiglie di oggetti correlati, ma singoli oggetti il cui tipo concreto dipende dal contesto. In Soft PHP MVC, &lt;code&gt;SchemaBuilder::make()&lt;/code&gt; ispeziona il driver configurato e restituisce il builder corretto — &lt;code&gt;MysqlSchemaBuilder&lt;/code&gt;, &lt;code&gt;PostgresSchemaBuilder&lt;/code&gt;, &lt;code&gt;SqliteSchemaBuilder&lt;/code&gt;, &lt;code&gt;MariaDbBuilder&lt;/code&gt; — senza che il chiamante debba saperlo. La decisione e centralizzata in un unico punto, non dispersa nel codice applicativo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cos'e il Factory Method: definizione e struttura
&lt;/h2&gt;

&lt;p&gt;Il &lt;strong&gt;Gang of Four&lt;/strong&gt; definisce il Factory Method come un pattern creazionale che "definisce un'interfaccia per creare un oggetto, ma lascia alle sottoclassi la decisione su quale classe istanziare. Il Factory Method permette a una classe di rinviare l'istanziazione alle sottoclassi". Gli attori sono: il &lt;strong&gt;Creator&lt;/strong&gt; (la classe con il metodo factory), il &lt;strong&gt;ConcreteCreator&lt;/strong&gt; (la sottoclasse che decide il tipo concreto), il &lt;strong&gt;Product&lt;/strong&gt; (l'interfaccia del prodotto), e il &lt;strong&gt;ConcreteProduct&lt;/strong&gt; (l'implementazione specifica).&lt;/p&gt;

&lt;p&gt;Il cuore del pattern e la separazione tra la &lt;strong&gt;logica di creazione&lt;/strong&gt; e la &lt;strong&gt;logica di utilizzo&lt;/strong&gt;. Chi usa l'oggetto non sa come e stato creato; chi lo crea non sa come verra usato. Questa separazione permette di cambiare le regole di creazione senza impattare il codice che usa l'oggetto — e viceversa. Il Dependency Inversion Principle nella sua applicazione più diretta alla creazione degli oggetti.&lt;/p&gt;

&lt;h2&gt;
  
  
  Il pattern make() nel framework
&lt;/h2&gt;

&lt;p&gt;Il &lt;code&gt;make()&lt;/code&gt; statico e il &lt;strong&gt;Factory Method adottato sistematicamente&lt;/strong&gt; in Soft PHP MVC. &lt;code&gt;CsrfService::make()&lt;/code&gt;, &lt;code&gt;EncryptionService::make()&lt;/code&gt;, &lt;code&gt;SessionService::make()&lt;/code&gt; — ogni service espone un metodo factory che incapsula la logica di creazione. Oggi alcuni restituiscono semplicemente &lt;code&gt;new static()&lt;/code&gt;; domani potrebbero restituire un singleton, leggere una configurazione, o risolvere da un container. Il punto di creazione e uno solo, e può evolvere senza ripercussioni sul resto del codice.&lt;/p&gt;

&lt;p&gt;La forza del Factory Method e nella &lt;strong&gt;promessa che fa al codice chiamante&lt;/strong&gt;: "non ti preoccupare del come, dimmi solo cosa ti serve". &lt;code&gt;SchemaBuilder::make()&lt;/code&gt; potrebbe creare l'oggetto con &lt;code&gt;new&lt;/code&gt;, pescarlo da una cache, o costruirlo con dieci dipendenze — il chiamante non lo sa e non deve saperlo. Questa ignoranza deliberata e il cuore del disaccoppiamento. Il Factory Method non nasconde complessità — la isola in un punto dove può essere gestita senza contaminare il codice che consuma il prodotto.&lt;/p&gt;

&lt;h3&gt;
  
  
  Vantaggi concreti del pattern make()
&lt;/h3&gt;

&lt;p&gt;L'adozione sistematica di &lt;code&gt;make()&lt;/code&gt; nel framework porta vantaggi misurabili:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Punto di creazione unico&lt;/strong&gt; — ogni modifica alla logica di istanziazione avviene in un solo metodo&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Evoluzione senza breaking change&lt;/strong&gt; — passare da &lt;code&gt;new static()&lt;/code&gt; a singleton o pool richiede zero modifiche al codice chiamante&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Naming semantico&lt;/strong&gt; — &lt;code&gt;make()&lt;/code&gt; comunica "sto creando un'istanza pronta all'uso", diverso da un costruttore generico&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Testabilita&lt;/strong&gt; — il factory method può essere sovrascritto in una sottoclasse di test per restituire mock o stub&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consistenza&lt;/strong&gt; — ogni service si istanzia allo stesso modo, riducendo il carico cognitivo per chi legge il codice&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Factory Method vs costruttore: una questione di nomi
&lt;/h2&gt;

&lt;p&gt;Un costruttore non può avere un &lt;strong&gt;nome semantico&lt;/strong&gt;. &lt;code&gt;new Connection($config)&lt;/code&gt; non dice se stai creando una connessione nuova o riutilizzando una esistente. &lt;code&gt;Connection::fromConfig($config)&lt;/code&gt; e &lt;code&gt;Connection::forTesting()&lt;/code&gt; sono Factory Method con nomi che comunicano l'intento. Il nome e documentazione che il compilatore verifica — non può diventare obsoleto come un commento. Un factory method ben nominato e il miglior tipo di documentazione: preciso, verificabile, impossibile da ignorare.&lt;/p&gt;

&lt;p&gt;In PHP, i &lt;strong&gt;named constructor&lt;/strong&gt; — metodi statici che restituiscono &lt;code&gt;new static(...)&lt;/code&gt; — sono la forma più idiomatica del Factory Method. Il framework ne usa diversi: &lt;code&gt;Migration::table()&lt;/code&gt; per creare migrazioni, &lt;code&gt;Seeder::table()&lt;/code&gt; per creare seeder, &lt;code&gt;Column::make()&lt;/code&gt; per definire colonne. Ogni nome racconta cosa stai costruendo e perché. La proliferazione di named constructor non e un segno di over-engineering — e un segno di API che comunicano con chiarezza.&lt;/p&gt;

&lt;h3&gt;
  
  
  Factory Method e PHP 8.4
&lt;/h3&gt;

&lt;p&gt;Le &lt;strong&gt;novità di PHP 8.4&lt;/strong&gt; rendono il Factory Method ancora più espressivo. Le property hooks permettono di validare i parametri nel momento dell'assegnazione, riducendo la logica nel costruttore. I tipi di intersezione permettono di restituire oggetti che soddisfano più interfacce contemporaneamente. E le closure di prima classe rendono possibile passare factory method come callable, abilitando pattern di lazy creation e deferred resolution che prima richiedevano classi dedicate.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quando il factory e troppo
&lt;/h2&gt;

&lt;p&gt;Non ogni &lt;code&gt;new&lt;/code&gt; ha bisogno di un factory. &lt;strong&gt;Value object semplici&lt;/strong&gt;, DTO, eccezioni — crearli direttamente e perfettamente legittimo. Il Factory Method serve quando: il tipo concreto può variare, la logica di creazione e complessa, o vuoi un punto di estensione per il futuro. Se la classe non cambiera mai e il costruttore ha zero o un parametro, &lt;code&gt;new&lt;/code&gt; e la scelta giusta. L'over-engineering e un costo reale, non solo teorico.&lt;/p&gt;

&lt;p&gt;Ecco una &lt;strong&gt;guida pratica&lt;/strong&gt; per decidere:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Usa new&lt;/strong&gt; — value object, DTO, eccezioni, classi con costruttore semplice e tipo fisso&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Usa make()&lt;/strong&gt; — service, repository, handler, classi con logica di creazione non banale&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Usa named constructor&lt;/strong&gt; — quando lo stesso tipo può essere creato da input diversi (fromArray, fromRequest, forTesting)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Usa Abstract Factory&lt;/strong&gt; — quando devi creare famiglie di oggetti correlati che variano insieme&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Il &lt;strong&gt;pragmatismo&lt;/strong&gt; e la differenza tra conoscere i pattern e sapere quando applicarli. Un codebase dove ogni oggetto passa attraverso un factory e un codebase over-engineered. Un codebase dove i punti di creazione critici hanno un factory e il resto usa &lt;code&gt;new&lt;/code&gt; e un codebase che bilancia flessibilita e semplicità — e quello e l'obiettivo di ogni architettura PHP ben progettata.&lt;/p&gt;




&lt;p&gt;👉 &lt;strong&gt;&lt;a href="https://iadicola.it/articoli/factory-method-creare-senza-conoscere?utm_source=devto&amp;amp;utm_medium=social" rel="noopener noreferrer"&gt;Leggi l'articolo completo su iadicola.it&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>php84</category>
      <category>orm</category>
      <category>architettura</category>
      <category>designpattern</category>
    </item>
    <item>
      <title>Quick note: Adapter Pattern nel mail service</title>
      <dc:creator>Dev-Iadicola</dc:creator>
      <pubDate>Mon, 10 Aug 2026 17:00:15 +0000</pubDate>
      <link>https://dev.to/dev_iadicola/quick-note-adapter-pattern-nel-mail-service-34an</link>
      <guid>https://dev.to/dev_iadicola/quick-note-adapter-pattern-nel-mail-service-34an</guid>
      <description>&lt;h2&gt;
  
  
  Quando il provider cambia nome
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;sendinblue/api-v3-sdk&lt;/code&gt; e diventato &lt;code&gt;getbrevo/brevo-php&lt;/code&gt;. Non un aggiornamento: un &lt;strong&gt;rebranding&lt;/strong&gt;. Il namespace e passato da &lt;code&gt;SendinBlue\Client&lt;/code&gt; a &lt;code&gt;Brevo\Client&lt;/code&gt;. Senza un adapter, ogni punto del codice che usava l'SDK avrebbe dovuto cambiare — e in un'applicazione reale, quei punti possono essere decine. Un rebranding del vendor non dovrebbe mai causare un refactoring nel codice applicativo. Se lo causa, manca un livello di astrazione.&lt;/p&gt;

&lt;p&gt;L'&lt;strong&gt;Adapter Pattern&lt;/strong&gt; wrappa l'interfaccia di un componente esterno in un'interfaccia che il nostro codice conosce. &lt;code&gt;MailService&lt;/code&gt; espone &lt;code&gt;send()&lt;/code&gt; con i nostri tipi — &lt;code&gt;MailMessage&lt;/code&gt;, &lt;code&gt;MailRecipient&lt;/code&gt; — e traduce internamente verso l'SDK di Brevo. Il codice applicativo chiama &lt;code&gt;MailService::make()-&amp;gt;send($message)&lt;/code&gt; e non sa se sotto c'e Brevo, SendGrid, Mailgun o un file di log. L'adapter e il confine tra il nostro dominio e il mondo esterno.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cos'e l'Adapter Pattern: definizione e varianti
&lt;/h2&gt;

&lt;p&gt;Il &lt;strong&gt;Gang of Four&lt;/strong&gt; definisce l'Adapter come un pattern strutturale che "converte l'interfaccia di una classe in un'altra interfaccia che il client si aspetta. L'Adapter permette a classi con interfacce incompatibili di collaborare". Esistono due varianti classiche: l'&lt;strong&gt;Object Adapter&lt;/strong&gt; (usa la composizione, wrappando l'oggetto adattato) e il &lt;strong&gt;Class Adapter&lt;/strong&gt; (usa l'ereditarieta multipla, non disponibile in PHP).&lt;/p&gt;

&lt;p&gt;In PHP, la variante naturale e l'&lt;strong&gt;Object Adapter&lt;/strong&gt;: la classe adapter ha una proprieta privata che contiene l'oggetto adattato, e i metodi dell'adapter delegano all'oggetto adattato dopo aver tradotto i parametri e i valori di ritorno. Il &lt;code&gt;MailService&lt;/code&gt; di Soft PHP MVC e un Object Adapter puro: mantiene un'istanza del client Brevo come dipendenza interna e traduce ogni chiamata dal vocabolario del framework al vocabolario dell'SDK.&lt;/p&gt;

&lt;h3&gt;
  
  
  La struttura del MailService come adapter
&lt;/h3&gt;

&lt;p&gt;Il &lt;code&gt;MailService&lt;/code&gt; nel framework separa tre responsabilità:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Interfaccia pubblica&lt;/strong&gt; — metodi come &lt;code&gt;send()&lt;/code&gt;, &lt;code&gt;sendTemplate()&lt;/code&gt; con tipi del framework (&lt;code&gt;MailMessage&lt;/code&gt;, &lt;code&gt;MailRecipient&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Traduzione&lt;/strong&gt; — conversione da &lt;code&gt;MailRecipient&lt;/code&gt; a &lt;code&gt;Brevo\Client\Model\SendSmtpEmailTo&lt;/code&gt;, da &lt;code&gt;MailMessage&lt;/code&gt; alla struttura richiesta dall'API&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Comunicazione&lt;/strong&gt; — la chiamata effettiva all'SDK di Brevo con error handling specifico del provider&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Questa separazione permette di cambiare il provider senza toccare ne l'interfaccia pubblica ne il codice applicativo — si riscrive solo la traduzione e la comunicazione.&lt;/p&gt;

&lt;h2&gt;
  
  
  Il valore dell'Adapter si misura al momento del cambiamento
&lt;/h2&gt;

&lt;p&gt;Il valore dell'Adapter non e immediatamente visibile — si manifesta quando qualcosa cambia. Quando SendinBlue e diventato Brevo, l'unico file da toccare e stato l'adapter. Nessun controller modificato, nessun service riscritto, nessun test aggiornato (a parte quello dell'adapter stesso). Il resto del codice ha &lt;strong&gt;continuato a funzionare come se nulla fosse accaduto&lt;/strong&gt; — perché per il codice applicativo, nulla e accaduto.&lt;/p&gt;

&lt;p&gt;Questa protezione dal cambiamento ha un nome nel mondo dei design pattern: &lt;strong&gt;Information Hiding&lt;/strong&gt;. L'adapter nasconde l'identita del provider dietro un'interfaccia stabile. Domani Brevo potrebbe cambiare di nuovo nome, cambiare la versione dell'API, o essere sostituito interamente da un altro servizio. L'adapter assorbe il cambiamento, e il codice applicativo resta intatto. E il ritorno sull'investimento di un'astrazione ben posizionata.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adapter e altri pattern: collaborazioni naturali
&lt;/h2&gt;

&lt;p&gt;L'Adapter collabora naturalmente con altri pattern. Con lo &lt;strong&gt;Strategy&lt;/strong&gt;: se hai più provider email (Brevo per la produzione, un logger per lo sviluppo), ogni adapter diventa una strategia intercambiabile. Con il &lt;strong&gt;Factory Method&lt;/strong&gt;: &lt;code&gt;MailService::make()&lt;/code&gt; decide quale adapter istanziare in base alla configurazione. Con il &lt;strong&gt;Facade&lt;/strong&gt;: il &lt;code&gt;MailService&lt;/code&gt; semplifica un'API complessa (l'SDK di Brevo ha decine di metodi) in un'interfaccia minimale con solo i metodi che il framework usa davvero.&lt;/p&gt;

&lt;p&gt;Questa composizione di pattern non e accidentale — e il risultato di una &lt;strong&gt;progettazione guidata dai principi SOLID&lt;/strong&gt;. L'adapter rispetta il Single Responsibility (traduce, non fa logica di business), l'Open/Closed (nuovo provider = nuovo adapter, zero modifiche altrove), il Dependency Inversion (il codice applicativo dipende dall'astrazione &lt;code&gt;MailService&lt;/code&gt;, non dal concreto Brevo). I pattern e i principi si rinforzano a vicenda.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quando usare l'Adapter Pattern
&lt;/h2&gt;

&lt;p&gt;L'Adapter e la scelta giusta in questi scenari:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Integrazione con SDK di terze parti&lt;/strong&gt; — API di pagamento, mail, storage cloud, social login&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Legacy code&lt;/strong&gt; — wrappare codice vecchio con un'interfaccia moderna senza riscriverlo&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cambio di provider&lt;/strong&gt; — quando prevedi (o vuoi prepararti per) il cambio di un servizio esterno&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Testing&lt;/strong&gt; — sostituire l'adapter reale con uno che scrive su file o su array in memoria&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Non usare l'Adapter quando l'integrazione e banale e il provider non cambiera mai (raro, ma possibile). L'overhead di un adapter inutile e minimo ma reale — una classe in più da mantenere, un livello di indirezione in più da navigare nel debugging. Come sempre, il &lt;strong&gt;pragmatismo&lt;/strong&gt; guida la scelta: se il costo dell'adapter e inferiore al costo di un futuro cambio di provider, l'adapter si ripaga.&lt;/p&gt;




&lt;p&gt;👉 &lt;strong&gt;&lt;a href="https://iadicola.it/articoli/quick-note-adapter-pattern-nel-mail-service?utm_source=devto&amp;amp;utm_medium=social" rel="noopener noreferrer"&gt;Leggi l'articolo completo su iadicola.it&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>designpattern</category>
      <category>mail</category>
      <category>refactoring</category>
    </item>
    <item>
      <title>Quick note: Middleware come Chain of Responsibility</title>
      <dc:creator>Dev-Iadicola</dc:creator>
      <pubDate>Sun, 09 Aug 2026 17:00:14 +0000</pubDate>
      <link>https://dev.to/dev_iadicola/quick-note-middleware-come-chain-of-responsibility-fbh</link>
      <guid>https://dev.to/dev_iadicola/quick-note-middleware-come-chain-of-responsibility-fbh</guid>
      <description>&lt;h2&gt;
  
  
  Ogni anello decide se passare al successivo
&lt;/h2&gt;

&lt;p&gt;Lo &lt;strong&gt;stack middleware&lt;/strong&gt; di Soft PHP MVC e una Chain of Responsibility: ogni middleware riceve la request, decide se gestirla o passarla al successivo, e può modificare la response in uscita. &lt;code&gt;CsrfMiddleware&lt;/code&gt; verifica il token — se manca, risponde 403 e la catena si interrompe. &lt;code&gt;RateLimitMiddleware&lt;/code&gt; conta le richieste — se il limite e superato, risponde 429. &lt;code&gt;AuthMiddleware&lt;/code&gt; verifica la sessione — se non autenticato, redirige al login. Ogni anello e un filtro autonomo con una logica precisa.&lt;/p&gt;

&lt;p&gt;La potenza del pattern e nella &lt;strong&gt;composibilita&lt;/strong&gt;: l'ordine dei middleware conta, ma ogni middleware e indipendente. Puoi aggiungere, rimuovere o riordinare anelli senza toccare gli altri. Il &lt;code&gt;VisitorTrackingMiddleware&lt;/code&gt; e stato aggiunto alla catena senza modificare una riga dei middleware esistenti — e questo e il test definitivo di un buon Chain of Responsibility. L'&lt;strong&gt;Open/Closed Principle&lt;/strong&gt; in azione: la catena e aperta all'estensione (nuovi anelli), chiusa alla modifica (anelli esistenti non cambiano).&lt;/p&gt;

&lt;h2&gt;
  
  
  Cos'e il Chain of Responsibility: definizione formale
&lt;/h2&gt;

&lt;p&gt;Il &lt;strong&gt;Gang of Four&lt;/strong&gt; definisce il Chain of Responsibility come un pattern comportamentale che "evita di accoppiare il mittente di una richiesta al suo destinatario, dando a più oggetti la possibilita di gestire la richiesta. Gli oggetti riceventi vengono concatenati e la richiesta viene passata lungo la catena fino a quando un oggetto la gestisce". I due elementi chiave sono: l'&lt;strong&gt;Handler&lt;/strong&gt; (l'interfaccia comune a tutti gli anelli) e la &lt;strong&gt;catena&lt;/strong&gt; (la sequenza ordinata di handler).&lt;/p&gt;

&lt;p&gt;A differenza dell'Observer, dove tutti gli osservatori vengono notificati, nella Chain of Responsibility la richiesta può &lt;strong&gt;fermarsi a qualsiasi anello&lt;/strong&gt;. Un middleware che risponde con un errore 403 interrompe la catena — i middleware successivi non vengono eseguiti. Questa capacità di cortocircuito e fondamentale per la sicurezza: il &lt;code&gt;CsrfMiddleware&lt;/code&gt; deve poter bloccare una richiesta malevola prima che raggiunga il controller.&lt;/p&gt;

&lt;h2&gt;
  
  
  L'anatomia di un middleware in Soft PHP MVC
&lt;/h2&gt;

&lt;p&gt;Ogni middleware nel framework implementa un contratto semplice: riceve la &lt;strong&gt;request&lt;/strong&gt; e un &lt;strong&gt;callable&lt;/strong&gt; che rappresenta il prossimo anello della catena. Il middleware può:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Passare la request al successivo&lt;/strong&gt; — chiama il callable e restituisce la response (middleware trasparente)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Modificare la request&lt;/strong&gt; — aggiunge header, normalizza input, poi passa al successivo&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interrompere la catena&lt;/strong&gt; — restituisce una response direttamente (errore, redirect, cache hit)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Modificare la response&lt;/strong&gt; — chiama il successivo, poi modifica la response prima di restituirla&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Questa flessibilita rende il middleware una primitiva estremamente potente. Non e un caso che la quasi totalita dei framework PHP moderni — Laravel, Symfony, Slim — adotti lo stesso pattern per il request handling. La Chain of Responsibility nel contesto HTTP e diventata uno &lt;strong&gt;standard de facto&lt;/strong&gt; dell'ecosistema PHP.&lt;/p&gt;

&lt;h3&gt;
  
  
  Middleware concreti nel framework
&lt;/h3&gt;

&lt;p&gt;Lo stack middleware di Soft PHP MVC include anelli con responsabilità diverse:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;CsrfMiddleware&lt;/strong&gt; — verifica il token CSRF su richieste POST/PUT/DELETE, protegge da attacchi cross-site request forgery&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;RateLimitMiddleware&lt;/strong&gt; — limita le richieste per IP in una finestra temporale, previene abusi e DDoS&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AuthMiddleware&lt;/strong&gt; — verifica l'autenticazione, redirige al login se la sessione e scaduta&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;VisitorTrackingMiddleware&lt;/strong&gt; — traccia i visitatori unici per analytics, senza bloccare la request&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MaintenanceModeMiddleware&lt;/strong&gt; — intercetta tutte le richieste e mostra la pagina di manutenzione quando attivo&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;L'ordine e significativo: il CSRF check avviene prima dell'auth, perché una richiesta senza token valido non dovrebbe nemmeno arrivare al controllo dell'autenticazione. Il rate limiting avviene prima di tutto, perché un attacco brute force non dovrebbe consumare risorse per verificare token o sessioni.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pipeline pattern: l'evoluzione del Chain of Responsibility
&lt;/h2&gt;

&lt;p&gt;In molti framework moderni, il Chain of Responsibility per i middleware e implementato come &lt;strong&gt;Pipeline&lt;/strong&gt;: un oggetto che riceve una lista di handler e li esegue in sequenza, passando il risultato di uno come input del successivo. La Pipeline e una variante più strutturata della catena classica — invece di lasciare che ogni anello conosca il successivo, la pipeline li orchestra dall'esterno.&lt;/p&gt;

&lt;p&gt;In Soft PHP MVC, il kernel HTTP costruisce la pipeline al boot dell'applicazione, concatenando i middleware configurati nel file di routing. La pipeline e &lt;strong&gt;immutabile dopo la costruzione&lt;/strong&gt;: l'ordine degli anelli non cambia durante l'esecuzione. Questa immutabilita semplifica il debugging e garantisce un comportamento predicibile — la stessa request attraversa sempre gli stessi anelli nello stesso ordine.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quando usare la Chain of Responsibility
&lt;/h2&gt;

&lt;p&gt;Il pattern e ideale quando:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Più oggetti possono gestire una richiesta&lt;/strong&gt; e il gestore corretto non e noto a priori&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;L'ordine di gestione e importante&lt;/strong&gt; ma deve essere configurabile&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nuovi gestori&lt;/strong&gt; devono poter essere aggiunti senza modificare quelli esistenti&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Una richiesta deve poter essere rifiutata&lt;/strong&gt; a qualsiasi livello della catena&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Oltre ai middleware HTTP, la Chain of Responsibility si applica a &lt;strong&gt;validazione&lt;/strong&gt; (ogni regola e un anello che può bloccare), &lt;strong&gt;logging&lt;/strong&gt; (ogni handler decide se loggare e a quale livello), e &lt;strong&gt;event handling&lt;/strong&gt; (ogni listener può marcare l'evento come gestito). In Soft PHP MVC, il middleware e l'applicazione principale, ma il pattern e una risorsa architetturale disponibile ogni volta che serve una catena decisionale configurabile e aperta all'estensione.&lt;/p&gt;




&lt;p&gt;👉 &lt;strong&gt;&lt;a href="https://iadicola.it/articoli/quick-note-middleware-come-chain-of-responsibility?utm_source=devto&amp;amp;utm_medium=social" rel="noopener noreferrer"&gt;Leggi l'articolo completo su iadicola.it&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>middleware</category>
      <category>architettura</category>
      <category>designpattern</category>
      <category>security</category>
    </item>
    <item>
      <title>Decorator Pattern: aggiungere comportamento senza toccare il codice esistente</title>
      <dc:creator>Dev-Iadicola</dc:creator>
      <pubDate>Sat, 08 Aug 2026 17:00:12 +0000</pubDate>
      <link>https://dev.to/dev_iadicola/decorator-pattern-aggiungere-comportamento-senza-toccare-il-codice-esistente-425m</link>
      <guid>https://dev.to/dev_iadicola/decorator-pattern-aggiungere-comportamento-senza-toccare-il-codice-esistente-425m</guid>
      <description>&lt;h2&gt;
  
  
  Il problema: estendere senza ereditare
&lt;/h2&gt;

&lt;p&gt;Immagina di avere un servizio che invia notifiche via email. Funziona perfettamente. Poi arriva la richiesta: "vogliamo anche un log di ogni notifica inviata". La tentazione immediata e modificare la classe esistente, aggiungendo il logging dentro il metodo &lt;code&gt;send()&lt;/code&gt;. Ma questo viola il &lt;strong&gt;principio di responsabilità singola&lt;/strong&gt;: la classe che invia email non dovrebbe occuparsi di logging. E se domani servisse anche il caching? E la validazione? Ogni nuova responsabilità si accumulera nella stessa classe fino a renderla ingestibile.&lt;/p&gt;

&lt;p&gt;L'ereditarieta sembra una soluzione: &lt;code&gt;LoggingEmailNotifier extends EmailNotifier&lt;/code&gt;. Ma l'ereditarieta crea una gerarchia rigida. Se vuoi logging + caching, serve una nuova sottoclasse. Logging + caching + rate limiting? Un'altra ancora. Il numero di combinazioni esplode esponenzialmente. Questo problema ha un nome preciso nella letteratura del software: &lt;strong&gt;class explosion&lt;/strong&gt;, e il Decorator Pattern e la risposta elegante.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cos'e il Decorator Pattern: definizione formale
&lt;/h2&gt;

&lt;p&gt;Il &lt;strong&gt;Gang of Four&lt;/strong&gt; definisce il Decorator come un pattern strutturale che "attacca responsabilità aggiuntive a un oggetto in modo dinamico, fornendo un'alternativa flessibile alla sottoclasse per estendere le funzionalita". Il concetto e semplice: il decorator implementa la stessa interfaccia dell'oggetto che wrappa, delega le chiamate all'oggetto originale, e aggiunge il proprio comportamento prima, dopo, o attorno alla delega.&lt;/p&gt;

&lt;p&gt;La struttura prevede quattro attori: il &lt;strong&gt;Component&lt;/strong&gt; (l'interfaccia comune), il &lt;strong&gt;ConcreteComponent&lt;/strong&gt; (l'implementazione base), il &lt;strong&gt;Decorator&lt;/strong&gt; (la classe astratta che mantiene un riferimento al Component wrappato) e i &lt;strong&gt;ConcreteDecorator&lt;/strong&gt; (le implementazioni che aggiungono comportamento specifico). Il client non distingue tra l'oggetto originale e quello decorato: entrambi rispettano lo stesso contratto.&lt;/p&gt;

&lt;h2&gt;
  
  
  Esempio teorico: un sistema di notifiche componibile
&lt;/h2&gt;

&lt;p&gt;Consideriamo un'interfaccia &lt;code&gt;NotifierInterface&lt;/code&gt; con un metodo &lt;code&gt;send(string $message): void&lt;/code&gt;. L'implementazione base &lt;code&gt;EmailNotifier&lt;/code&gt; invia l'email. Poi creiamo i decorator:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;LoggingDecorator&lt;/strong&gt;: riceve un &lt;code&gt;NotifierInterface&lt;/code&gt; nel costruttore, chiama &lt;code&gt;$this-&amp;gt;notifier-&amp;gt;send($message)&lt;/code&gt; e poi logga l'invio. Il logging e aggiunto senza toccare &lt;code&gt;EmailNotifier&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;RateLimitDecorator&lt;/strong&gt;: prima di delegare la chiamata, controlla se il limite di invii e stato raggiunto. Se si, lancia un'eccezione. Se no, delega e incrementa il contatore.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;RetryDecorator&lt;/strong&gt;: wrappa la chiamata in un try/catch e ritenta fino a N volte in caso di fallimento. Aggiunge resilienza senza che il notifier base sappia nulla di retry.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;EncryptionDecorator&lt;/strong&gt;: prima di delegare, cripta il messaggio. Il notifier base riceve un messaggio già criptato senza saperlo.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;La composizione avviene a runtime: &lt;code&gt;$notifier = new LoggingDecorator(new RateLimitDecorator(new RetryDecorator(new EmailNotifier())))&lt;/code&gt;. L'ordine conta: il logging avvolge il rate limiting che avvolge il retry che avvolge l'invio. Puoi ricombinare questi decorator in qualsiasi ordine senza creare nuove classi.&lt;/p&gt;

&lt;h3&gt;
  
  
  Perché la composizione batte l'ereditarieta
&lt;/h3&gt;

&lt;p&gt;Con 4 decorator e la necessita di combinarne qualsiasi sottoinsieme, l'ereditarieta richiederebbe 15 sottoclassi (tutte le combinazioni possibili). Con il Decorator ne servono 4: una per responsabilità. Ogni nuovo decorator si compone con tutti gli esistenti senza modificare nulla. Questa e la potenza della &lt;strong&gt;composizione rispetto all'ereditarieta&lt;/strong&gt;, uno dei principi fondamentali della programmazione ad oggetti moderna.&lt;/p&gt;

&lt;h2&gt;
  
  
  Decorator nel mondo reale: middleware HTTP
&lt;/h2&gt;

&lt;p&gt;Se hai lavorato con framework PHP moderni, hai già usato il Decorator Pattern senza saperlo. I &lt;strong&gt;middleware HTTP&lt;/strong&gt; sono decorator: ogni middleware riceve la request, può modificarla, delega al middleware successivo (l'oggetto wrappato), e può modificare la response al ritorno. La pipeline di middleware e una catena di decorator dove ogni anello aggiunge un comportamento: autenticazione, CORS, rate limiting, logging.&lt;/p&gt;

&lt;p&gt;In Soft PHP MVC, il &lt;code&gt;MiddlewarePipeline&lt;/code&gt; funziona esattamente così. Il &lt;code&gt;CsrfMiddleware&lt;/code&gt; decora la request aggiungendo la verifica del token. Il &lt;code&gt;RateLimitMiddleware&lt;/code&gt; decora aggiungendo il controllo delle richieste per IP. Il &lt;code&gt;CorsMiddleware&lt;/code&gt; decora la response aggiungendo gli header necessari. Nessuno di questi middleware conosce gli altri: ognuno fa una cosa sola e la fa bene.&lt;/p&gt;

&lt;h2&gt;
  
  
  Decorator Pattern e stream I/O
&lt;/h2&gt;

&lt;p&gt;Un altro esempio classico e l'I/O. Immagina un'interfaccia &lt;code&gt;StreamInterface&lt;/code&gt; con metodi &lt;code&gt;read()&lt;/code&gt; e &lt;code&gt;write()&lt;/code&gt;. L'implementazione base &lt;code&gt;FileStream&lt;/code&gt; legge e scrive su file. Un &lt;code&gt;BufferedStream&lt;/code&gt; wrappa qualsiasi stream aggiungendo un buffer in memoria per ridurre le operazioni disco. Un &lt;code&gt;CompressedStream&lt;/code&gt; wrappa qualsiasi stream aggiungendo compressione gzip al volo. Un &lt;code&gt;EncryptedStream&lt;/code&gt; aggiunge crittografia.&lt;/p&gt;

&lt;p&gt;La composizione &lt;code&gt;new EncryptedStream(new CompressedStream(new BufferedStream(new FileStream('data.bin'))))&lt;/code&gt; crea uno stream che scrive su file, con buffer, compressione e crittografia, senza che nessuna di queste classi conosca le altre. Ogni layer e indipendente, testabile, e riutilizzabile in contesti diversi.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quando usare il Decorator
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Usa il Decorator&lt;/strong&gt; quando vuoi aggiungere responsabilità a oggetti singoli senza influenzare altri oggetti della stessa classe&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Usa il Decorator&lt;/strong&gt; quando l'ereditarieta porta a un'esplosione di sottoclassi per coprire tutte le combinazioni&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Usa il Decorator&lt;/strong&gt; quando il comportamento aggiuntivo deve essere componibile e l'ordine può variare&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Non usare il Decorator&lt;/strong&gt; se il comportamento aggiuntivo e sempre lo stesso e non cambia mai: in quel caso l'ereditarieta semplice e sufficiente&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Non usare il Decorator&lt;/strong&gt; se la catena diventa troppo profonda e il debugging diventa impossibile: a quel punto considera il middleware pattern con una pipeline esplicita&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Decorator e principi SOLID
&lt;/h2&gt;

&lt;p&gt;Il Decorator e uno dei pattern che meglio incarnano i principi SOLID. Rispetta il &lt;strong&gt;Single Responsibility Principle&lt;/strong&gt; perché ogni decorator ha una sola ragione di cambiare. Rispetta l'&lt;strong&gt;Open/Closed Principle&lt;/strong&gt; perché estende il comportamento senza modificare il codice esistente. Rispetta il &lt;strong&gt;Liskov Substitution Principle&lt;/strong&gt; perché ogni decorator e sostituibile al component originale. Rispetta il &lt;strong&gt;Dependency Inversion Principle&lt;/strong&gt; perché tutti dipendono dall'astrazione (l'interfaccia), non dalle implementazioni concrete.&lt;/p&gt;

&lt;p&gt;Pochi pattern riescono a soddisfare quattro principi SOLID contemporaneamente. Il Decorator ci riesce naturalmente, senza forzature. Questo spiega perché e uno dei pattern più diffusi e più utili nel software professionale.&lt;/p&gt;




&lt;p&gt;👉 &lt;strong&gt;&lt;a href="https://iadicola.it/articoli/decorator-pattern-aggiungere-comportamento-senza-toccare-codice?utm_source=devto&amp;amp;utm_medium=social" rel="noopener noreferrer"&gt;Leggi l'articolo completo su iadicola.it&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>middleware</category>
      <category>architettura</category>
      <category>designpattern</category>
      <category>solid</category>
    </item>
    <item>
      <title>Proxy Pattern: controllare l'accesso senza cambiare l'interfaccia</title>
      <dc:creator>Dev-Iadicola</dc:creator>
      <pubDate>Fri, 07 Aug 2026 17:00:11 +0000</pubDate>
      <link>https://dev.to/dev_iadicola/proxy-pattern-controllare-laccesso-senza-cambiare-linterfaccia-42p1</link>
      <guid>https://dev.to/dev_iadicola/proxy-pattern-controllare-laccesso-senza-cambiare-linterfaccia-42p1</guid>
      <description>&lt;h2&gt;
  
  
  Il problema: oggetti pesanti che non servono subito
&lt;/h2&gt;

&lt;p&gt;Hai un modello &lt;code&gt;Article&lt;/code&gt; con una relazione &lt;code&gt;comments()&lt;/code&gt;. La pagina del blog elenca 20 articoli con titolo, data e autore. Nessuno ha ancora cliccato su un articolo per vederne i commenti, eppure il codice carica tutte le relazioni in anticipo, eseguendo 21 query (una per gli articoli e una per i commenti di ciascuno). E il classico &lt;strong&gt;N+1 problem&lt;/strong&gt;, ma la radice e più profonda: il problema e che l'oggetto Article espone direttamente i commenti, e chi lo usa non ha modo di decidere quando caricarli.&lt;/p&gt;

&lt;p&gt;Il &lt;strong&gt;Proxy Pattern&lt;/strong&gt; risolve questo problema interponendo un oggetto surrogato (il proxy) tra il client e l'oggetto reale. Il proxy implementa la stessa interfaccia dell'oggetto reale, ma controlla &lt;em&gt;quando&lt;/em&gt; e &lt;em&gt;come&lt;/em&gt; l'oggetto reale viene creato o acceduto. Il client non sa di parlare con un proxy — per lui e lo stesso oggetto di sempre.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cos'e il Proxy Pattern: definizione e varianti
&lt;/h2&gt;

&lt;p&gt;Il Gang of Four definisce il Proxy come un pattern strutturale che "fornisce un surrogato o segnaposto per un altro oggetto per controllarne l'accesso". La struttura e simile al Decorator — entrambi wrappano un oggetto con la stessa interfaccia — ma l'intento e diverso: il Decorator aggiunge comportamento, il Proxy controlla l'accesso.&lt;/p&gt;

&lt;p&gt;Esistono diverse varianti del Proxy, ognuna con uno scopo specifico:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Virtual Proxy (Lazy Loading)&lt;/strong&gt;: ritarda la creazione dell'oggetto reale fino al primo utilizzo. Utile per oggetti pesanti che potrebbero non servire mai.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Protection Proxy&lt;/strong&gt;: verifica i permessi prima di delegare la chiamata. L'oggetto reale non sa nulla di autorizzazione — il proxy la gestisce esternamente.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cache Proxy&lt;/strong&gt;: memorizza il risultato dell'oggetto reale e lo restituisce direttamente alle chiamate successive, evitando ricalcoli costosi.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Remote Proxy&lt;/strong&gt;: rappresenta un oggetto che vive su un altro server o processo. Il client chiama metodi locali, il proxy traduce in chiamate di rete.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Logging Proxy&lt;/strong&gt;: registra ogni chiamata all'oggetto reale per debugging o auditing senza che il codice di business contenga logica di logging.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Esempio teorico: lazy loading delle relazioni ORM
&lt;/h2&gt;

&lt;p&gt;Consideriamo un ORM che carica un &lt;code&gt;Article&lt;/code&gt; dal database. L'articolo ha una proprietà &lt;code&gt;$comments&lt;/code&gt; che dovrebbe contenere un array di oggetti &lt;code&gt;Comment&lt;/code&gt;. Con il caricamento eager, tutti i commenti vengono caricati immediatamente. Con il Proxy Pattern, la proprietà contiene inizialmente un &lt;code&gt;CommentCollectionProxy&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Il &lt;code&gt;CommentCollectionProxy&lt;/code&gt; implementa la stessa interfaccia di una collection (es. &lt;code&gt;Countable&lt;/code&gt;, &lt;code&gt;IteratorAggregate&lt;/code&gt;, &lt;code&gt;ArrayAccess&lt;/code&gt;). Internamente mantiene un flag &lt;code&gt;$loaded = false&lt;/code&gt; e un riferimento al query necessario per caricare i dati. Quando qualcuno chiama &lt;code&gt;count()&lt;/code&gt; o itera la collection, il proxy esegue la query, memorizza il risultato e delega la chiamata alla collection reale. Alle chiamate successive il dato e già in memoria.&lt;/p&gt;

&lt;h3&gt;
  
  
  Il vantaggio: N+1 diventa 1+0
&lt;/h3&gt;

&lt;p&gt;Se la pagina del blog mostra solo titolo e data, nessun proxy viene mai risolto: zero query per i commenti. Se l'utente apre un articolo specifico, il proxy di quell'articolo risolve i commenti con una singola query. Il pattern trasforma l'N+1 problem in un "1 + solo quello che serve", senza che il codice del controller cambi di una riga.&lt;/p&gt;

&lt;h2&gt;
  
  
  Esempio teorico: Protection Proxy per le API
&lt;/h2&gt;

&lt;p&gt;Immagina un servizio &lt;code&gt;ReportService&lt;/code&gt; con un metodo &lt;code&gt;generateFinancialReport()&lt;/code&gt;. Questo metodo può essere chiamato solo da utenti con ruolo "admin" o "finance". Invece di aggiungere il controllo dei permessi dentro il service (violando SRP), crei un &lt;code&gt;AuthorizedReportServiceProxy&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Il proxy riceve il &lt;code&gt;ReportService&lt;/code&gt; reale e un &lt;code&gt;AuthorizationChecker&lt;/code&gt; nel costruttore&lt;/li&gt;
&lt;li&gt;Prima di delegare &lt;code&gt;generateFinancialReport()&lt;/code&gt;, verifica che l'utente corrente abbia il permesso &lt;code&gt;report.financial.generate&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Se il permesso manca, lancia una &lt;code&gt;ForbiddenException&lt;/code&gt; senza mai chiamare il service reale&lt;/li&gt;
&lt;li&gt;Il &lt;code&gt;ReportService&lt;/code&gt; resta pulito: genera report, punto. Non sa nulla di permessi.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Esempio teorico: Cache Proxy per chiamate API esterne
&lt;/h2&gt;

&lt;p&gt;Un &lt;code&gt;WeatherService&lt;/code&gt; chiama un'API esterna per ottenere le previsioni meteo. Ogni chiamata costa 200ms di latenza. Un &lt;code&gt;CachedWeatherProxy&lt;/code&gt; wrappa il service: alla prima chiamata delega al service reale e salva il risultato in cache con un TTL di 30 minuti. Alle chiamate successive restituisce il dato dalla cache in meno di 1ms. Il controller non sa se sta ricevendo dati freschi o cachati — e non deve saperlo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Proxy vs Decorator: la differenza sottile
&lt;/h2&gt;

&lt;p&gt;Proxy e Decorator hanno la stessa struttura: un wrapper con la stessa interfaccia dell'oggetto wrappato. La differenza e nell'&lt;strong&gt;intento&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Decorator&lt;/strong&gt;: aggiunge comportamento nuovo. Il focus e sull'estensione delle funzionalita.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Proxy&lt;/strong&gt;: controlla l'accesso all'oggetto esistente. Il focus e su quando, come e se l'oggetto viene usato.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In pratica: un &lt;code&gt;LoggingDecorator&lt;/code&gt; aggiunge logging come funzionalita extra. Un &lt;code&gt;LazyProxy&lt;/code&gt; controlla &lt;em&gt;quando&lt;/em&gt; l'oggetto viene creato. Un &lt;code&gt;ProtectionProxy&lt;/code&gt; controlla &lt;em&gt;se&lt;/em&gt; l'oggetto viene acceduto. La distinzione e concettuale, non strutturale — ed e importante per comunicare l'intento del codice a chi lo legge.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quando usare il Proxy
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Lazy Loading&lt;/strong&gt;: quando creare l'oggetto e costoso e potrebbe non servire (relazioni ORM, connessioni, file pesanti)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Access Control&lt;/strong&gt;: quando vuoi separare la logica di autorizzazione dalla logica di business&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Caching&lt;/strong&gt;: quando il risultato e costoso da calcolare ma stabile nel tempo&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Remote Access&lt;/strong&gt;: quando l'oggetto reale vive su un altro server e vuoi nascondere la complessità di rete&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Non usare il Proxy&lt;/strong&gt; se l'oggetto e leggero e viene sempre usato: il proxy aggiunge indirezione senza beneficio&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Non usare il Proxy&lt;/strong&gt; se la trasparenza diventa un problema: a volte e meglio rendere esplicito che un'operazione e lazy o cachata&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Il Proxy Pattern e uno dei pattern più invisibili — quando funziona bene, nessuno sa che c'e. E questa e la sua forza: il codice di business resta pulito, e il controllo dell'accesso, del caching o del caricamento e gestito in un unico punto, testabile e modificabile indipendentemente.&lt;/p&gt;




&lt;p&gt;👉 &lt;strong&gt;&lt;a href="https://iadicola.it/articoli/proxy-pattern-controllare-accesso-senza-cambiare-interfaccia?utm_source=devto&amp;amp;utm_medium=social" rel="noopener noreferrer"&gt;Leggi l'articolo completo su iadicola.it&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>orm</category>
      <category>performance</category>
      <category>architettura</category>
      <category>designpattern</category>
    </item>
    <item>
      <title>Command Pattern: trasformare le azioni in oggetti</title>
      <dc:creator>Dev-Iadicola</dc:creator>
      <pubDate>Thu, 06 Aug 2026 17:00:16 +0000</pubDate>
      <link>https://dev.to/dev_iadicola/command-pattern-trasformare-le-azioni-in-oggetti-3451</link>
      <guid>https://dev.to/dev_iadicola/command-pattern-trasformare-le-azioni-in-oggetti-3451</guid>
      <description>&lt;h2&gt;
  
  
  Il problema: azioni che vivono solo nel momento
&lt;/h2&gt;

&lt;p&gt;Un controller riceve una richiesta POST e chiama direttamente &lt;code&gt;$order-&amp;gt;cancel()&lt;/code&gt;. Funziona. Ma cosa succede quando servono requisiti aggiuntivi? "Vogliamo un log di chi ha cancellato l'ordine e quando." Aggiungi una riga di logging. "Vogliamo poter annullare la cancellazione." Adesso serve memorizzare lo stato precedente. "Vogliamo che le cancellazioni passino per un'approvazione." Serve una coda. "Vogliamo poter ripetere l'operazione se fallisce." Serve un sistema di retry.&lt;/p&gt;

&lt;p&gt;Ogni requisito aggiuntivo aggiunge complessità al controller perché l'azione — cancellare un ordine — vive solo nel flusso di esecuzione: non e un &lt;em&gt;oggetto&lt;/em&gt; che puoi manipolare, accodare, serializzare o annullare. Il &lt;strong&gt;Command Pattern&lt;/strong&gt; risolve questo problema trasformando l'azione in un oggetto con un proprio stato, una propria identita e un ciclo di vita.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cos'e il Command Pattern: definizione formale
&lt;/h2&gt;

&lt;p&gt;Il Gang of Four definisce il Command come un pattern comportamentale che "incapsula una richiesta come oggetto, permettendo di parametrizzare i client con richieste diverse, accodare o loggare le richieste, e supportare operazioni annullabili". La struttura prevede cinque attori:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Command&lt;/strong&gt;: l'interfaccia con il metodo &lt;code&gt;execute()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ConcreteCommand&lt;/strong&gt;: implementa &lt;code&gt;execute()&lt;/code&gt; con la logica specifica, mantenendo un riferimento al Receiver&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Receiver&lt;/strong&gt;: l'oggetto che sa effettivamente come eseguire l'operazione&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Invoker&lt;/strong&gt;: chiede al Command di eseguire la richiesta, senza sapere cosa fa&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Client&lt;/strong&gt;: crea il ConcreteCommand e lo associa al Receiver&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Esempio teorico: un sistema di ordini con undo
&lt;/h2&gt;

&lt;p&gt;Immagina un gestionale dove gli operatori gestiscono ordini. Ogni azione e un Command:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;CancelOrderCommand&lt;/code&gt;: riceve l'ordine nel costruttore. Il metodo &lt;code&gt;execute()&lt;/code&gt; salva lo stato corrente (&lt;code&gt;$this-&amp;gt;previousStatus = $order-&amp;gt;getStatus()&lt;/code&gt;), poi chiama &lt;code&gt;$order-&amp;gt;cancel()&lt;/code&gt;. Il metodo &lt;code&gt;undo()&lt;/code&gt; ripristina lo stato precedente: &lt;code&gt;$order-&amp;gt;setStatus($this-&amp;gt;previousStatus)&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ShipOrderCommand&lt;/code&gt;: segna l'ordine come spedito, registra la data di spedizione. L'&lt;code&gt;undo()&lt;/code&gt; annulla la spedizione e ripristina lo stato precedente.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;RefundOrderCommand&lt;/code&gt;: esegue il rimborso. L'&lt;code&gt;undo()&lt;/code&gt; annulla il rimborso (se ancora possibile).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ChangeAddressCommand&lt;/code&gt;: aggiorna l'indirizzo di spedizione. L'&lt;code&gt;undo()&lt;/code&gt; ripristina l'indirizzo precedente.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;L'Invoker mantiene una &lt;strong&gt;history stack&lt;/strong&gt;: ogni Command eseguito viene pushato nello stack. L'operazione "annulla" fa pop dall'stack e chiama &lt;code&gt;undo()&lt;/code&gt; sull'ultimo Command. L'operazione "ripeti" fa la stessa cosa con uno stack di redo. Il sistema di undo/redo e generico e funziona con qualsiasi Command, senza conoscerne il tipo concreto.&lt;/p&gt;

&lt;h2&gt;
  
  
  Command Pattern nella CLI
&lt;/h2&gt;

&lt;p&gt;In Soft PHP MVC, i comandi CLI sono un'applicazione naturale del Command Pattern. Ogni comando implementa una classe con un metodo &lt;code&gt;handle(Input, Output): int&lt;/code&gt;. L'attributo &lt;code&gt;#[CliCommand]&lt;/code&gt; dichiara il nome e la descrizione. Il &lt;code&gt;Kernel&lt;/code&gt; (l'Invoker) riceve il nome del comando dalla linea di comando, cerca il ConcreteCommand corrispondente, e chiama &lt;code&gt;handle()&lt;/code&gt;. Il Kernel non sa cosa fa il comando: sa solo che ha un metodo &lt;code&gt;handle()&lt;/code&gt; e restituisce un exit code.&lt;/p&gt;

&lt;p&gt;Questa struttura permette di aggiungere comandi senza toccare il Kernel: basta creare una nuova classe con l'attributo &lt;code&gt;#[CliCommand]&lt;/code&gt; e l'auto-discovery la trova. Il Command Pattern e il motivo per cui 26 comandi diversi — da &lt;code&gt;migrate:fresh&lt;/code&gt; a &lt;code&gt;key:generate&lt;/code&gt; — condividono la stessa infrastruttura senza conflitti.&lt;/p&gt;

&lt;h2&gt;
  
  
  Esempio teorico: job queue asincrona
&lt;/h2&gt;

&lt;p&gt;Il Command Pattern e alla base di ogni sistema di code (queue). Un job e un Command serializzato: contiene tutti i dati necessari per eseguire l'operazione, ma l'esecuzione e differita nel tempo. Il flusso e:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Il controller crea il Command: &lt;code&gt;$command = new SendInvoiceEmail($orderId, $customerEmail)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Il dispatcher (Invoker) serializza il Command e lo mette in coda (Redis, database, RabbitMQ)&lt;/li&gt;
&lt;li&gt;Un worker legge il Command dalla coda, lo deserializza e chiama &lt;code&gt;execute()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Se l'esecuzione fallisce, il Command può essere rimesso in coda per un retry&lt;/li&gt;
&lt;li&gt;Se fallisce N volte, viene spostato in una dead letter queue per analisi manuale&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Il fatto che l'azione sia un oggetto serializzabile rende possibile tutto questo: accodare, ritardare, ritentare, loggare, monitorare. Un'azione che vive solo come chiamata di metodo non può essere accodata o ritentata — un Command si.&lt;/p&gt;

&lt;h2&gt;
  
  
  Command vs Strategy: la differenza
&lt;/h2&gt;

&lt;p&gt;Command e Strategy sono entrambi pattern comportamentali con una struttura simile (un oggetto con un metodo da invocare), ma l'intento e diverso:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Strategy&lt;/strong&gt;: rappresenta &lt;em&gt;come&lt;/em&gt; fare qualcosa. E intercambiabile: puoi cambiare l'algoritmo a runtime. L'accento e sull'alternativa.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Command&lt;/strong&gt;: rappresenta &lt;em&gt;cosa&lt;/em&gt; fare. E un'azione reificata con il proprio stato e ciclo di vita. L'accento e sull'operazione.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Uno Strategy cambia il comportamento di un contesto. Un Command e un'azione che puoi manipolare come dato: accodare, serializzare, annullare, ripetere. La differenza e sottile ma fondamentale per scegliere il pattern giusto.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quando usare il Command Pattern
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Usa il Command&lt;/strong&gt; quando vuoi supportare undo/redo: ogni Command salva lo stato precedente e sa come ripristinarlo&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Usa il Command&lt;/strong&gt; quando le azioni devono essere accodate, ritardate o eseguite in batch&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Usa il Command&lt;/strong&gt; quando vuoi loggare ogni azione con i suoi parametri per auditing o debugging&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Usa il Command&lt;/strong&gt; quando azioni diverse devono passare per la stessa pipeline (validazione, autorizzazione, logging)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Non usare il Command&lt;/strong&gt; per operazioni semplici e immediate dove la complessità aggiuntiva non e giustificata&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Non usare il Command&lt;/strong&gt; se non hai bisogno di nessuna delle funzionalita che il pattern offre: l'astrazione senza beneficio e solo burocrazia&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Il Command Pattern trasforma le azioni da verbi effimeri a sostantivi permanenti. Questa trasformazione apre possibilita che prima non esistevano: undo, queue, replay, auditing. E uno dei pattern con il miglior rapporto tra complessità introdotta e funzionalita abilitate.&lt;/p&gt;




&lt;p&gt;👉 &lt;strong&gt;&lt;a href="https://iadicola.it/articoli/command-pattern-trasformare-azioni-in-oggetti?utm_source=devto&amp;amp;utm_medium=social" rel="noopener noreferrer"&gt;Leggi l'articolo completo su iadicola.it&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>php84</category>
      <category>architettura</category>
      <category>designpattern</category>
      <category>cli</category>
    </item>
    <item>
      <title>State Pattern: oggetti che cambiano comportamento in base al proprio stato</title>
      <dc:creator>Dev-Iadicola</dc:creator>
      <pubDate>Wed, 05 Aug 2026 17:00:10 +0000</pubDate>
      <link>https://dev.to/dev_iadicola/state-pattern-oggetti-che-cambiano-comportamento-in-base-al-proprio-stato-16ep</link>
      <guid>https://dev.to/dev_iadicola/state-pattern-oggetti-che-cambiano-comportamento-in-base-al-proprio-stato-16ep</guid>
      <description>&lt;h2&gt;
  
  
  Il problema: lo switch sullo stato che divora il codice
&lt;/h2&gt;

&lt;p&gt;Un ordine in un e-commerce ha diversi stati: &lt;em&gt;draft&lt;/em&gt;, &lt;em&gt;pending&lt;/em&gt;, &lt;em&gt;paid&lt;/em&gt;, &lt;em&gt;shipped&lt;/em&gt;, &lt;em&gt;delivered&lt;/em&gt;, &lt;em&gt;cancelled&lt;/em&gt;, &lt;em&gt;refunded&lt;/em&gt;. Ogni operazione dipende dallo stato corrente: puoi pagare un ordine solo se e pending, puoi spedire solo se e paid, puoi cancellare solo se non e già shipped. Il codice diventa una cascata di &lt;code&gt;if ($this-&amp;gt;status === 'pending')&lt;/code&gt; in ogni metodo.&lt;/p&gt;

&lt;p&gt;Il metodo &lt;code&gt;cancel()&lt;/code&gt; controlla se lo stato permette la cancellazione. Il metodo &lt;code&gt;ship()&lt;/code&gt; controlla se lo stato permette la spedizione. Il metodo &lt;code&gt;refund()&lt;/code&gt; controlla se lo stato permette il rimborso. Ogni nuovo stato o nuova operazione richiede di aggiornare &lt;em&gt;tutti&lt;/em&gt; i metodi. Ogni nuova transizione richiede di aggiornare &lt;em&gt;tutti&lt;/em&gt; i controlli. La complessità cresce come il prodotto di stati per operazioni: 7 stati e 6 operazioni significano 42 condizioni da gestire e mantenere sincronizzate.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cos'e lo State Pattern: definizione formale
&lt;/h2&gt;

&lt;p&gt;Il Gang of Four definisce lo State come un pattern comportamentale che "permette a un oggetto di alterare il proprio comportamento quando il suo stato interno cambia. L'oggetto sembrera cambiare la propria classe". La struttura prevede tre attori:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Context&lt;/strong&gt;: l'oggetto che ha uno stato (es. &lt;code&gt;Order&lt;/code&gt;). Mantiene un riferimento allo State corrente e delega le operazioni a esso.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;State&lt;/strong&gt;: l'interfaccia che dichiara i metodi per ogni operazione (es. &lt;code&gt;pay()&lt;/code&gt;, &lt;code&gt;ship()&lt;/code&gt;, &lt;code&gt;cancel()&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ConcreteState&lt;/strong&gt;: ogni stato (es. &lt;code&gt;PendingState&lt;/code&gt;, &lt;code&gt;PaidState&lt;/code&gt;) implementa i metodi con il comportamento specifico di quello stato.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Esempio teorico: ciclo di vita di un ordine
&lt;/h2&gt;

&lt;p&gt;Definiamo l'interfaccia &lt;code&gt;OrderStateInterface&lt;/code&gt; con i metodi: &lt;code&gt;pay(Order $order): void&lt;/code&gt;, &lt;code&gt;ship(Order $order): void&lt;/code&gt;, &lt;code&gt;cancel(Order $order): void&lt;/code&gt;, &lt;code&gt;refund(Order $order): void&lt;/code&gt;, &lt;code&gt;getStatus(): string&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Ogni stato implementa l'interfaccia:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;DraftState&lt;/strong&gt;: &lt;code&gt;pay()&lt;/code&gt; lancia un'eccezione ("non puoi pagare un ordine in bozza, prima confermalo"). &lt;code&gt;cancel()&lt;/code&gt; transiziona a &lt;code&gt;CancelledState&lt;/code&gt;. Tutti gli altri metodi lanciano eccezioni appropriate.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PendingState&lt;/strong&gt;: &lt;code&gt;pay()&lt;/code&gt; processa il pagamento e transiziona a &lt;code&gt;PaidState&lt;/code&gt;. &lt;code&gt;cancel()&lt;/code&gt; transiziona a &lt;code&gt;CancelledState&lt;/code&gt;. &lt;code&gt;ship()&lt;/code&gt; lancia "non puoi spedire un ordine non pagato".&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PaidState&lt;/strong&gt;: &lt;code&gt;ship()&lt;/code&gt; registra la spedizione e transiziona a &lt;code&gt;ShippedState&lt;/code&gt;. &lt;code&gt;refund()&lt;/code&gt; processa il rimborso e transiziona a &lt;code&gt;RefundedState&lt;/code&gt;. &lt;code&gt;pay()&lt;/code&gt; lancia "ordine già pagato".&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ShippedState&lt;/strong&gt;: &lt;code&gt;cancel()&lt;/code&gt; lancia "non puoi cancellare un ordine già spedito". &lt;code&gt;refund()&lt;/code&gt; richiede prima il reso. L'unica transizione valida e verso &lt;code&gt;DeliveredState&lt;/code&gt; quando il corriere conferma la consegna.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CancelledState&lt;/strong&gt; e &lt;strong&gt;RefundedState&lt;/strong&gt;: sono stati terminali. Tutti i metodi lanciano eccezioni: nessuna transizione e possibile.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;La classe &lt;code&gt;Order&lt;/code&gt; ha una proprieta &lt;code&gt;private OrderStateInterface $state&lt;/code&gt; e delega ogni operazione: &lt;code&gt;public function pay(): void { $this-&amp;gt;state-&amp;gt;pay($this); }&lt;/code&gt;. Il metodo di transizione &lt;code&gt;Order::transitionTo(OrderStateInterface $newState)&lt;/code&gt; e chiamato dagli stati stessi: &lt;code&gt;$order-&amp;gt;transitionTo(new PaidState())&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Il vantaggio: aggiungere uno stato senza toccare gli altri
&lt;/h3&gt;

&lt;p&gt;Se arriva un nuovo stato — ad esempio &lt;code&gt;OnHoldState&lt;/code&gt; per ordini bloccati in attesa di verifica antifrode — basta creare una nuova classe che implementa &lt;code&gt;OrderStateInterface&lt;/code&gt;. Definisci quali operazioni sono permesse in questo stato e quali transizioni sono valide. Nessun altro stato deve cambiare. Nessun metodo della classe &lt;code&gt;Order&lt;/code&gt; deve essere modificato. Il principio Open/Closed e rispettato naturalmente.&lt;/p&gt;

&lt;h2&gt;
  
  
  State Pattern vs Enum con match
&lt;/h2&gt;

&lt;p&gt;In PHP 8.1+ si potrebbe gestire gli stati con un Enum e &lt;code&gt;match&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;match($this-&amp;gt;status) { OrderStatus::Pending =&amp;gt; ..., OrderStatus::Paid =&amp;gt; ..., ... }&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Funziona per casi semplici, ma ha un limite strutturale: ogni nuovo stato richiede di aggiornare ogni &lt;code&gt;match&lt;/code&gt; in ogni metodo. Con lo State Pattern, ogni nuovo stato e autocontenuto nella propria classe. La scelta dipende dalla complessità:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;3-4 stati, 2-3 operazioni&lt;/strong&gt;: l'Enum con match e più semplice e diretto. Lo State Pattern sarebbe over-engineering.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;5+ stati, 4+ operazioni&lt;/strong&gt;: lo State Pattern scala meglio perché ogni stato e isolato.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Transizioni complesse con regole di business&lt;/strong&gt;: lo State Pattern permette di incapsulare le regole dentro ogni stato.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  State Machine come evoluzione
&lt;/h2&gt;

&lt;p&gt;Lo State Pattern può evolvere in una &lt;strong&gt;State Machine&lt;/strong&gt; formale, dove le transizioni valide sono dichiarate esplicitamente in una mappa: &lt;code&gt;['pending' =&amp;gt; ['paid', 'cancelled'], 'paid' =&amp;gt; ['shipped', 'refunded']]&lt;/code&gt;. La State Machine aggiunge garanzie: nessuna transizione non dichiarata e possibile, e ogni transizione può avere guardie (condizioni) e azioni (side effect).&lt;/p&gt;

&lt;p&gt;In molti framework questa evoluzione e supportata da librerie dedicate (Symfony Workflow, Laravel State Machines). Ma il concetto alla base e sempre lo State Pattern: il comportamento cambia in base allo stato, e ogni stato sa quali transizioni sono valide.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quando usare lo State Pattern
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Usa lo State Pattern&lt;/strong&gt; quando un oggetto ha un numero significativo di stati e il comportamento varia in base allo stato corrente&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Usa lo State Pattern&lt;/strong&gt; quando gli switch/if sullo stato sono ripetuti in molti metodi della stessa classe&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Usa lo State Pattern&lt;/strong&gt; quando le regole di transizione sono complesse e vuoi renderle esplicite&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Non usare lo State Pattern&lt;/strong&gt; per oggetti con 2-3 stati semplici: un boolean o un enum con match bastano&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Non usare lo State Pattern&lt;/strong&gt; se le transizioni non hanno regole: se ogni stato può andare in ogni altro stato, il pattern aggiunge struttura senza valore&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Lo State Pattern non e un modo elegante di riscrivere degli if: e un modo di rendere esplicite e isolate le regole di comportamento che dipendono dallo stato. Quando queste regole sono complesse, il pattern trasforma un groviglio di condizioni in una struttura leggibile, testabile e manutenibile.&lt;/p&gt;




&lt;p&gt;👉 &lt;strong&gt;&lt;a href="https://iadicola.it/articoli/state-pattern-oggetti-cambiano-comportamento-in-base-allo-stato?utm_source=devto&amp;amp;utm_medium=social" rel="noopener noreferrer"&gt;Leggi l'articolo completo su iadicola.it&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>php84</category>
      <category>orm</category>
      <category>architettura</category>
      <category>designpattern</category>
    </item>
    <item>
      <title>L'AI sostituirà i programmatori?</title>
      <dc:creator>Dev-Iadicola</dc:creator>
      <pubDate>Tue, 04 Aug 2026 17:00:15 +0000</pubDate>
      <link>https://dev.to/dev_iadicola/lai-sostituira-i-programmatori-2ogl</link>
      <guid>https://dev.to/dev_iadicola/lai-sostituira-i-programmatori-2ogl</guid>
      <description>&lt;p&gt;Si sente spesso questa affermazione, sui social, nelle conferenze, nelle chiacchierate tra colleghi.&lt;/p&gt;

&lt;p&gt;C'è chi la teme, chi la cavalca come argomento di marketing, chi la usa per giustificare tagli ai team di sviluppo.&lt;/p&gt;

&lt;p&gt;Io ho una posizione diversa, basata sull'esperienza diretta: l'AI è uno strumento potente, ma chi dice che sostituirà i programmatori non ha ancora revisionato abbastanza codice scritto da un agente.Il problema non è la velocità&lt;/p&gt;

&lt;h2&gt;
  
  
  L'AI è veloce.
&lt;/h2&gt;

&lt;p&gt;Su questo non ci sono dubbi. Genera codice in pochi secondi, risponde a qualsiasi richiesta, non si stanca e non chiede ferie.Ma la velocità da sola non basta.&lt;/p&gt;

&lt;p&gt;Anzi, può essere controproducente se il codice prodotto è di bassa qualità.&lt;/p&gt;

&lt;p&gt;E qui iniziano i problemi.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cosa ho osservato sul campo
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Codice di bassa qualità&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Uno dei problemi più frequenti è la duplicazione.&lt;/p&gt;

&lt;p&gt;L'agente non ha una visione globale del progetto: non sa che quella funzione esiste già altrove, non ragiona sulla base di codebase consolidate.&lt;/p&gt;

&lt;p&gt;Scrive quello che gli chiedi, punto.&lt;/p&gt;

&lt;p&gt;Il risultato è un progetto che cresce in larghezza invece che in profondità, pieno di logica ridondante difficile da mantenere.&lt;/p&gt;

&lt;h2&gt;
  
  
  Assenza di pattern architetturali
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;L'AI conosce i design pattern. Se glielo chiedi, ti spiegherà cos'è un repository, un service, un DTO.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Ma se non glielo chiedi esplicitamente, &lt;strong&gt;non li userà&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;La logica di business finisce nei controller, le responsabilità non vengono separate, e il progetto diventa rapidamente un monolite ingestibile.&lt;/p&gt;

&lt;p&gt;Ho visto controller con decine di righe di logica inline che avrebbero dovuto stare in classi dedicate. Non perché l'agente non sapesse farlo, ma perché nessuno glielo aveva chiesto.&lt;/p&gt;

&lt;h2&gt;
  
  
  Architettura approssimativa
&lt;/h2&gt;

&lt;p&gt;Se chiedi a un agente di progettare un'architettura, ti darà qualcosa di funzionante — ma raramente qualcosa di ben fatto.&lt;/p&gt;

&lt;p&gt;Classi astratte che andrebbero ripensate, dependency injection usata male o per niente, layer che si sovrappongono senza rispettare le responsabilità.&lt;/p&gt;

&lt;p&gt;Un software architect esperto farebbe scelte diverse, e soprattutto le motiverebbe.&lt;/p&gt;

&lt;h2&gt;
  
  
  Nessuna visione a lungo termine
&lt;/h2&gt;

&lt;p&gt;Questo è forse il limite più critico.&lt;/p&gt;

&lt;p&gt;L'agente risponde alla richiesta presente.&lt;/p&gt;

&lt;p&gt;Non pensa a come il progetto evolverà tra sei mesi, non considera la scalabilità, non anticipa i problemi che emergeranno quando il team crescerà o i requisiti cambieranno.&lt;/p&gt;

&lt;p&gt;Il debito tecnico si accumula silenziosamente, e quando esplode è sempre nel momento peggiore.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tende ad accontentarti
&lt;/h2&gt;

&lt;h3&gt;
  
  
  L'AI non ha interessi propri.
&lt;/h3&gt;

&lt;h3&gt;
  
  
  Esegue.
&lt;/h3&gt;

&lt;p&gt;Se cambi direzione dieci volte in una settimana, la seguirà ogni volta senza alzare la mano. Se hai una pessima idea, ci sono buone probabilità che la implementi comunque — a meno che non sia palesemente errata.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Un collega esperto ti direbbe di no.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Ti farebbe le domande scomode. L'agente no.&lt;/p&gt;

&lt;h3&gt;
  
  
  Un esempio concreto
&lt;/h3&gt;

&lt;p&gt;Se chiedi a un agente di creare un'entità per gestire dati statici — tipo una lista di nazioni o di categorie che non cambieranno mai — lo farà.&lt;/p&gt;

&lt;p&gt;Tabella nel database, model, migration, tutto quanto.Un programmatore con esperienza ti fermerebbe subito: "Se i dati non cambiano, non hai bisogno di un'entità. Usa un file JSON o un enum."&lt;/p&gt;

&lt;p&gt;È una scelta banale per chi ha anni di esperienza, ma l'agente non la proporrà mai se non gliela chiedi.&lt;/p&gt;

&lt;h3&gt;
  
  
  La code review inutile
&lt;/h3&gt;

&lt;p&gt;Paradossalmente, se chiedi all'agente di fare una code review su codice già ben scritto, ti suggerirà comunque dei cambiamenti.&lt;/p&gt;

&lt;p&gt;Perché è programmato per rispondere, non per dire "qui non c'è nulla da fare".&lt;/p&gt;

&lt;p&gt;Il rischio concreto è introdurre complessità non necessaria su qualcosa che funzionava già bene.&lt;/p&gt;

&lt;h3&gt;
  
  
  Perché succede tutto questo?
&lt;/h3&gt;

&lt;p&gt;La risposta è semplice: l'AI è una macchina che esegue ordini.&lt;/p&gt;

&lt;p&gt;Non ha intuizione, non ha contesto storico sul progetto, non ha opinioni reali.&lt;/p&gt;

&lt;p&gt;Risponde al prompt nel modo più plausibile possibile, &lt;strong&gt;basandosi sui dati su cui è stata addestrata.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Non ragiona sul problema.
&lt;/h3&gt;

&lt;p&gt;Questo non significa che sia inutile. Significa che va usata per quello che è.&lt;/p&gt;

&lt;h2&gt;
  
  
  Allora a cosa serve?
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;L'AI è uno strumento. Come un martello: utile nelle mani giuste, pericoloso in quelle sbagliate.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Nella mia esperienza, rende i programmatori più veloci su compiti ripetitivi, boilerplate, ricerca di bug banali, generazione di test.&lt;/p&gt;

&lt;p&gt;Ma richiede sempre qualcuno in grado di valutare l'output, riconoscere i problemi architetturali, prendere le decisioni che contano.Il programmatore che sa usarla bene è più produttivo. Il programmatore che si fida ciecamente, accumula debito tecnico.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusione
&lt;/h2&gt;

&lt;p&gt;L'AI sostituirà i programmatori? Forse, un giorno. Non lo escludo.&lt;/p&gt;

&lt;p&gt;Ma oggi, chi pensa di poter affidare a un agente la progettazione e lo sviluppo di un software senza supervisione tecnica competente, si troverà presto con un progetto difficile da mantenere, da scalare e da capire.La qualità del codice conta. E quella, per ora, richiede ancora un essere umano che sappia cosa sta guardando.&lt;/p&gt;




&lt;p&gt;👉 &lt;strong&gt;&lt;a href="https://iadicola.it/articoli/l-ai-sostituira-i-programmatori?utm_source=devto&amp;amp;utm_medium=social" rel="noopener noreferrer"&gt;Leggi l'articolo completo su iadicola.it&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>php</category>
      <category>crm</category>
      <category>aggiornamenti</category>
      <category>infrastruttura</category>
    </item>
    <item>
      <title>Facade Pattern: semplificare l'accesso a sistemi complessi</title>
      <dc:creator>Dev-Iadicola</dc:creator>
      <pubDate>Mon, 03 Aug 2026 17:00:14 +0000</pubDate>
      <link>https://dev.to/dev_iadicola/facade-pattern-semplificare-laccesso-a-sistemi-complessi-2a1n</link>
      <guid>https://dev.to/dev_iadicola/facade-pattern-semplificare-laccesso-a-sistemi-complessi-2a1n</guid>
      <description>&lt;h2&gt;
  
  
  Il problema: troppi oggetti per fare una cosa semplice
&lt;/h2&gt;

&lt;p&gt;Per inviare un'email di conferma ordine servono sei passaggi: creare il template engine, caricare il template, renderizzare con i dati dell'ordine, creare il transport SMTP, configurare le credenziali, costruire il messaggio con mittente, destinatario, oggetto e corpo, e infine inviare. Sei oggetti, dodici metodi, venti righe di codice. Ogni controller che deve inviare un'email ripete lo stesso boilerplate, o copia-incolla da un controller precedente.&lt;/p&gt;

&lt;p&gt;Il &lt;strong&gt;Facade Pattern&lt;/strong&gt; propone di creare un'interfaccia semplificata che nasconde questa complessità. Invece di sei oggetti e dodici metodi, il controller chiama &lt;code&gt;Mailer::send('order-confirmation', $order, $customer-&amp;gt;email)&lt;/code&gt;. Una riga. La Facade si occupa di orchestrare i sei oggetti sotto il cofano.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cos'e il Facade Pattern: definizione formale
&lt;/h2&gt;

&lt;p&gt;Il Gang of Four definisce il Facade come un pattern strutturale che "fornisce un'interfaccia unificata a un insieme di interfacce in un sottosistema. La Facade definisce un'interfaccia di livello superiore che rende il sottosistema più facile da usare". Non nasconde il sottosistema — lo rende accessibile a chi non ha bisogno di conoscerne i dettagli.&lt;/p&gt;

&lt;p&gt;La struttura e semplice: una classe &lt;strong&gt;Facade&lt;/strong&gt; che conosce quali classi del sottosistema sono responsabili di ogni richiesta, e delega le chiamate del client alle classi appropriate. Il sottosistema non sa dell'esistenza della Facade — le sue classi sono autonome e possono essere usate direttamente quando serve un controllo fine.&lt;/p&gt;

&lt;h2&gt;
  
  
  Esempio teorico: un sottosistema di reportistica
&lt;/h2&gt;

&lt;p&gt;Immagina un sistema di generazione report con diverse componenti:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;DataExtractor&lt;/code&gt;: esegue query sul database e restituisce dati grezzi&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;DataTransformer&lt;/code&gt;: aggrega, filtra e formatta i dati per il report&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ChartGenerator&lt;/code&gt;: genera grafici SVG dai dati trasformati&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;PdfRenderer&lt;/code&gt;: combina testo e grafici in un documento PDF&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;FileStorage&lt;/code&gt;: salva il PDF generato nel filesystem o nel cloud&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;NotificationService&lt;/code&gt;: notifica l'utente che il report e pronto&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Senza Facade, il controller deve orchestrare tutti questi oggetti manualmente: estrarre i dati, trasformarli, generare i grafici, renderizzare il PDF, salvarlo e notificare l'utente. Sei dipendenze nel controller, sei passaggi da coordinare, sei punti dove qualcosa può andare storto.&lt;/p&gt;

&lt;p&gt;La Facade &lt;code&gt;ReportFacade&lt;/code&gt; espone un metodo: &lt;code&gt;generate(string $type, array $params, int $userId): string&lt;/code&gt;. Internamente orchestra tutti e sei i passaggi e restituisce il path del report generato. Il controller ha una sola dipendenza e una sola riga di codice.&lt;/p&gt;

&lt;h3&gt;
  
  
  La Facade non imprigiona
&lt;/h3&gt;

&lt;p&gt;Un malinteso comune e che la Facade impedisca l'accesso diretto al sottosistema. Non e così: la Facade e un &lt;em&gt;in più&lt;/em&gt;, non un &lt;em&gt;invece di&lt;/em&gt;. Se un caso d'uso specifico richiede il controllo fine sul &lt;code&gt;ChartGenerator&lt;/code&gt; — ad esempio per generare un grafico senza il PDF — il codice può usare direttamente &lt;code&gt;ChartGenerator&lt;/code&gt; senza passare dalla Facade. La Facade semplifica il caso comune, non limita i casi speciali.&lt;/p&gt;

&lt;h2&gt;
  
  
  Esempio teorico: Facade per l'autenticazione
&lt;/h2&gt;

&lt;p&gt;L'autenticazione coinvolge molti componenti: verifica credenziali, hashing password, gestione sessione, generazione token, verifica 2FA, logging dei tentativi. Una &lt;code&gt;AuthFacade&lt;/code&gt; espone:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;attempt(string $email, string $password): bool&lt;/code&gt; — verifica credenziali, logga il tentativo, avvia la sessione&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;verify2FA(string $code): bool&lt;/code&gt; — verifica il codice TOTP e completa l'autenticazione&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;logout(): void&lt;/code&gt; — invalida sessione e token&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;check(): bool&lt;/code&gt; — verifica se l'utente e autenticato&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ogni metodo della Facade coordina 3-4 componenti interni. Il middleware di autenticazione chiama &lt;code&gt;AuthFacade::check()&lt;/code&gt; senza sapere che sotto il cofano vengono verificati sessione, token JWT e timestamp di scadenza.&lt;/p&gt;

&lt;h2&gt;
  
  
  Facade vs Service: la differenza
&lt;/h2&gt;

&lt;p&gt;La distinzione tra Facade e Service e sottile ma importante:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Facade&lt;/strong&gt;: semplifica l'accesso a un sottosistema &lt;em&gt;esistente&lt;/em&gt;. Non aggiunge logica di business: orchestra componenti già esistenti. Se rimuovi la Facade, le classi del sottosistema funzionano ancora.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Service&lt;/strong&gt;: contiene logica di business propria. Può usare componenti del sottosistema, ma aggiunge regole, validazioni e decisioni che non esistono altrove.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Se il metodo della tua "Facade" contiene 50 righe di logica di business con condizioni e calcoli, probabilmente e un Service, non una Facade. Se orchestra 6 chiamate a componenti diversi senza aggiungere logica, e una Facade pura.&lt;/p&gt;

&lt;h2&gt;
  
  
  Facade in Laravel e il malinteso
&lt;/h2&gt;

&lt;p&gt;Le Facade di Laravel (&lt;code&gt;Cache::get()&lt;/code&gt;, &lt;code&gt;DB::table()&lt;/code&gt;, &lt;code&gt;Auth::check()&lt;/code&gt;) non sono il Facade Pattern del Gang of Four. Sono &lt;strong&gt;static proxy&lt;/strong&gt;: classi che risolvono un service dal container e delegano la chiamata statica a un'istanza. La confusione di nomenclatura e storica, ma e importante capire la differenza: il Facade Pattern originale crea un'interfaccia semplificata per un sottosistema complesso. Le "Facade" di Laravel sono un meccanismo di risoluzione dal container con sintassi statica.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quando usare il Facade Pattern
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Usa la Facade&lt;/strong&gt; quando un sottosistema ha molte classi e il caso d'uso comune richiede di coordinarle sempre nello stesso modo&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Usa la Facade&lt;/strong&gt; quando vuoi ridurre le dipendenze del codice client: una Facade al posto di sei classi&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Usa la Facade&lt;/strong&gt; quando vuoi creare un punto di ingresso chiaro per un modulo o package&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Non usare la Facade&lt;/strong&gt; per nascondere un cattivo design: se il sottosistema e confuso, semplificarlo con una Facade non risolve il problema strutturale&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Non usare la Facade&lt;/strong&gt; se il sottosistema ha una sola classe: stai aggiungendo un layer di indirezione senza beneficio&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Il Facade Pattern e il pattern della cortesia: rende un sistema complesso accessibile senza semplificarlo oltre misura. Non elimina la complessità — la nasconde dietro un'interfaccia pulita per chi non ha bisogno di vederla, e la lascia accessibile per chi ne ha bisogno.&lt;/p&gt;




&lt;p&gt;👉 &lt;strong&gt;&lt;a href="https://iadicola.it/articoli/facade-pattern-semplificare-accesso-sistemi-complessi?utm_source=devto&amp;amp;utm_medium=social" rel="noopener noreferrer"&gt;Leggi l'articolo completo su iadicola.it&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>architettura</category>
      <category>designpattern</category>
      <category>solid</category>
      <category>refactoring</category>
    </item>
    <item>
      <title>Composite Pattern: trattare gerarchie come singoli oggetti</title>
      <dc:creator>Dev-Iadicola</dc:creator>
      <pubDate>Sun, 02 Aug 2026 17:00:27 +0000</pubDate>
      <link>https://dev.to/dev_iadicola/composite-pattern-trattare-gerarchie-come-singoli-oggetti-31pn</link>
      <guid>https://dev.to/dev_iadicola/composite-pattern-trattare-gerarchie-come-singoli-oggetti-31pn</guid>
      <description>&lt;h2&gt;
  
  
  Il problema: strutture ricorsive con trattamento diverso
&lt;/h2&gt;

&lt;p&gt;Un menu di navigazione ha voci semplici (link a una pagina) e voci con sotto-menu (dropdown che contengono altre voci). Il codice che renderizza il menu deve distinguere costantemente: "questa voce e un link diretto o un contenitore?" — e dentro il contenitore, ripetere la stessa domanda per ogni elemento. Ogni rendering, ogni conteggio, ogni ricerca richiede un &lt;code&gt;if (is_array($item))&lt;/code&gt; o un &lt;code&gt;instanceof&lt;/code&gt; per distinguere foglie da nodi.&lt;/p&gt;

&lt;p&gt;Lo stesso problema emerge ovunque ci siano &lt;strong&gt;strutture ad albero&lt;/strong&gt;: un filesystem (file e cartelle), un'organizzazione aziendale (dipendenti e dipartimenti), un preventivo (singole voci e raggruppamenti), un layout UI (componenti singoli e container). Il &lt;strong&gt;Composite Pattern&lt;/strong&gt; elimina la distinzione: foglie e nodi implementano la stessa interfaccia, e il codice client li tratta allo stesso modo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cos'e il Composite Pattern: definizione formale
&lt;/h2&gt;

&lt;p&gt;Il Gang of Four definisce il Composite come un pattern strutturale che "compone oggetti in strutture ad albero per rappresentare gerarchie parte-intero. Il Composite permette ai client di trattare oggetti singoli e composizioni di oggetti in modo uniforme". La struttura prevede:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Component&lt;/strong&gt;: l'interfaccia comune a foglie e compositi (es. &lt;code&gt;MenuItemInterface&lt;/code&gt; con &lt;code&gt;render(): string&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Leaf&lt;/strong&gt;: l'elemento terminale che non contiene figli (es. &lt;code&gt;MenuItem&lt;/code&gt; — un singolo link)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Composite&lt;/strong&gt;: l'elemento che contiene figli, anch'esso Component (es. &lt;code&gt;MenuGroup&lt;/code&gt; — un dropdown con sotto-voci)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;La chiave e che &lt;code&gt;MenuGroup&lt;/code&gt; implementa &lt;code&gt;MenuItemInterface&lt;/code&gt; e contiene un array di &lt;code&gt;MenuItemInterface&lt;/code&gt;. Il suo metodo &lt;code&gt;render()&lt;/code&gt; chiama &lt;code&gt;render()&lt;/code&gt; su ogni figlio. I figli possono essere &lt;code&gt;MenuItem&lt;/code&gt; (foglie) o altri &lt;code&gt;MenuGroup&lt;/code&gt; (compositi) — la ricorsione e naturale.&lt;/p&gt;

&lt;h2&gt;
  
  
  Esempio teorico: un sistema di preventivi
&lt;/h2&gt;

&lt;p&gt;Un preventivo per un progetto web ha una struttura gerarchica:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Progetto Completo&lt;/strong&gt; (composito, 15.000 EUR totale)

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Frontend&lt;/strong&gt; (composito, 6.000 EUR)

&lt;ul&gt;
&lt;li&gt;Design UI — 2.000 EUR (foglia)&lt;/li&gt;
&lt;li&gt;Sviluppo template — 2.500 EUR (foglia)&lt;/li&gt;
&lt;li&gt;Responsive testing — 1.500 EUR (foglia)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Backend&lt;/strong&gt; (composito, 7.000 EUR)

&lt;ul&gt;
&lt;li&gt;API REST — 3.000 EUR (foglia)&lt;/li&gt;
&lt;li&gt;Autenticazione — 2.000 EUR (foglia)&lt;/li&gt;
&lt;li&gt;Pannello admin — 2.000 EUR (foglia)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deploy &amp;amp; Infrastruttura&lt;/strong&gt; (composito, 2.000 EUR)

&lt;ul&gt;
&lt;li&gt;Setup server — 1.000 EUR (foglia)&lt;/li&gt;
&lt;li&gt;CI/CD pipeline — 1.000 EUR (foglia)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;L'interfaccia &lt;code&gt;QuoteItemInterface&lt;/code&gt; ha due metodi: &lt;code&gt;getTotal(): float&lt;/code&gt; e &lt;code&gt;getDescription(): string&lt;/code&gt;. La foglia &lt;code&gt;QuoteLine&lt;/code&gt; restituisce il proprio importo. Il composito &lt;code&gt;QuoteGroup&lt;/code&gt; somma i totali di tutti i figli. Chiamare &lt;code&gt;$progetto-&amp;gt;getTotal()&lt;/code&gt; calcola ricorsivamente il totale dell'intero preventivo, indipendentemente dalla profondita della gerarchia.&lt;/p&gt;

&lt;h3&gt;
  
  
  Operazioni uniformi sulla gerarchia
&lt;/h3&gt;

&lt;p&gt;Se aggiungi un metodo &lt;code&gt;applyDiscount(float $percentage): void&lt;/code&gt; all'interfaccia, la foglia applica lo sconto al proprio importo, e il composito delega ad ogni figlio. Uno sconto applicato al nodo "Backend" si propaga automaticamente a "API REST", "Autenticazione" e "Pannello admin". Uno sconto applicato al nodo radice si propaga all'intero preventivo. Il codice che applica lo sconto non sa e non deve sapere se sta operando su una foglia o su un albero di 50 nodi.&lt;/p&gt;

&lt;h2&gt;
  
  
  Esempio teorico: un filesystem virtuale
&lt;/h2&gt;

&lt;p&gt;L'esempio classico del Composite e il filesystem. L'interfaccia &lt;code&gt;FileSystemEntry&lt;/code&gt; dichiara: &lt;code&gt;getSize(): int&lt;/code&gt;, &lt;code&gt;getName(): string&lt;/code&gt;, &lt;code&gt;getPath(): string&lt;/code&gt;. La foglia &lt;code&gt;File&lt;/code&gt; restituisce la propria dimensione. Il composito &lt;code&gt;Directory&lt;/code&gt; somma le dimensioni di tutti i figli (file e sotto-directory). Chiamare &lt;code&gt;$rootDir-&amp;gt;getSize()&lt;/code&gt; calcola ricorsivamente la dimensione dell'intero albero.&lt;/p&gt;

&lt;p&gt;Aggiungere operazioni e semplice: &lt;code&gt;find(string $name): array&lt;/code&gt; nella foglia controlla il proprio nome, nella directory delega a tutti i figli e raccoglie i risultati. &lt;code&gt;delete(): void&lt;/code&gt; nella foglia rimuove il file, nella directory rimuove ricorsivamente tutto il contenuto e poi se stessa. Ogni operazione si definisce una volta per la foglia e una volta per il composito.&lt;/p&gt;

&lt;h2&gt;
  
  
  Composite e il rendering di UI
&lt;/h2&gt;

&lt;p&gt;Nei sistemi di rendering UI, il Composite Pattern e onnipresente. Un &lt;code&gt;Panel&lt;/code&gt; contiene &lt;code&gt;Button&lt;/code&gt;, &lt;code&gt;Label&lt;/code&gt;, &lt;code&gt;TextField&lt;/code&gt; e altri &lt;code&gt;Panel&lt;/code&gt;. Il metodo &lt;code&gt;render()&lt;/code&gt; di un &lt;code&gt;Panel&lt;/code&gt; renderizza tutti i figli in sequenza. Il metodo &lt;code&gt;setVisible(false)&lt;/code&gt; nasconde il panel e tutti i suoi figli. Il metodo &lt;code&gt;validate()&lt;/code&gt; valida tutti i campi contenuti, ricorsivamente.&lt;/p&gt;

&lt;p&gt;React, Vue, Blade — tutti i sistemi di templating moderni usano il Composite Pattern implicitamente: un componente può contenere altri componenti, e il rendering e ricorsivo. La differenza e che nel Composite Pattern classico l'interfaccia e esplicita e tipizzata, mentre nei template engine e implicita nella struttura del markup.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quando usare il Composite Pattern
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Usa il Composite&lt;/strong&gt; quando i dati hanno una struttura ad albero naturale (menu, filesystem, organizzazioni, preventivi, UI)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Usa il Composite&lt;/strong&gt; quando vuoi trattare singoli elementi e gruppi di elementi allo stesso modo&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Usa il Composite&lt;/strong&gt; quando le operazioni devono propagarsi ricorsivamente nella gerarchia&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Non usare il Composite&lt;/strong&gt; se la struttura e piatta: non forzare un albero dove basta una lista&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Non usare il Composite&lt;/strong&gt; se foglie e compositi hanno comportamenti radicalmente diversi: il Composite funziona quando l'interfaccia comune ha senso per entrambi&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Il Composite Pattern trasforma la complessità strutturale in semplicità d'uso: una gerarchia di qualsiasi profondita si usa come un singolo oggetto. E uno dei pattern che meglio dimostrano come la ricorsione e il polimorfismo, combinati, possano gestire complessità che sembrerebbe richiedere logica ad hoc.&lt;/p&gt;




&lt;p&gt;👉 &lt;strong&gt;&lt;a href="https://iadicola.it/articoli/composite-pattern-trattare-gerarchie-come-singoli-oggetti?utm_source=devto&amp;amp;utm_medium=social" rel="noopener noreferrer"&gt;Leggi l'articolo completo su iadicola.it&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>php84</category>
      <category>architettura</category>
      <category>designpattern</category>
      <category>refactoring</category>
    </item>
    <item>
      <title>Iterator Pattern: attraversare collezioni senza esporne la struttura</title>
      <dc:creator>Dev-Iadicola</dc:creator>
      <pubDate>Sat, 01 Aug 2026 17:00:13 +0000</pubDate>
      <link>https://dev.to/dev_iadicola/iterator-pattern-attraversare-collezioni-senza-esporne-la-struttura-b4b</link>
      <guid>https://dev.to/dev_iadicola/iterator-pattern-attraversare-collezioni-senza-esporne-la-struttura-b4b</guid>
      <description>&lt;h2&gt;
  
  
  Il problema: attraversamento accoppiato alla struttura
&lt;/h2&gt;

&lt;p&gt;Hai una classe &lt;code&gt;UserCollection&lt;/code&gt; che internamente usa un array PHP. Il codice client fa &lt;code&gt;for ($i = 0; $i &amp;lt; $collection-&amp;gt;count(); $i++) { $user = $collection-&amp;gt;getAt($i); ... }&lt;/code&gt;. Funziona, ma il client sa che la collezione e indicizzata per posizione. Se domani la struttura interna cambia — un albero, una linked list, un result set paginato dal database — il codice client si rompe.&lt;/p&gt;

&lt;p&gt;Il problema e l'&lt;strong&gt;accoppiamento tra attraversamento e struttura&lt;/strong&gt;. Chi usa la collezione non dovrebbe sapere come e organizzata internamente. Dovrebbe solo poter dire "dammi il prossimo elemento" fino a che non ce ne sono più. L'&lt;strong&gt;Iterator Pattern&lt;/strong&gt; formalizza questa separazione.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cos'e l'Iterator Pattern: definizione formale
&lt;/h2&gt;

&lt;p&gt;Il Gang of Four definisce l'Iterator come un pattern comportamentale che "fornisce un modo per accedere sequenzialmente agli elementi di un oggetto aggregato senza esporne la rappresentazione sottostante". La struttura prevede:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Iterator&lt;/strong&gt;: l'interfaccia con metodi come &lt;code&gt;current()&lt;/code&gt;, &lt;code&gt;next()&lt;/code&gt;, &lt;code&gt;hasNext()&lt;/code&gt;, &lt;code&gt;rewind()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ConcreteIterator&lt;/strong&gt;: implementa l'attraversamento per una struttura dati specifica&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Aggregate&lt;/strong&gt;: l'interfaccia della collezione con un metodo &lt;code&gt;createIterator()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ConcreteAggregate&lt;/strong&gt;: la collezione che crea il proprio iteratore&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In PHP, il pattern e talmente fondamentale da essere integrato nel linguaggio: le interfacce &lt;code&gt;Iterator&lt;/code&gt; e &lt;code&gt;IteratorAggregate&lt;/code&gt; di SPL permettono a qualsiasi oggetto di essere usato in un &lt;code&gt;foreach&lt;/code&gt;. Se la tua classe implementa &lt;code&gt;Iterator&lt;/code&gt;, il &lt;code&gt;foreach&lt;/code&gt; funziona automaticamente — il linguaggio stesso usa l'Iterator Pattern.&lt;/p&gt;

&lt;h2&gt;
  
  
  Esempio teorico: paginazione trasparente dal database
&lt;/h2&gt;

&lt;p&gt;Immagina di dover processare 100.000 utenti dal database. Caricarli tutti in memoria e impraticabile: servirebbero gigabyte di RAM. La soluzione e un &lt;code&gt;PaginatedUserIterator&lt;/code&gt; che carica gli utenti a blocchi di 1.000:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Il costruttore riceve la query base e la dimensione del blocco&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;current()&lt;/code&gt; restituisce l'utente corrente dal blocco caricato&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;next()&lt;/code&gt; avanza al prossimo utente; quando il blocco finisce, carica il blocco successivo dal database&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;valid()&lt;/code&gt; restituisce false quando non ci sono più blocchi&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Il codice client e un semplice &lt;code&gt;foreach ($users as $user)&lt;/code&gt; — non sa e non deve sapere che sotto il cofano stanno avvenendo 100 query da 1.000 record ciascuna. La memoria usata e costante (1.000 oggetti alla volta), indipendentemente dal numero totale di utenti. Questo e il potere dell'Iterator: disaccoppia il "cosa fare con ogni elemento" dal "come ottenere il prossimo elemento".&lt;/p&gt;

&lt;h2&gt;
  
  
  Generator PHP: Iterator senza boilerplate
&lt;/h2&gt;

&lt;p&gt;PHP offre i &lt;strong&gt;generator&lt;/strong&gt; come zucchero sintattico per creare Iterator senza implementare l'intera interfaccia. Un generator e una funzione che usa &lt;code&gt;yield&lt;/code&gt; invece di &lt;code&gt;return&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;function paginatedUsers(int $chunkSize): Generator { $offset = 0; while ($chunk = fetchUsersChunk($offset, $chunkSize)) { foreach ($chunk as $user) { yield $user; } $offset += $chunkSize; } }&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Il generator produce un oggetto &lt;code&gt;Generator&lt;/code&gt; che implementa &lt;code&gt;Iterator&lt;/code&gt;. Il &lt;code&gt;foreach (paginatedUsers(1000) as $user)&lt;/code&gt; funziona identicamente all'esempio precedente, ma con 6 righe invece di una classe intera. I generator sono la forma moderna dell'Iterator Pattern in PHP.&lt;/p&gt;

&lt;h3&gt;
  
  
  Lazy evaluation: calcolare solo cio che serve
&lt;/h3&gt;

&lt;p&gt;I generator sono &lt;strong&gt;lazy&lt;/strong&gt; per natura: producono il valore successivo solo quando richiesto. Se il &lt;code&gt;foreach&lt;/code&gt; fa &lt;code&gt;break&lt;/code&gt; dopo 10 elementi, il generator non carichera mai gli altri 99.990. Questa lazy evaluation e impossibile con un array: &lt;code&gt;array_map&lt;/code&gt; e &lt;code&gt;array_filter&lt;/code&gt; processano sempre l'intera collezione, anche se serve solo il primo risultato.&lt;/p&gt;

&lt;p&gt;La combinazione di generator e &lt;code&gt;yield from&lt;/code&gt; permette di comporre iteratori: un generator che filtra, uno che trasforma, uno che limita — ogni step e lazy e la pipeline processa un elemento alla volta, senza mai tenere l'intera collezione in memoria.&lt;/p&gt;

&lt;h2&gt;
  
  
  Esempio teorico: file processing riga per riga
&lt;/h2&gt;

&lt;p&gt;Un file CSV di 2 GB non può essere caricato in memoria con &lt;code&gt;file()&lt;/code&gt;. Un &lt;code&gt;CsvIterator&lt;/code&gt; apre il file, legge una riga alla volta con &lt;code&gt;fgets()&lt;/code&gt;, la parsa e la &lt;code&gt;yield&lt;/code&gt;a. Il codice client fa &lt;code&gt;foreach (new CsvIterator('data.csv') as $row)&lt;/code&gt; e processa 2 GB di dati con 10 KB di memoria.&lt;/p&gt;

&lt;p&gt;Questo approccio si combina con i generator per creare pipeline di trasformazione:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;readCsv('data.csv')&lt;/code&gt; — generator che produce righe grezze&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;filterActive($rows)&lt;/code&gt; — generator che filtra solo le righe con status attivo&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;mapToEntity($rows)&lt;/code&gt; — generator che trasforma array in oggetti&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;batchInsert($entities, 500)&lt;/code&gt; — generator che raggruppa in batch e inserisce nel database&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ogni step processa un elemento alla volta. L'intero file da 2 GB viene processato con un consumo di memoria costante. Senza l'Iterator Pattern (e i generator come sua implementazione moderna), questo sarebbe impossibile o richiederebbe codice molto più complesso.&lt;/p&gt;

&lt;h2&gt;
  
  
  Iterator e interfacce SPL in PHP
&lt;/h2&gt;

&lt;p&gt;PHP offre diverse interfacce e classi nell'estensione SPL per casi d'uso specifici:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;FilterIterator&lt;/strong&gt;: wrappa un iteratore e restituisce solo gli elementi che soddisfano una condizione&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LimitIterator&lt;/strong&gt;: wrappa un iteratore e restituisce solo i primi N elementi&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AppendIterator&lt;/strong&gt;: concatena più iteratori in una sequenza unica&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;RecursiveIteratorIterator&lt;/strong&gt;: attraversa strutture ricorsive (alberi di directory, menu annidati)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CachingIterator&lt;/strong&gt;: aggiunge lookahead — sai se c'e un elemento successivo prima di avanzare&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Queste classi si compongono come Decorator: &lt;code&gt;new LimitIterator(new FilterIterator(new ArrayIterator($data)), 0, 10)&lt;/code&gt; crea un iteratore che filtra e limita a 10 risultati. E OOP puro, senza un singolo &lt;code&gt;for&lt;/code&gt; nel codice client.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quando usare l'Iterator Pattern
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Usa l'Iterator&lt;/strong&gt; quando la struttura dati e complessa (alberi, grafi, risultati paginati) e vuoi nasconderla al client&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Usa l'Iterator&lt;/strong&gt; quando i dati sono troppi per stare in memoria e servono lazy loading o streaming&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Usa l'Iterator&lt;/strong&gt; quando vuoi comporre pipeline di trasformazione senza allocare array intermedi&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Usa i Generator&lt;/strong&gt; come implementazione moderna quando non serve un'intera classe Iterator&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Non usare l'Iterator&lt;/strong&gt; se hai un semplice array PHP: il &lt;code&gt;foreach&lt;/code&gt; su array e già ottimale&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Non usare l'Iterator&lt;/strong&gt; se hai bisogno di accesso random (per indice): l'Iterator e sequenziale per definizione&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;L'Iterator Pattern e così fondamentale che ogni linguaggio moderno lo integra nella propria sintassi. In PHP, il &lt;code&gt;foreach&lt;/code&gt; e l'Iterator Pattern reso trasparente. Ma capire il pattern dietro il costrutto sintattico permette di crearne di nuovi — iteratori lazy, paginati, filtrati — che risolvono problemi reali con eleganza e efficienza.&lt;/p&gt;




&lt;p&gt;👉 &lt;strong&gt;&lt;a href="https://iadicola.it/articoli/iterator-pattern-attraversare-collezioni-senza-esporne-struttura?utm_source=devto&amp;amp;utm_medium=social" rel="noopener noreferrer"&gt;Leggi l'articolo completo su iadicola.it&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>php84</category>
      <category>performance</category>
      <category>architettura</category>
      <category>designpattern</category>
    </item>
    <item>
      <title>Dependency Injection: il pattern che rende tutto il resto possibile</title>
      <dc:creator>Dev-Iadicola</dc:creator>
      <pubDate>Fri, 31 Jul 2026 17:00:13 +0000</pubDate>
      <link>https://dev.to/dev_iadicola/dependency-injection-il-pattern-che-rende-tutto-il-resto-possibile-4bo</link>
      <guid>https://dev.to/dev_iadicola/dependency-injection-il-pattern-che-rende-tutto-il-resto-possibile-4bo</guid>
      <description>&lt;h2&gt;
  
  
  Il problema: classi che creano le proprie dipendenze
&lt;/h2&gt;

&lt;p&gt;Una classe &lt;code&gt;OrderService&lt;/code&gt; ha bisogno di un &lt;code&gt;OrderRepository&lt;/code&gt; per accedere ai dati e di un &lt;code&gt;Mailer&lt;/code&gt; per inviare conferme. L'approccio più istintivo e crearli internamente: &lt;code&gt;$this-&amp;gt;repository = new PgsqlOrderRepository()&lt;/code&gt; e &lt;code&gt;$this-&amp;gt;mailer = new SmtpMailer()&lt;/code&gt;. Sembra semplice, ma ha conseguenze profonde.&lt;/p&gt;

&lt;p&gt;Primo: &lt;code&gt;OrderService&lt;/code&gt; e &lt;strong&gt;accoppiato al cemento&lt;/strong&gt;. Sa che il repository e PostgreSQL e il mailer e SMTP. Se vuoi usare MySQL o un mock per i test, devi modificare &lt;code&gt;OrderService&lt;/code&gt;. Secondo: non puoi testare &lt;code&gt;OrderService&lt;/code&gt; senza un database e un server SMTP reali. Terzo: se &lt;code&gt;PgsqlOrderRepository&lt;/code&gt; a sua volta crea le proprie dipendenze, hai una catena di creazione che nessuno controlla centralmente. Ogni classe e responsabile di crearsi il proprio mondo — e questo rende il sistema rigido, fragile e difficile da testare.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cos'e la Dependency Injection
&lt;/h2&gt;

&lt;p&gt;La &lt;strong&gt;Dependency Injection&lt;/strong&gt; (DI) e un principio semplice: una classe non crea le proprie dipendenze, le riceve dall'esterno. Invece di &lt;code&gt;$this-&amp;gt;repository = new PgsqlOrderRepository()&lt;/code&gt;, il costruttore dichiara: &lt;code&gt;public function __construct(private readonly OrderRepositoryInterface $repository, private readonly MailerInterface $mailer)&lt;/code&gt;. Chi crea &lt;code&gt;OrderService&lt;/code&gt; decide quale implementazione passare.&lt;/p&gt;

&lt;p&gt;La DI non e un framework, non e un container, non e una libreria. E un &lt;strong&gt;principio di design&lt;/strong&gt;: le dipendenze vengono iniettate, non create internamente. Esistono tre forme:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Constructor Injection&lt;/strong&gt;: le dipendenze vengono passate nel costruttore. E la forma preferita perché rende le dipendenze esplicite e immutabili: la classe non può esistere senza le sue dipendenze.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Setter Injection&lt;/strong&gt;: le dipendenze vengono passate tramite metodi setter. Utile per dipendenze opzionali, ma rende possibile l'uso della classe in uno stato incompleto.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Method Injection&lt;/strong&gt;: la dipendenza viene passata come parametro del metodo che la usa. Utile quando la dipendenza varia ad ogni chiamata.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Esempio teorico: un servizio ordini testabile
&lt;/h2&gt;

&lt;p&gt;Senza DI, testare &lt;code&gt;OrderService&lt;/code&gt; richiede un database reale con dati di test e un server SMTP (o un mock complesso). Con DI, il test crea implementazioni fake:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;InMemoryOrderRepository&lt;/code&gt;: implementa &lt;code&gt;OrderRepositoryInterface&lt;/code&gt; con un array PHP. &lt;code&gt;save()&lt;/code&gt; aggiunge all'array. &lt;code&gt;findById()&lt;/code&gt; cerca nell'array. Zero database, zero latenza.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;SpyMailer&lt;/code&gt;: implementa &lt;code&gt;MailerInterface&lt;/code&gt; registrando ogni email in un array interno. Il test verifica: &lt;code&gt;$this-&amp;gt;assertCount(1, $mailer-&amp;gt;getSentEmails())&lt;/code&gt;. Zero SMTP, zero email reali.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Il test diventa: &lt;code&gt;$service = new OrderService(new InMemoryOrderRepository(), new SpyMailer()); $service-&amp;gt;cancel($orderId); $this-&amp;gt;assertTrue(...)&lt;/code&gt;. E un test unitario puro: testa la logica di cancellazione senza dipendenze esterne, senza database, senza rete. Gira in millisecondi.&lt;/p&gt;

&lt;h3&gt;
  
  
  Il test dice la verità sul design
&lt;/h3&gt;

&lt;p&gt;Se una classe e difficile da testare, quasi sempre e perché le dipendenze non sono iniettate. Il test e il primo "utente" della classe, e se l'utente fa fatica, il design ha un problema. La DI non e un requisito per il testing — e un requisito per il &lt;strong&gt;buon design&lt;/strong&gt;, e il testing e la prova empirica.&lt;/p&gt;

&lt;h2&gt;
  
  
  Il Container: automazione della DI
&lt;/h2&gt;

&lt;p&gt;Con la DI manuale, chi crea &lt;code&gt;OrderService&lt;/code&gt; deve conoscere tutte le sue dipendenze e le dipendenze delle dipendenze. In un'applicazione con 50 classi, questa catena diventa lunga e ripetitiva. Il &lt;strong&gt;DI Container&lt;/strong&gt; automatizza la risoluzione:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Registri le associazioni: &lt;code&gt;OrderRepositoryInterface&lt;/code&gt; → &lt;code&gt;PgsqlOrderRepository&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Il container legge il costruttore di &lt;code&gt;OrderService&lt;/code&gt; via Reflection&lt;/li&gt;
&lt;li&gt;Vede che serve un &lt;code&gt;OrderRepositoryInterface&lt;/code&gt;, lo risolve a &lt;code&gt;PgsqlOrderRepository&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Crea ricorsivamente tutte le dipendenze necessarie&lt;/li&gt;
&lt;li&gt;Restituisce un &lt;code&gt;OrderService&lt;/code&gt; completamente assemblato&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Il container e un lusso, non una necessita. Per progetti piccoli, la DI manuale (creare gli oggetti nel bootstrap) e perfettamente valida. Per progetti con decine di servizi e dipendenze profonde, il container elimina il boilerplate di assemblaggio.&lt;/p&gt;

&lt;h2&gt;
  
  
  DI e il Dependency Inversion Principle
&lt;/h2&gt;

&lt;p&gt;La Dependency Injection e la tecnica. Il &lt;strong&gt;Dependency Inversion Principle&lt;/strong&gt; (la D di SOLID) e il principio: "i moduli di alto livello non dovrebbero dipendere da moduli di basso livello. Entrambi dovrebbero dipendere da astrazioni." La DI e il meccanismo pratico per realizzare questo principio.&lt;/p&gt;

&lt;p&gt;Senza DI, &lt;code&gt;OrderService&lt;/code&gt; (alto livello) dipende da &lt;code&gt;PgsqlOrderRepository&lt;/code&gt; (basso livello). Con DI, &lt;code&gt;OrderService&lt;/code&gt; dipende da &lt;code&gt;OrderRepositoryInterface&lt;/code&gt; (astrazione), e &lt;code&gt;PgsqlOrderRepository&lt;/code&gt; implementa quell'astrazione. La direzione della dipendenza si e &lt;strong&gt;invertita&lt;/strong&gt;: il modulo di basso livello dipende dall'astrazione definita dal modulo di alto livello, non viceversa.&lt;/p&gt;

&lt;h2&gt;
  
  
  Errori comuni con la DI
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Service Locator&lt;/strong&gt;: iniettare il container stesso e usarlo per risolvere le dipendenze a runtime. Nasconde le dipendenze reali e rende il codice opaco. Le dipendenze devono essere nel costruttore, non risolte a runtime.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Troppe dipendenze&lt;/strong&gt;: se un costruttore ha 8 parametri, il problema non e la DI — e che la classe ha troppe responsabilità. La DI rende visibile il problema, non lo causa.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interfacce inutili&lt;/strong&gt;: creare un'interfaccia per ogni classe "perché la DI lo richiede" e cargo cult. L'interfaccia serve quando ci sono (o ci saranno realisticamente) multiple implementazioni. Una &lt;code&gt;UserRepositoryInterface&lt;/code&gt; con una sola implementazione e burocrazia — a meno che non serva per il testing, e allora ha un motivo concreto.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Auto-wiring magico&lt;/strong&gt;: affidarsi ciecamente alla risoluzione automatica del container rende invisibili le dipendenze. E comodo ma va bilanciato con la leggibilità.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Quando usare la Dependency Injection
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Sempre&lt;/strong&gt; per le dipendenze di servizio (repository, mailer, logger, cache): sono le dipendenze che cambiano tra ambienti (produzione, test, staging)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sempre&lt;/strong&gt; quando vuoi che la classe sia testabile con mock o fake&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Non necessaria&lt;/strong&gt; per value objects e DTO: creare un &lt;code&gt;new Money(100, 'EUR')&lt;/code&gt; internamente e perfettamente valido&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Non necessaria&lt;/strong&gt; per factory di oggetti semplici: non serve iniettare una factory se la creazione e banale&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;La Dependency Injection non e un pattern opzionale da adottare quando si diventa esperti: e il &lt;strong&gt;fondamento&lt;/strong&gt; che rende possibili tutti gli altri pattern. Strategy, Repository, Observer, Decorator — tutti funzionano perché le dipendenze sono iniettate, non create internamente. Senza DI, i pattern diventano rigidi e non sostituibili. Con DI, diventano componenti intercambiabili di un sistema flessibile.&lt;/p&gt;




&lt;p&gt;👉 &lt;strong&gt;&lt;a href="https://iadicola.it/articoli/dependency-injection-pattern-che-rende-tutto-il-resto-possibile?utm_source=devto&amp;amp;utm_medium=social" rel="noopener noreferrer"&gt;Leggi l'articolo completo su iadicola.it&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>php84</category>
      <category>architettura</category>
      <category>designpattern</category>
      <category>solid</category>
    </item>
  </channel>
</rss>
