{"id":2547,"date":"2024-12-17T16:02:49","date_gmt":"2024-12-17T16:02:49","guid":{"rendered":"https:\/\/www.giuseppemaccario.com\/it\/?p=2547"},"modified":"2025-01-10T10:04:19","modified_gmt":"2025-01-10T10:04:19","slug":"churn-php-come-identificare-i-mostri-nei-tuoi-progetti-php","status":"publish","type":"post","link":"https:\/\/www.giuseppemaccario.com\/it\/churn-php-come-identificare-i-mostri-nei-tuoi-progetti-php\/","title":{"rendered":"Churn PHP: come identificare i mostri nei tuoi progetti PHP"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\" id=\"tldr\">TL;DR<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Churn PHP \u00e8 uno strumento che aiuta a individuare i file di codice pi\u00f9 problematici in un progetto, combinando complessit\u00e0 e frequenza di modifiche (churn). Codici con alta complessit\u00e0 e frequenti modifiche rappresentano candidati ideali per il refactoring, una pratica che dovrebbe essere parte quotidiana dello sviluppo per migliorare manutenibilit\u00e0 e stabilit\u00e0 del codice.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"sommario\">Sommario<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li><a href=\"#introduzione\">Introduzione<\/a><\/li>\n\n\n\n<li><a href=\"#complessit%C3%A0-del-codice\">Complessit\u00e0 del codice<\/a>\n<ul class=\"wp-block-list\">\n<li><a href=\"#cyclomatic-complexity\">Cyclomatic Complexity<\/a><\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><a href=\"#refactoring\">Refactoring<\/a>\n<ul class=\"wp-block-list\">\n<li><a href=\"#come-dare-priorit%C3%A0-ai-file\">Come dare priorit\u00e0 ai file<\/a><\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><a href=\"#cos%C3%A8-churn-php\">Cos&#8217;\u00e8 Churn PHP<\/a>\n<ul class=\"wp-block-list\">\n<li><a href=\"#come-funziona\">Come funziona<\/a><\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><a href=\"#le-metriche\">Le metriche<\/a>\n<ul class=\"wp-block-list\">\n<li><a href=\"#times-changed\">Times Changed<\/a><\/li>\n\n\n\n<li><a href=\"#complexity\">Complexity<\/a><\/li>\n\n\n\n<li><a href=\"#score\">Score<\/a><\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><a href=\"#esempi-pratici-di-refactoring\">Esempi pratici di refactoring<\/a>\n<ul class=\"wp-block-list\">\n<li><a href=\"#itemcontrollerphp-stato-iniziale\">ItemController.php (Stato iniziale)<\/a><\/li>\n\n\n\n<li><a href=\"#passaggi-per-il-refactoring\">Passaggi per il refactoring<\/a><\/li>\n\n\n\n<li><a href=\"#createcontrollerphp\">CreateController.php<\/a><\/li>\n\n\n\n<li><a href=\"#getlistcontrollerphp\">GetListController.php<\/a><\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><a href=\"#approfondimento-su-churn-php\">Approfondimento su Churn PHP<\/a>\n<ul class=\"wp-block-list\">\n<li><a href=\"#configurazione-avanzata\">Configurazione avanzata<\/a><\/li>\n\n\n\n<li><a href=\"#file-di-esempio-churnyml\">File di esempio churn.yml<\/a><\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><a href=\"#conclusione\">Conclusione<\/a><\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"introduzione\">Introduzione<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Quante volte, iniziando a lavorare per una nuova azienda, hai aperto un file contenente una sola classe e, con grande sorpresa, hai scoperto che contiene 3000 righe di codice? A me \u00e8 capitato tantissime volte. E mi chiedo sempre perch\u00e9 noi sviluppatori non dedichiamo del tempo a un&#8217;attivit\u00e0 fondamentale che, molto spesso, farebbe risparmiare tempo e soldi in futuro? Mi riferisco al refactoring.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In molti mi hanno detto: &#8220;Finch\u00e9 funziona, non si tocca&#8221;. Oppure: &#8220;Sono solo dettagli&#8221;, o ancora la classica scusa: &#8220;Non abbiamo tempo&#8221;. Ma il tempo per altre attivit\u00e1, come un meme o una sigaretta, spesso lo troviamo in molti. \u00c8 vero, toccare un pezzo di codice implica uno sforzo ulteriore: altri test (automatici o manuali), altri messaggi di commit a cui pensare, insomma, altre grane. Ma siamo sviluppatori, non lavoriamo in un fast food &#8211; spoiler: io ho lavorato in un fast food quando <em>ero giovane<\/em>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Per quanto mi riguarda, ridurre la complessit\u00e0 nel codice <strong>\u00e8 e deve essere una priorit\u00e0<\/strong>. Il refactoring \u00e8 un&#8217;attivit\u00e0 di sviluppo esattamente come lo sono scrivere test, fare bug fixing o sviluppare nuove funzionalit\u00e0.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"complessit\u00e0-del-codice\">Complessit\u00e0 del codice<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Il problema di una classe contenente 3000 linee non \u00e8 la lunghezza, ma la complessit\u00e0 nel leggere un &#8220;mostro&#8221; del genere. Avere molte ramificazioni significa dover tenere traccia di un numero troppo alto di variabili e flussi. Questo sforzo \u00e8 semplicemente troppo dispendioso in termini di sforzo mentale, e ci\u00f2 porta a errori. Inoltre, un &#8220;mostro&#8221; di 3000 righe sar\u00e0 difficile da testare nella sua interezza, perch\u00e9 ci saranno sicuramente dipendenze ed eccezioni di cui tenere conto.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Ma come si misura la complessit\u00e0 del codice? Un punto di partenza \u00e8 la <a href=\"https:\/\/en.wikipedia.org\/wiki\/Cyclomatic_complexity\" target=\"_blank\" rel=\"noreferrer noopener nofollow\">Cyclomatic complexity<\/a>, ovvero una metrica software utilizzata per indicare <em>una misura quantitativa del numero di percorsi linearmente indipendenti attraverso il codice sorgente di un programma<\/em>. \u00c8 stata sviluppata da <em>Thomas J. McCabe, Sr.<\/em> nel 1976. In altre parole, la Cyclomatic Complexity indica quante decisioni (if, loop, switch, ecc.) ci sono nel codice, aiutando a valutare la sua manutenibilit\u00e0 e il numero minimo di test necessari. Pi\u00f9 \u00e8 alta, pi\u00f9 il codice \u00e8 complesso da capire e testare. Ed ecco perch\u00e9 l&#8217;elevata complessit\u00e0 del codice \u00e8 (quasi) sempre negativa. Scrivo <em>quasi<\/em> perch\u00e9, se una classe non viene quasi mai toccata, potrebbe non risultare un grosso problema.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"refactoring\">Refactoring<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Come dicevo all&#8217;inizio dell&#8217;articolo, ho personalmente lavorato in molte aziende in cui la complessit\u00e0 del codice non era neanche percepita come un problema, e sto parlando di aziende sia italiane che straniere, grandi e piccole. E non \u00e8 vero che solo i progetti legacy soffrono di questo problema; a volte \u00e8 proprio il progetto in corso che, per poca sensibilit\u00e0 da parte degli sviluppatori \u2013 e dei manager \u2013 si porta dietro questo macigno, aggiungendo, giorno dopo giorno, complessit\u00e0 su complessit\u00e0. Un giorno sar\u00e0 chiamato &#8220;legacy&#8221;, e i futuri sviluppatori diranno che \u00e8 troppo complesso.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Allocare un intero sprint per un vasto refactoring non \u00e8 mai la soluzione, ma fare in modo che il refactoring diventi parte della nostra pratica quotidiana dovrebbe essere la strada giusta da seguire. Se facciamo refactoring mentre apportiamo modifiche al nostro codice, finiamo per lavorare con un codice progressivamente migliore. Ma come? A quali file dare la priorit\u00e0? Una regola \u00e8 <strong>dare priorit\u00e0 ai file che hanno un alto grado di complessit\u00e0 e cambiano abbastanza frequentemente<\/strong>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\u00c8 proprio la combinazione tra complessit\u00e0 e modifiche frequenti che guider\u00e0 il nostro refactoring.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"cos\u00e9-churn-php\">Cos&#8217;\u00e9 Churn PHP<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Churn PHP aiuta a scoprire buoni candidati per il refactoring. <a href=\"https:\/\/michaelfeathers.silvrback.com\/\" target=\"_blank\" rel=\"noreferrer noopener nofollow\">Michael Feathers<\/a> ha coniato il termine &#8220;churn&#8221; per descrivere il tasso di modifiche apportate ai file di un progetto. Il churn pu\u00f2 essere quantificato con un valore, simile a quello utilizzato per misurare la complessit\u00e0 del codice. Supponendo che ogni classe sia definita in un file separato e che ogni modifica a una classe corrisponda a un nuovo commit nel sistema di controllo versione, un metodo pratico per misurare il churn di una classe consiste nel conteggiare i commit che interessano il file in cui \u00e8 contenuta.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\u00c9 proprio su questa combinazione di fattori, <em>complessit\u00e1 e churn di una classe<\/em>, che Churn PHP fornisce dei valori numerici per individuare facilmente le classi che devono essere modificate spesso, ma che sono anche molto difficili da modificare, perch\u00e9 hanno un&#8217;elevata complessit\u00e0 del codice. <\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img decoding=\"async\" src=\"https:\/\/github.com\/bmitch\/churn-php\/raw\/master\/img\/output.png\" alt=\"image churn PHP in action\"\/><figcaption class=\"wp-element-caption\">Esempio di analisi Churn PHP<\/figcaption><\/figure>\n<\/div>\n\n\n<h2 class=\"wp-block-heading\" id=\"le-metriche\">Le metriche<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li><p><strong>Times Changed<\/strong>: Si riferisce al numero di volte in cui un determinato file o classe \u00e8 stato modificato in un dato periodo. \u00c8 un semplice conteggio dei commit relativi a quel file. In un progetto PHP, un numero elevato di modifiche a una classe o funzione specifica potrebbe indicare aree del codice che vengono aggiornate frequentemente, il che potrebbe suggerire una potenziale instabilit\u00e0 o requisiti in evoluzione.<\/p><\/li>\n\n\n\n<li><p><strong>Complexity<\/strong>: La complexity si riferisce a quanto il codice in una determinata classe o file sia complesso. Questo pu\u00f2 includere fattori come il numero di funzioni\/metodi, le dichiarazioni condizionali, i cicli annidati e la struttura generale del codice. Un file o una classe pi\u00f9 complessa pu\u00f2 risultare pi\u00f9 difficile da mantenere, comprendere e modificare, il che potrebbe portare a un churn pi\u00f9 elevato. La complessit\u00e0 \u00e8 spesso misurata utilizzando strumenti come la Cyclomatic complexity, che valuta il numero di percorsi indipendenti nel codice.<\/p><\/li>\n\n\n\n<li><p><strong>Score<\/strong>: Lo score \u00e8 una metrica complessiva che combina sia il Times Changed che la Complexity. \u00c8 un modo per quantificare quanta attenzione potrebbe richiedere un determinato file o classe. Un punteggio pi\u00f9 alto indica che il file ha subito molte modifiche e potrebbe anche avere una complessit\u00e0 elevata, suggerendo che si tratti di una parte critica o instabile del codice. Questo potrebbe indicare aree che necessitano di refactoring, test aggiuntivi o una migliore documentazione per garantirne la manutenibilit\u00e0 a lungo termine.<\/p><\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">Un valore di churn alto combinato con una complessit\u00e0 elevata potrebbe indicare aree del codice difficili da mantenere o soggette a bug, orientando le decisioni riguardo al refactoring o alla semplificazione del codice.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"esempi-pratici-di-refactoring\">Esempi pratici di refactoring<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Troppa teoria potrebbe mascherare l&#8217;impatto che queste metriche hanno sul nostro lavoro. Voglio mostrare un esempio concreto di come si pu\u00f2 semplificare una classe  per rendere l&#8217;articolo pi\u00f9 pratico e applicabile. \u00c9 un esempio molto semplice, ma ci sono casi pi\u00fa complessi come quelli di classi interdipendenti, in cui bisogna rompere le dipendenze introducendo nuovi design patterns.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Di seguito, la classe <em>ItemController.php<\/em>, contenuta in un progetto Laravel.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;?php\n\n\/* NOTE: here namespace and use *\/\n\nclass ItemController extends Controller\n{\n    \/**\n     * @param  Request  $request\n     * @return JsonResponse\n     *\/\n    public function create(Request $request): JsonResponse\n    {\n        $validate_data = $request-&gt;validate(&#91;\n            'slug' =&gt; 'required|string',\n            'item' =&gt; 'required|string',\n            'session_id' =&gt; 'nullable|string',\n        ]);\n\n        \/\/ Find message\/letter for its slug\n        $message = Message::where('slug', \"like\", \"%\" . $validate_data&#91;'slug'] . \"%\")-&gt;first();\n\n        if (!$message) {\n            return response()-&gt;json(&#91;\n                'item'       =&gt; '',\n                'session_id'    =&gt; '',\n                'slug'          =&gt; '',\n                'error'         =&gt; 'No message found!'\n            ]);\n        }\n\n        \/\/ Is there already an items for this user?\n        $item = null;\n        if (isset($validate_data&#91;'session_id'])) {\n            $item = Item::where('session_id', $validate_data&#91;'session_id'])-&gt;where('message_id', $message-&gt;id)-&gt;first();\n        }\n\n        if ($item) {\n            Item::destroy($item-&gt;id);\n        }\n\n        if ($validate_data&#91;'item'] === '' \n            || $validate_data&#91;'item'] === Constants::LINK) {\n            return response()-&gt;json(&#91;\n                'item'       =&gt; '',\n                'session_id'    =&gt; '',\n                'slug'          =&gt; '',\n                'error'         =&gt; 'No item selected!'\n            ]);\n        }\n\n        \/\/ Save new items\n        $item                = new Item();\n        $item-&gt;message_id    = $message-&gt;id;\n        $item-&gt;user_id       = (Auth::check()) ? Auth::user()-&gt;id : Constants::NOT_LOGGED_USER_ID;\n        $item-&gt;name          = $validate_data&#91;'name'];\n        $item-&gt;session_id    = (isset($validate_data&#91;'session_id'])) ? $validate_data&#91;'session_id'] : \\Session::getId();\n        $item-&gt;save();\n\n        return response()-&gt;json(&#91;\n            'item'       =&gt; $item-&gt;item,\n            'session_id'    =&gt; $item-&gt;session_id,\n            'slug'          =&gt; $validate_data&#91;'slug'],\n        ]);\n    }\n\n    \/**\n     * @param Request $request\n     * @return JsonResponse\n     *\/\n    public function getPublicItems(Request $request)\n    {\n        $request-&gt;merge(&#91;'slug' =&gt; $request-&gt;slug]);\n\n        $validate_data = $request-&gt;validate(&#91;\n            'slugs' =&gt; 'required|string',\n        ]);\n\n        \/\/ get messages from slugs\n        $arrSlugs = json_decode($validate_data&#91;'slugs'], true);\n        $query = Message::query();\n        foreach ($arrSlugs as $slug) {\n            $query-&gt;orWhere('slug', \"like\", \"%-\" . $slug);\n        }\n        $messages = $query-&gt;get(&#91;'id', 'slug']);\n\n        $ids = array();\n        foreach ($messages as $message) {\n            $ids&#91;] = $message-&gt;id;\n        }\n\n        \/\/ get items by messages ids\n        $items = Item::select('item', 'message_id', \\DB::raw('count(item) as item_count'))\n            -&gt;whereIn('message_id', $ids)\n            -&gt;groupBy('item', 'message_id')\n            -&gt;orderBy('message_id', 'desc')\n            -&gt;orderBy('item', 'desc')\n            -&gt;get();\n\n        \/\/ Prepare result\n        $results = &#91;];\n        foreach ($items as $item) {\n            foreach ($messages as $message) {\n                if ($item-&gt;message_id == $message-&gt;id) {\n                    $result = array();\n                    $result&#91;'slug']    = $this-&gt;getPublicSlug($message-&gt;slug);\n                    $result&#91;'item'] = $item-&gt;item;\n                    $result&#91;'count']   = $item-&gt;item_count;\n\n                    $results&#91;] = $result;\n                }\n            }\n        }\n\n        return response()-&gt;json(&#91;\n            'items' =&gt; $results,\n        ]);\n    }\n}\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Nello specifico questa classe \u00e9 un controller nella directory <em>Http\/Controllers<\/em> di base, e che Churn PHP mi indica con questi valori:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>+---------------------------------------------------+---------------+------------+-------+\n| File                                              | Times Changed | Complexity | Score |\n+---------------------------------------------------+---------------+------------+-------+\n| app\/Http\/Controllers\/ItemController.php           | 14            | 17         | 0.102 |\n+---------------------------------------------------+---------------+------------+-------+\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">In effetti \u00e9 una classe che ho cambiato spesso, e che contiene vari metodi pubblici, quindi possiamo dire che contiene molte responsabilit\u00e1 e che viola l&#8217;<em>SRP<\/em> (<em><a href=\"https:\/\/blog.cleancoder.com\/uncle-bob\/2020\/10\/18\/Solid-Relevance.html\" target=\"_blank\" rel=\"noreferrer noopener nofollow\">Single Responsibility Principle<\/a><\/em>). <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Ecco gli steps che ho seguito per semplificare la classe:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Dove mancano, ho creato nuove classi di Request, in questa maniera inizio con lo spostare la logica delle validazioni dal controller alle classi Requests;<\/li>\n\n\n\n<li>Dove posso, incapsulo alcune logiche in metodi privati, in maniera da eliminare commenti rindondanti e semplificare la lettura del codice. Non c&#8217;\u00e9 nessuno motivo di mantenere un commento di questo tipo <code>\/\/ Get messages by slugs<\/code> quando con PHPStorm posso comodamente selezionare il pezzo di codice interessato, e con un semplice comando come <a href=\"https:\/\/www.jetbrains.com\/help\/phpstorm\/extract-method.html\" target=\"_blank\" rel=\"noreferrer noopener nofollow\">Extract Method<\/a>, posso generare un nuovo metodo che semplicemente chiamer\u00f3 <code>getMessagesBySlugs<\/code>; il codice ora \u00e9 diventato autoesplicativo. In pi\u00fa posso eliminare alcune variabili perch\u00e9 ora sfrutto il ritorno inline dei valori nei nuovi metodi;<\/li>\n\n\n\n<li>User\u00f3 i metodi pubblici di questa classe per creare nuove classi, separate, che hanno una singola responsabilit\u00e0. I nomi delle nuove classi rispecchiano ora le funzionalit\u00e1, che non saranno pi\u00fa affogate in una grande classe generale. Piccolo dettaglio: le nuove classi avranno un unico metodo pubblico invoke() e saranno contenute nella cartella <code>Item<\/code>. Devo tenere conto di questa cosa anche nei <em>namespaces<\/em> e nel file delle rotte, dove scriver\u00f3 direttamente il namespace della classe che mi serve invece di indiciare i nomi dei metodi;<\/li>\n\n\n\n<li>Se posso, far\u00f3 anche leva su una tecnica chiamata <em>Return Early Pattern<\/em>, ovvero si scrive il ritorno di una funzione o di un metodo non appena una certa condizione non \u00e8 soddisfatta, invece di permettere al codice di continuare l&#8217;esecuzione, o invece di circordare un blocco di codice se una condizione \u00e9 rispettata.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">Qui di seguito, le nuove classi.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"createcontrollerphp\">CreateController.php<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;?php\n\n\/* NOTE: here namespace and use *\/\n\nclass CreateController extends Controller\n{\n    \/**\n     * @param ItemCreateRequest $request\n     * @return JsonResponse\n     *\/\n    public function __invoke(ItemCreateRequest $request): JsonResponse\n    {\n        $validateData = $request-&gt;validated();\n\n        if ($validateData&#91;'item'] === ''\n            || $validateData&#91;'item'] === Constants::LINK) {\n\n            return response()-&gt;json(&#91;\n                'item' =&gt; '',\n                'session_id' =&gt; '',\n                'slug' =&gt; '',\n                'error' =&gt; 'No item selected!',\n            ]);\n        }\n\n        $message = Message::where('slug', 'like', '%' . $validateData&#91;'slug'] . '%')\n            -&gt;first();\n\n        if (!$message) {\n            return response()-&gt;json(&#91;\n                'item' =&gt; '',\n                'session_id' =&gt; '',\n                'slug' =&gt; '',\n                'error' =&gt; 'No message found!',\n            ]);\n        }\n\n        if ($sessionId) {\n            $this-&gt;deleteItemForUserIfExists($validateData&#91;'session_id'] ?? null, $message-&gt;id);\n        }\n        \n        $item = $this-&gt;storeNewItem($message-&gt;id, $validateData);\n        \n        return response()-&gt;json(&#91;\n            'item' =&gt; $item-&gt;item,\n            'session_id' =&gt; $item-&gt;session_id,\n            'slug' =&gt; $validateData&#91;'slug'],\n        ]);\n    }\n\n    \/**\n     * @param string $sessionId\n     * @param int $messageId\n     *\n     * @return void\n     *\/\n    private function deleteItemForUserIfExists(string $sessionId, int $messageId): void\n    {\n        \n        $item = Item::where('session_id', $sessionId)\n            -&gt;where('message_id', $messageId)\n            -&gt;first();\n\n        if ($item) {\n            $item-&gt;delete();\n        }\n    }\n\n    \/**\n     * @param int $message\n     * @param array $validateData\n     *\n     * @return Item\n     *\/\n    private function storeNewItem(int $messageId, array $validateData): Item\n    {\n        $item = new Item();\n        $item-&gt;message_id = $messageId;\n        $item-&gt;user_id = (Auth::check())\n            ? Auth::user()-&gt;id\n            : Constants::NOT_LOGGED_USER_ID;\n        $item-&gt;name = $validateData&#91;'name'];\n        $item-&gt;session_id = (isset($validateData&#91;'session_id']))\n            ? $validateData&#91;'session_id']\n            : \\Session::getId();\n        $item-&gt;save();\n\n        return $item;\n    }\n}\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"getlistcontrollerphp\">GetListController.php<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;?php\n\n\/* NOTE: here namespace and use *\/\n\nclass GetListController extends Controller\n{\n    \/**\n     * @param GetItmesListRequest $request $request\n     * @return JsonResponse\n     *\/\n    public function __invoke(GetItmesListRequest $request): JsonResponse\n    {\n        $validateData = $request-&gt;validated();\n\n        $messages = $this-&gt;getMessagesBySlugs($validateData&#91;'slugs']);\n\n        $ids = &#91;];\n        foreach ($messages as $message) {\n            $ids&#91;] = $message-&gt;id;\n        }\n\n        \/\/ get items by messages ids\n        $items = Item::select('item', 'message_id', \\DB::raw('count(item) as item_count'))\n            -&gt;whereIn('message_id', $ids)\n            -&gt;groupBy('item', 'message_id')\n            -&gt;orderBy('message_id', 'desc')\n            -&gt;orderBy('item', 'desc')\n            -&gt;get();\n\n        $results = $this-&gt;prepareResults($items, $messages);\n\n        return response()-&gt;json(&#91;\n            'items' =&gt; $results,\n        ]);\n    }\n\n    \/**\n     * @param string $slugs\n     * @return Builder&#91;]|Collection\n     *\/\n    private function getMessagesBySlugs(string $slugs): array|Collection\n    {\n        $arrSlugs = json_decode($slugs, true);\n\n        $query = Message::query();\n        foreach ($arrSlugs as $slug) {\n            $query-&gt;orWhere('slug', 'like', '%-' . $slug);\n        }\n\n        return $query-&gt;get(&#91;'id', 'slug']);\n    }\n\n    \/**\n     * @param array|Collection $items\n     * @param array|Collection $messages\n     * \n     * @return array\n     *\/\n    private function prepareResults(array|Collection $items, array|Collection $messages): array\n    {\n        $results = &#91;];\n        foreach ($items as $item) {\n            foreach ($messages as $message) {\n                if ($item-&gt;message_id == $message-&gt;id) {\n                    $results&#91;] = &#91;\n                        'slug' =&gt; $this-&gt;getPublicSlug($message-&gt;slug),\n                        'item' =&gt; $item-&gt;item,\n                        'count' =&gt; $item-&gt;item_count,\n                    ];\n                }\n            }\n        }\n\n        return $results;\n    }\n}\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Con ulteriori ottimizzazioni, come l&#8217;introduzione di una classe di servizio da iniettare nel costruttore della classe, e una gestione pi\u00f9 strutturata delle eccezioni, si potrebbe rendere il codice ancora pi\u00f9 robusto e riutilizzabile.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"approfondimento-su-churn-php\">Approfondimento su Churn PHP<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Churn PHP \u00e8 uno strumento potente, ma spesso viene utilizzato con configurazioni di base che non sfruttano appieno il suo potenziale. Personalizzare il file <em>churn.yml<\/em> consente di adattare l\u2019analisi alle specifiche esigenze di un progetto. Ad esempio, si possono escludere file o directory non rilevanti come <em>vendor\/<\/em> o <em>storage\/<\/em>, oppure impostare soglie personalizzate per complessit\u00e0 e churn, evidenziando solo i file realmente critici. Di seguito un piccolo esempio di file di configurazione <em>churn.yml<\/em>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># This list is used only if there is no argument when running churn.\n# Default: &lt;empty&gt;\ndirectoriesToScan:\n - src\n - tests\/\n\n# Files to ignore when processing. The full path to the file relative to the root of your project is required.\n# Also supports regular expressions.\n# Default: All PHP files in the path provided to churn-php are processed.\nfilesToIgnore:\n  - vendor\/*\n  - storage\/*\n\n# The command returns an 1 exit code if the highest score is greater than the threshold.\n# Disabled if null.\n# Default: null\nmaxScoreThreshold: 0.9\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Inoltre, Churn PHP supporta diversi formati di output, come JSON, ideali per integrazioni avanzate con dashboard o pipeline CI\/CD. Configurare il tool in modo da eseguire analisi incrementali direttamente su GitHub Actions o GitLab CI, ad esempio, permette di identificare i file problematici in tempo reale, prima che il codice venga integrato. Una configurazione curata trasforma Churn PHP in un alleato imprescindibile per mantenere la qualit\u00e0 del codice alta senza rallentare lo sviluppo.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Per quanto riguarda l&#8217;installazione, la compatibilit\u00e1 e ulteriori configurazioni, fare riferimento al <a href=\"https:\/\/github.com\/bmitch\/churn-php\" target=\"_blank\" rel=\"noreferrer noopener nofollow\">repository Github Churn PHP<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"rector-e-churn-php-due-strumenti-complementari-per-il-refactoring\">Rector e Churn PHP: due strumenti complementari per il refactoring<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Un&#8217;ultima nota riguardo ad un altro potente strumento utilizzato per il refactoring: <strong>Rector<\/strong>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Rector \u00e8 uno strumento di <em>automatic refactoring<\/em> per PHP che permette di trasformare il codice sorgente in maniera programmata e automatizzata, applicando regole predefinite o personalizzate. A differenza di Churn PHP, che si concentra sull&#8217;analisi del codice per individuare le classi con un alto tasso di modifiche (churn) e complessit\u00e0, Rector interviene direttamente sul codice, eseguendo il refactoring in modo rapido e sicuro.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">L\u2019uso combinato di questi strumenti \u00e8 estremamente efficace: Churn PHP aiuta a identificare i file che necessitano di interventi prioritari grazie a metriche concrete, mentre Rector pu\u00f2 automatizzare molte delle modifiche necessarie, come la rimozione di codice ridondante, l\u2019adeguamento a standard moderni o la semplificazione di pattern complessi, basandosi su regole impostate dagli sviluppatori. Questa sinergia consente di ottimizzare il refactoring, bilanciando analisi intelligente e automazione, per ottenere un codice pi\u00f9 pulito e manutenibile senza rallentare il flusso di sviluppo.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Per l&#8217;installazione e la documentazione, fare riferimento al <a href=\"https:\/\/github.com\/rectorphp\/rector\" target=\"_blank\" rel=\"noreferrer noopener nofollow\">repository Github di Rector<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"conclusioni\">Conclusioni<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Il refactoring non \u00e8 solo una pratica tecnica, ma una strategia che pu\u00f2 trasformare il modo in cui un team affronta lo sviluppo software. Strumenti come PHPStan, e Churn PHP aiutano a identificare aree critiche, e strumenti come <a href=\"https:\/\/www.giuseppemaccario.com\/it\/qualita-del-codice-con-laravel-pint\/\">Pint<\/a> aiutano a mantenere uno standard di scrittura omogeneo (PSR12 per esempio), ma il successo passa attraverso strategie a lungo termine: integrare il refactoring nelle attivit\u00e0 quotidiane e promuovere una cultura che lo consideri parte essenziale del processo di sviluppo. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\u00c8 importante bilanciare il desiderio di migliorare il codice con i rischi, come l\u2019introduzione di bug, affrontandolo con approcci agili e incrementali. Infine, metriche come il churn non solo guidano il refactoring, ma rivelano anche la salute del codice e del team, offrendo spunti per migliorare collaborazione e qualit\u00e0 generale.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">E tu? Quali strategie utilizzi per affrontare il refactoring? Lascio aperti i commenti per chi avesse voglia di sviluppare una conversazione riguardo il refactoring e le tecniche usate.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Churn PHP \u00e8 uno strumento che aiuta a individuare i file di codice pi\u00f9 problematici in un progetto, combinando complessit\u00e0 e frequenza di modifiche (churn). \u00c8 proprio la combinazione tra complessit\u00e0 e modifiche frequenti che guider\u00e0 il nostro refactoring.<\/p>\n","protected":false},"author":1,"featured_media":2550,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_import_markdown_pro_load_document_selector":0,"_import_markdown_pro_submit_text_textarea":"","ngg_post_thumbnail":0,"footnotes":""},"categories":[38,82],"tags":[71,41,83],"class_list":["post-2547","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-php","category-refactoring","tag-laravel","tag-php","tag-refactoring"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.3 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Churn PHP: come identificare i mostri nei tuoi progetti PHP - Giuseppe Maccario<\/title>\n<meta name=\"description\" content=\"Churn PHP \u00e8 uno strumento che aiuta a individuare il codice pi\u00f9 problematico in un progetto, combinando complessit\u00e0 e frequenza di modifiche.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.giuseppemaccario.com\/it\/churn-php-come-identificare-i-mostri-nei-tuoi-progetti-php\/\" \/>\n<meta property=\"og:locale\" content=\"it_IT\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Churn PHP: come identificare i mostri nei tuoi progetti PHP - Giuseppe Maccario\" \/>\n<meta property=\"og:description\" content=\"Churn PHP \u00e8 uno strumento che aiuta a individuare il codice pi\u00f9 problematico in un progetto, combinando complessit\u00e0 e frequenza di modifiche.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.giuseppemaccario.com\/it\/churn-php-come-identificare-i-mostri-nei-tuoi-progetti-php\/\" \/>\n<meta property=\"og:site_name\" content=\"Giuseppe Maccario\" \/>\n<meta property=\"article:published_time\" content=\"2024-12-17T16:02:49+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-01-10T10:04:19+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.giuseppemaccario.com\/it\/wp-content\/uploads\/2024\/12\/Churn-PHP-come-identificare-i-mostri-nel-tuo-progetto-pexels-gomez-daniel-290429793-14770928-scaled.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"2560\" \/>\n\t<meta property=\"og:image:height\" content=\"1707\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"giuseppemaccario\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Scritto da\" \/>\n\t<meta name=\"twitter:data1\" content=\"giuseppemaccario\" \/>\n\t<meta name=\"twitter:label2\" content=\"Tempo di lettura stimato\" \/>\n\t<meta name=\"twitter:data2\" content=\"12 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.giuseppemaccario.com\\\/it\\\/churn-php-come-identificare-i-mostri-nei-tuoi-progetti-php\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.giuseppemaccario.com\\\/it\\\/churn-php-come-identificare-i-mostri-nei-tuoi-progetti-php\\\/\"},\"author\":{\"name\":\"giuseppemaccario\",\"@id\":\"https:\\\/\\\/www.giuseppemaccario.com\\\/it\\\/#\\\/schema\\\/person\\\/cb06a58fab509a897056972173e2e5dc\"},\"headline\":\"Churn PHP: come identificare i mostri nei tuoi progetti PHP\",\"datePublished\":\"2024-12-17T16:02:49+00:00\",\"dateModified\":\"2025-01-10T10:04:19+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.giuseppemaccario.com\\\/it\\\/churn-php-come-identificare-i-mostri-nei-tuoi-progetti-php\\\/\"},\"wordCount\":2002,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/www.giuseppemaccario.com\\\/it\\\/#\\\/schema\\\/person\\\/cb06a58fab509a897056972173e2e5dc\"},\"image\":{\"@id\":\"https:\\\/\\\/www.giuseppemaccario.com\\\/it\\\/churn-php-come-identificare-i-mostri-nei-tuoi-progetti-php\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.giuseppemaccario.com\\\/it\\\/wp-content\\\/uploads\\\/2024\\\/12\\\/Churn-PHP-come-identificare-i-mostri-nel-tuo-progetto-pexels-gomez-daniel-290429793-14770928-scaled.jpg\",\"keywords\":[\"laravel\",\"php\",\"refactoring\"],\"articleSection\":[\"PHP\",\"refactoring\"],\"inLanguage\":\"it-IT\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.giuseppemaccario.com\\\/it\\\/churn-php-come-identificare-i-mostri-nei-tuoi-progetti-php\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.giuseppemaccario.com\\\/it\\\/churn-php-come-identificare-i-mostri-nei-tuoi-progetti-php\\\/\",\"url\":\"https:\\\/\\\/www.giuseppemaccario.com\\\/it\\\/churn-php-come-identificare-i-mostri-nei-tuoi-progetti-php\\\/\",\"name\":\"Churn PHP: come identificare i mostri nei tuoi progetti PHP - Giuseppe Maccario\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.giuseppemaccario.com\\\/it\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.giuseppemaccario.com\\\/it\\\/churn-php-come-identificare-i-mostri-nei-tuoi-progetti-php\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.giuseppemaccario.com\\\/it\\\/churn-php-come-identificare-i-mostri-nei-tuoi-progetti-php\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.giuseppemaccario.com\\\/it\\\/wp-content\\\/uploads\\\/2024\\\/12\\\/Churn-PHP-come-identificare-i-mostri-nel-tuo-progetto-pexels-gomez-daniel-290429793-14770928-scaled.jpg\",\"datePublished\":\"2024-12-17T16:02:49+00:00\",\"dateModified\":\"2025-01-10T10:04:19+00:00\",\"description\":\"Churn PHP \u00e8 uno strumento che aiuta a individuare il codice pi\u00f9 problematico in un progetto, combinando complessit\u00e0 e frequenza di modifiche.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.giuseppemaccario.com\\\/it\\\/churn-php-come-identificare-i-mostri-nei-tuoi-progetti-php\\\/#breadcrumb\"},\"inLanguage\":\"it-IT\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.giuseppemaccario.com\\\/it\\\/churn-php-come-identificare-i-mostri-nei-tuoi-progetti-php\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"it-IT\",\"@id\":\"https:\\\/\\\/www.giuseppemaccario.com\\\/it\\\/churn-php-come-identificare-i-mostri-nei-tuoi-progetti-php\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.giuseppemaccario.com\\\/it\\\/wp-content\\\/uploads\\\/2024\\\/12\\\/Churn-PHP-come-identificare-i-mostri-nel-tuo-progetto-pexels-gomez-daniel-290429793-14770928-scaled.jpg\",\"contentUrl\":\"https:\\\/\\\/www.giuseppemaccario.com\\\/it\\\/wp-content\\\/uploads\\\/2024\\\/12\\\/Churn-PHP-come-identificare-i-mostri-nel-tuo-progetto-pexels-gomez-daniel-290429793-14770928-scaled.jpg\",\"width\":2560,\"height\":1707,\"caption\":\"Churn PHP: come identificare i mostri nel tuo progetto\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.giuseppemaccario.com\\\/it\\\/churn-php-come-identificare-i-mostri-nei-tuoi-progetti-php\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.giuseppemaccario.com\\\/it\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Churn PHP: come identificare i mostri nei tuoi progetti PHP\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.giuseppemaccario.com\\\/it\\\/#website\",\"url\":\"https:\\\/\\\/www.giuseppemaccario.com\\\/it\\\/\",\"name\":\"Giuseppe Maccario\",\"description\":\"Sviluppatore Software in Amsterdam (NL)\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.giuseppemaccario.com\\\/it\\\/#\\\/schema\\\/person\\\/cb06a58fab509a897056972173e2e5dc\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.giuseppemaccario.com\\\/it\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"it-IT\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/www.giuseppemaccario.com\\\/it\\\/#\\\/schema\\\/person\\\/cb06a58fab509a897056972173e2e5dc\",\"name\":\"giuseppemaccario\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"it-IT\",\"@id\":\"https:\\\/\\\/www.giuseppemaccario.com\\\/it\\\/wp-content\\\/uploads\\\/2018\\\/08\\\/giuseppe-maccario-experienced-software-developer-logo.png\",\"url\":\"https:\\\/\\\/www.giuseppemaccario.com\\\/it\\\/wp-content\\\/uploads\\\/2018\\\/08\\\/giuseppe-maccario-experienced-software-developer-logo.png\",\"contentUrl\":\"https:\\\/\\\/www.giuseppemaccario.com\\\/it\\\/wp-content\\\/uploads\\\/2018\\\/08\\\/giuseppe-maccario-experienced-software-developer-logo.png\",\"width\":50,\"height\":50,\"caption\":\"giuseppemaccario\"},\"logo\":{\"@id\":\"https:\\\/\\\/www.giuseppemaccario.com\\\/it\\\/wp-content\\\/uploads\\\/2018\\\/08\\\/giuseppe-maccario-experienced-software-developer-logo.png\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Churn PHP: come identificare i mostri nei tuoi progetti PHP - Giuseppe Maccario","description":"Churn PHP \u00e8 uno strumento che aiuta a individuare il codice pi\u00f9 problematico in un progetto, combinando complessit\u00e0 e frequenza di modifiche.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.giuseppemaccario.com\/it\/churn-php-come-identificare-i-mostri-nei-tuoi-progetti-php\/","og_locale":"it_IT","og_type":"article","og_title":"Churn PHP: come identificare i mostri nei tuoi progetti PHP - Giuseppe Maccario","og_description":"Churn PHP \u00e8 uno strumento che aiuta a individuare il codice pi\u00f9 problematico in un progetto, combinando complessit\u00e0 e frequenza di modifiche.","og_url":"https:\/\/www.giuseppemaccario.com\/it\/churn-php-come-identificare-i-mostri-nei-tuoi-progetti-php\/","og_site_name":"Giuseppe Maccario","article_published_time":"2024-12-17T16:02:49+00:00","article_modified_time":"2025-01-10T10:04:19+00:00","og_image":[{"width":2560,"height":1707,"url":"https:\/\/www.giuseppemaccario.com\/it\/wp-content\/uploads\/2024\/12\/Churn-PHP-come-identificare-i-mostri-nel-tuo-progetto-pexels-gomez-daniel-290429793-14770928-scaled.jpg","type":"image\/jpeg"}],"author":"giuseppemaccario","twitter_card":"summary_large_image","twitter_misc":{"Scritto da":"giuseppemaccario","Tempo di lettura stimato":"12 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.giuseppemaccario.com\/it\/churn-php-come-identificare-i-mostri-nei-tuoi-progetti-php\/#article","isPartOf":{"@id":"https:\/\/www.giuseppemaccario.com\/it\/churn-php-come-identificare-i-mostri-nei-tuoi-progetti-php\/"},"author":{"name":"giuseppemaccario","@id":"https:\/\/www.giuseppemaccario.com\/it\/#\/schema\/person\/cb06a58fab509a897056972173e2e5dc"},"headline":"Churn PHP: come identificare i mostri nei tuoi progetti PHP","datePublished":"2024-12-17T16:02:49+00:00","dateModified":"2025-01-10T10:04:19+00:00","mainEntityOfPage":{"@id":"https:\/\/www.giuseppemaccario.com\/it\/churn-php-come-identificare-i-mostri-nei-tuoi-progetti-php\/"},"wordCount":2002,"commentCount":0,"publisher":{"@id":"https:\/\/www.giuseppemaccario.com\/it\/#\/schema\/person\/cb06a58fab509a897056972173e2e5dc"},"image":{"@id":"https:\/\/www.giuseppemaccario.com\/it\/churn-php-come-identificare-i-mostri-nei-tuoi-progetti-php\/#primaryimage"},"thumbnailUrl":"https:\/\/www.giuseppemaccario.com\/it\/wp-content\/uploads\/2024\/12\/Churn-PHP-come-identificare-i-mostri-nel-tuo-progetto-pexels-gomez-daniel-290429793-14770928-scaled.jpg","keywords":["laravel","php","refactoring"],"articleSection":["PHP","refactoring"],"inLanguage":"it-IT","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.giuseppemaccario.com\/it\/churn-php-come-identificare-i-mostri-nei-tuoi-progetti-php\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.giuseppemaccario.com\/it\/churn-php-come-identificare-i-mostri-nei-tuoi-progetti-php\/","url":"https:\/\/www.giuseppemaccario.com\/it\/churn-php-come-identificare-i-mostri-nei-tuoi-progetti-php\/","name":"Churn PHP: come identificare i mostri nei tuoi progetti PHP - Giuseppe Maccario","isPartOf":{"@id":"https:\/\/www.giuseppemaccario.com\/it\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.giuseppemaccario.com\/it\/churn-php-come-identificare-i-mostri-nei-tuoi-progetti-php\/#primaryimage"},"image":{"@id":"https:\/\/www.giuseppemaccario.com\/it\/churn-php-come-identificare-i-mostri-nei-tuoi-progetti-php\/#primaryimage"},"thumbnailUrl":"https:\/\/www.giuseppemaccario.com\/it\/wp-content\/uploads\/2024\/12\/Churn-PHP-come-identificare-i-mostri-nel-tuo-progetto-pexels-gomez-daniel-290429793-14770928-scaled.jpg","datePublished":"2024-12-17T16:02:49+00:00","dateModified":"2025-01-10T10:04:19+00:00","description":"Churn PHP \u00e8 uno strumento che aiuta a individuare il codice pi\u00f9 problematico in un progetto, combinando complessit\u00e0 e frequenza di modifiche.","breadcrumb":{"@id":"https:\/\/www.giuseppemaccario.com\/it\/churn-php-come-identificare-i-mostri-nei-tuoi-progetti-php\/#breadcrumb"},"inLanguage":"it-IT","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.giuseppemaccario.com\/it\/churn-php-come-identificare-i-mostri-nei-tuoi-progetti-php\/"]}]},{"@type":"ImageObject","inLanguage":"it-IT","@id":"https:\/\/www.giuseppemaccario.com\/it\/churn-php-come-identificare-i-mostri-nei-tuoi-progetti-php\/#primaryimage","url":"https:\/\/www.giuseppemaccario.com\/it\/wp-content\/uploads\/2024\/12\/Churn-PHP-come-identificare-i-mostri-nel-tuo-progetto-pexels-gomez-daniel-290429793-14770928-scaled.jpg","contentUrl":"https:\/\/www.giuseppemaccario.com\/it\/wp-content\/uploads\/2024\/12\/Churn-PHP-come-identificare-i-mostri-nel-tuo-progetto-pexels-gomez-daniel-290429793-14770928-scaled.jpg","width":2560,"height":1707,"caption":"Churn PHP: come identificare i mostri nel tuo progetto"},{"@type":"BreadcrumbList","@id":"https:\/\/www.giuseppemaccario.com\/it\/churn-php-come-identificare-i-mostri-nei-tuoi-progetti-php\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.giuseppemaccario.com\/it\/"},{"@type":"ListItem","position":2,"name":"Churn PHP: come identificare i mostri nei tuoi progetti PHP"}]},{"@type":"WebSite","@id":"https:\/\/www.giuseppemaccario.com\/it\/#website","url":"https:\/\/www.giuseppemaccario.com\/it\/","name":"Giuseppe Maccario","description":"Sviluppatore Software in Amsterdam (NL)","publisher":{"@id":"https:\/\/www.giuseppemaccario.com\/it\/#\/schema\/person\/cb06a58fab509a897056972173e2e5dc"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.giuseppemaccario.com\/it\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"it-IT"},{"@type":["Person","Organization"],"@id":"https:\/\/www.giuseppemaccario.com\/it\/#\/schema\/person\/cb06a58fab509a897056972173e2e5dc","name":"giuseppemaccario","image":{"@type":"ImageObject","inLanguage":"it-IT","@id":"https:\/\/www.giuseppemaccario.com\/it\/wp-content\/uploads\/2018\/08\/giuseppe-maccario-experienced-software-developer-logo.png","url":"https:\/\/www.giuseppemaccario.com\/it\/wp-content\/uploads\/2018\/08\/giuseppe-maccario-experienced-software-developer-logo.png","contentUrl":"https:\/\/www.giuseppemaccario.com\/it\/wp-content\/uploads\/2018\/08\/giuseppe-maccario-experienced-software-developer-logo.png","width":50,"height":50,"caption":"giuseppemaccario"},"logo":{"@id":"https:\/\/www.giuseppemaccario.com\/it\/wp-content\/uploads\/2018\/08\/giuseppe-maccario-experienced-software-developer-logo.png"}}]}},"_links":{"self":[{"href":"https:\/\/www.giuseppemaccario.com\/it\/wp-json\/wp\/v2\/posts\/2547","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.giuseppemaccario.com\/it\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.giuseppemaccario.com\/it\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.giuseppemaccario.com\/it\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.giuseppemaccario.com\/it\/wp-json\/wp\/v2\/comments?post=2547"}],"version-history":[{"count":17,"href":"https:\/\/www.giuseppemaccario.com\/it\/wp-json\/wp\/v2\/posts\/2547\/revisions"}],"predecessor-version":[{"id":2592,"href":"https:\/\/www.giuseppemaccario.com\/it\/wp-json\/wp\/v2\/posts\/2547\/revisions\/2592"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.giuseppemaccario.com\/it\/wp-json\/wp\/v2\/media\/2550"}],"wp:attachment":[{"href":"https:\/\/www.giuseppemaccario.com\/it\/wp-json\/wp\/v2\/media?parent=2547"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.giuseppemaccario.com\/it\/wp-json\/wp\/v2\/categories?post=2547"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.giuseppemaccario.com\/it\/wp-json\/wp\/v2\/tags?post=2547"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}