{"id":17028055,"url":"https://github.com/mochitto/best-practices","last_synced_at":"2025-03-22T19:43:54.778Z","repository":{"id":191348602,"uuid":"674282187","full_name":"Mochitto/best-practices","owner":"Mochitto","description":"A repo storing docs on best practices","archived":false,"fork":false,"pushed_at":"2023-10-04T12:30:46.000Z","size":14,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-01-27T23:43:10.025Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Mochitto.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2023-08-03T15:00:30.000Z","updated_at":"2023-08-03T15:00:30.000Z","dependencies_parsed_at":"2023-08-29T12:42:29.781Z","dependency_job_id":"473c8f36-d620-4ec0-8100-0b6b3bea3f40","html_url":"https://github.com/Mochitto/best-practices","commit_stats":null,"previous_names":["mochitto/best-practices"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Mochitto%2Fbest-practices","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Mochitto%2Fbest-practices/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Mochitto%2Fbest-practices/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Mochitto%2Fbest-practices/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Mochitto","download_url":"https://codeload.github.com/Mochitto/best-practices/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245013963,"owners_count":20547177,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-14T07:52:07.158Z","updated_at":"2025-03-22T19:43:54.755Z","avatar_url":"https://github.com/Mochitto.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# RT Best practices\n\n## IMPORTANT\nThis document has to be updated to follow new best practices.\n\n\nQuesto documento riporta alcune best practices che possono aiutare a scrivere codice semplice da leggere e modificare in futuro.\n\n---\nIndice:\n- git, github e versioning\n    - Semantic versioning - Semver\n    - Changelogs - keepachangelog\n    - Messaggi di commit\n    - Git history e branches\n- Commenti e documentazione nel codice\n    - Nomi\n    - Commenti\n    - Quando scrivere le docstrings\n- Refactoring e tenere il codice pulito\n    - Linee guida\n    - Estrarre funzioni\n    - Funzioni pure e side-effects\n    - Funzioni pure: pipes, composition e higher-order functions\n- Architettura\n    - Funzioni e moduli\n    - Component\n    - Services\n    - Data-services\n    - Architettura tipo\n\n---\n\n## git, github e versioning\n\nUtilizzare tags, changelog files e semantic versioning puo' aiutarci nel sapere in che momento aggiungiamo quale feature, risolviamo bugs o facciamo altre modifiche ad un progetto.\n\n### Semantic versioning - Semver\n\nIl semantic versioning ha lo scopo di permettere di capire a colpo d'occhio il tipo di cambiamento che e' avvenuto fra versioni diverse (o commits) di una applicazione.\nSi basa su uno standard curato dalla community (vesione [italiana](https://semver.org/lang/it/) e [inglese](https://semver.org/).\nEsso prevede questo tipo di nomenclatura:\n\n`[Versione maggiore].[versione minore].[patch/hotfix]`\n\n\n```\nex. versione 1.2.4\n```\n\n**Versione maggiore**: cambiamenti che cambiano l'API in modo non retrocompatibile (per progetti interni, generalmente riscritture del progetto).\n**Versione minore**: quando viene aggiunta una funzionalita' (in modo retrocompatibile).\n**Patch**: correzioni di bugs.\n\nOgni volta che la versione maggiore viene incrementata, versione minore e patch tornano a 0; quando versione minore viene aggiornata, patch torna a 0.\n```\nEx.\n0.0.1 =\u003e Commit: BUG FIX - fixed button bug  =\u003e  0.0.2\n1.0.2 =\u003e Commit: Rewrite in Angular 17 =\u003e 2.0.0\n2.3.4 =\u003e Commit: Feature - added table view =\u003e 2.4.0\n```\n\nQueste versioni possono essere \"collegate\" ai commit in questo modo:\n```bash\ngit commit -m \"\u003cmessaggio di commit\u003e\" # crea commit\ngit tag v0.0.1 # crea tag (aggiunta automaticamente all'ultimo commit)\ngit push origin main --tags # push tags verso github\n```\n\nI tags si possono vedere in questo modo\n```git\ngit tag \n```\n\nI tags hanno senso se usati assieme ad un changelog =\u003e\n\n### Changelogs - keepachangelog\n\nI changelogs sono dei files che permettono di documentare in modo leggibile cio' che e' stato aggiunto, modificato, rimosso etc. in ogni versione del programma.\nSi basa su uno standard tenuto dalla community (versione [italiana](https://keepachangelog.com/it-IT/1.0.0/) e [inglese](https://keepachangelog.com/en/1.1.0/)).\n\nEsempio:\n```md\n# Changelog\n\nAll notable changes to this project will be documented in this file.\n\nThe format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),\nand this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).\n\n## [Unreleased]\n### Fixed\n\n- Improve French translation (#377).\n\n## [1.1.1] - 2023-03-05\n\n### Added\n\n- Arabic translation (#444).\n```\n\nOgni volta che si va a merge-are o rebase-are e si crea una nuova versione del progetto, bisognerebbe aggiungere le varie modifiche che sono state fatte alla versione in questo documento.\n\nCi sono vari tipi di cambiamenti:\n- **Added**: nuove features\n- **Changed**: modifiche di features presenti\n- **Deprecated**: deprecazioni nel codice\n- **Removed**: features rimosse\n- **Fixed**: bug fixes\n- **Security**: vulnerabilita' presenti/sistemate\n\nE' buon uso tenere un header con `## [Unreleased]` durante lo sviluppo della versione, in modo da poter cambiare \"unreleased\" in \"X.Y.Z\" quando la versione viene rilasciata.\n\n### Messaggi di commit\n\nAnche i commit sono un tipo di documentazione.\n\nIn genere, bisognerebbe creare un commit per ogni numbero di modifiche che possono essere raggruppate assieme sotto uno di queste categorie:\n- **Feat**: nuova feature\n- **Fix**: bug fix\n- **Chore**: rimozione di commenti, pulizia dei files, formattazione con prettier, aggiornare dependencies etc. - cio' che non riguarda fix, features e non cambia il codice della src o dei tests\n- **Docs**: aggiornamenti sui files di documentazione (ad esempio, aggiungere righe al changelog)\n- **Test**: nuovi tests o correzione di tests presenti\n(ce ne sono altri, ma questi sono i casi principali)\n\nLa struttura di base e'\n```\n\u003ctipologia di commit\u003e: \u003cdescrizione\u003e\n```\n\nEsempi:\n```\nFeat: added buttons to download pdf templates\nFix: program doesn't run out of memory anymore when exporting.\nChore: cleaned up imports\nTest: added tests for the stores data service\n```\n\n\n### Git history e branches\n\nQuando si sviluppa una nuova feature o si risolve un bug, e' buona cosa creare un nuovo branch su cui lavorare.\nEsistono anche dei branches usati spesso in ogni progetto:\n- **Main (o master)**: branch che ha il codice pronto per essere mandato in production; con codice rifinito e stabile\n- **Development (o develop)**: branch che si usa durante lo sviluppo del programma, in cui si merge-ano i branch di features e fixes\n- **feat/\u003cbranch name\u003e**: branch usato per lo sviluppo di una feature\n- **fix/\u003cbranch name\u003e**: branch usato per lo sviluppo di un/piu' bug fix\n\nIl flow tipico potrebbe essere:\n1. Devo creare una nuova feature per gestire lo scroll su una mappa -\u003e creo `feat/map-scroll`\n2. Ho finito di sviluppare la feature e puo' unirsi alle altre features aggiunte dalle altre persone -\u003e aggiorno CHANGELOG, merge-o su `development` e taggo il commit con la nuova versione (minor)\n3. Rimuovo il branch `feat/map-scroll`\n4. Mi richiedono di cambiare parte della feature -\u003e creo `fix/map-scroll`\n5. Ho finito di sviluppare il fix e puo' unirsi alle altre features aggiunte dalle altre persone -\u003e aggiorno CHANGELOG, merge-o su `development` e taggo il commit con la nuova versione (patch)\n6. Abbiamo raggiunto abbstanza features da rilasciare una versione stabile -\u003e apro una PR per merge-are su `main`, sistemo cio' che potrebbe essere da sistemare e taggo il commit (major o minor)\n\n!! Usare **rebase, amend, force-push etc.** solo quando si lavora su branches che si possiedono e che non sono condivisi con altre persone.\nRebase e' una azione distruttiva che cambia l'ordine dei commits e a cui non si puo' rimediare in caso di errori.\nRebase-are su branch condivisi porta anche il rischio di rimuovere il lavoro fatto da altre persone.\n\nIn caso di errori, si puo' create un nuovo commit con ex. `Fix: fixing problems regarding previous commits`.\n\n---\n\n## Commenti e documentazione nel codice\n\nUn tipo di documentazione che e' presente nel codice sono i commenti, le type signatures e i nomi che si danno alle variabili.\n\n### Nomi\nSpesso un buon nome toglie il bisogno di usare commenti per dare informazioni aggiuntive.\n\n**Nomi da non usare**:\n- lettere singole\n- soprannomi\n- abbreviazioni\n- acronimi\n\n```js\n// Avoid Single Letter Names\nlet n = 'use name instead';\n\n// Avoid Acronyms\nlet cra = 'no clue what this is';\n\n// Avoid Abbreviations\nlet cat = 'cat or category??';\n\n// Avoid Meaningless Names\nlet foo = 'what is foo??';\n```\n\n**Linee guida utili**:\nIn genere, usare verbi per funzioni e nomi per variabili puo' aiutare a dare nomi migliori.\nE' anche utile essere specifici quando un nome puo' essere generico (data, values, user...).\n```js\nfunction getValues() // invece che values()\n\nconst ApiStoresData // invece che data\n\nconst adminUser // invece che user\n```\n\n\n### Commenti\n\nSi possono dividere in:\n- **Docstrings**: commenti che descrivono la funzione di una funzione, classe o variabile, qualora il nome non sia abbastanza per intuirlo.\n- **TODO**: commenti che descrivono cio' che andra' fatto in futuro, ma che non e' collegato al codice presente (simile ad una task da risolvere)\n- **FIXME**: commenti che descrivono cio' che va fatto il prima possibile (codice scritto male che ha bisogno di refactor, valori hard-coded che devono essere scritti in modo dinamico, parti di codice che vanno estratte in funzioni specifiche, cambiamenti che non sono attuabili nella fase del progetto attuale ma in futuro lo saranno etc.)\n\nStrutture dei commenti:\n```js\n/** QUESTA E' UNA DOCSTRING IN JAVASCRIPT, inizia con /** e si mette sopra alla variabile, funzione o classe che va a definire.\n*   \u003cmessaggio, anche a piu' righe\u003e\n*/\nconst qualcosa = qualcosa\n\n// TODO: Questo e' un todo, inizia con \"TODO:\"\n// FIXME: Questo e' un fixme, inzia con \"FIXME:\"\n\n```\n\nEsempi:\n```js\n/**\n* A test function written to test docstrings.\n* FIXME: remove me later, just for testing\n*/\nfunction greetWorld() {\n    console.log(\"Hello world\")\n}\n\n// TODO: Add a new function that takes a name as a parameter and prints \"hello ${name}\"\n```\n\nAvere la documentazione nel codice permette che essa sia sempre aggiornata.  \nQuando si modifica una funzione, una classe o la funzione di una variabile, e' importante controllare se anche la docstring ha bisogno di essere aggiornata.  \n\nQuando invece si crea del codice particolarmente complesso, puo' essere utile commentare i vari passaggi e il **perche'** il codice e' scritto in questo modo.\n\nEsempio:\n```js\n// Javascript has scoping problems in MyClass since higher order functions are used in some of its methods.\n// Using this reference, we can avoid using \"this\" and avoid the scoping problem - https://stackoverflow.com/questions/40298991/understanding-javascripts-this-different-types-of-function-calls-and-how-to-c\nlet myClassThis\n\nclass Myclass {\n    constructor() {\n        myClassThis = this\n        this.name = \"john\"\n        this.speak(this.hello())\n        this.speak(this.bye())\n    }\n\n    speak(message) {\n        console.log(message())\n    }\n\n    hello() {\n        return `Hello, ${myClassThis.name}`\n    }\n\n    bye() {\n        return `Hello, ${myClassThis.name}`\n    }\n}\n```\n\n!! Nei commenti e' importante scrivere il **perche'** si e' fatta una scelta, non il **come** qualcosa funzioni: se si sente il bisogno di scrivedere come qualcosa sta funzionando, allora e' probabilmente troppo complesso.\n\nIl codice dovrebbe essere leggibile e comprensibile, almeno per quanto riguarda la logica. I commenti possono dare un contesto, in cui il codice viene applicato.\n\n### Quando scrivere le docstrings\nPrima di fare un commit, e' utile aggiungere docstrings a parti del codice che sono \"complete\".\n\nSe sto creando un component, aggiungero' una docstring che descrive per cosa viene usato il componente solo una volta completato.\nSe invece sto scrivendo una piccola funzione, e' utile aggiungere subito una docstring, magari ancora prima di scrivere la funzione (descrivere cio' che stai per fare puo' aiutarti a capire meglio come farlo: [rubber duck debugging](https://en.wikipedia.org/wiki/Rubber_duck_debugging))\n\n---\n\n## Refactoring e tenere il codice pulito\n\nDurante il tempo, si crea del debito tecnico dovuto alla mancanza di revisioni del codice.\nE' buon uso avere alcuni accorgimenti sia durante la scrittura che durante la revisione del codice.\n\n### Linee guida\nQueste linee guida possono aiutare a riconoscere quando bisogna revisionare il codice (refactor). Non sono sempre applicabili, ma generalmente e' buona norma seguirle.\n\n- **Le funzioni non dovrebbero essere piu' lunghe di 50 linee**; se lo sono e' probabile che serva *estrarre funzioni* (di piu' su questo in seguito)\n- **Si fa fatica a dare nomi alle variabili e funzioni**; probabilmente la architettura/logica che si sta applicando e' troppo complessa\n- **Si sente il bisogno di aggiungere commenti che spieghino cio' che succede nel codice**; probabilmente la logica e' troppo complessa e va semplificata\n- **Il file e' piu' lungo di 300 righe**; probabilmente puo' essere diviso in diversi file con moduli specifici\n- **Si fatica a navigare il file** probabilmente il file e' troppo lungo o la logica non lineare, ad esempio nel caso di una gestione dello stato fatta male\n- **Una funzione richiede piu' di tre parametri**: probabilmente puoi ridurre il numero di parametri creando piu' funzioni invece che una sola\n- **Stai provando a vedere cosa fa una funzione mettendoci cose a caso** (durante lo sviluppo, non durante reverse-engineering); probabilmente devi scrivere dei test che descrivono cio' che ti aspetti e cio' che non vuoi che succeda\n- **Stai usando type signatures generiche o literals complessi**; probabilmente devi creare delle interfacce specifiche o semplificare la logica di cio' che stai scrivendo per usare tipi piu' semplici\n- **Hai piu' di tre/quattro livelli di indentazione**; probabilmente devi *estrarre funzioni*.\n- **Hai lo stesso codice (o molto simile) in piu' di tre punti**; probabilmente e' il momento di astrarre la logica comune e creare una funzione che gestisca i vari casi (creare astrazioni quando la duplicazione e' bassa puo' invece aumentare la complessita' della applicazione)\n\n### Estrarre funzioni\nSpesso le funzioni possono essere divise in sotto-funzioni piu' specifiche. Cio' permette di ridurre la complessita' generale delle funzioni, in quanto fanno una sola cosa (e quindi sono molto leggibili e prevedibili).\n\nEsempio \n```js\n\n// PRIMA DEL REFACTOR\n\n// operation: \"3 + 4\"\nfunction calculate(operation) {\n    let operator\n    if (\"+\" in operation){ operator = \"+\"}\n    else if (\"-\" in operation){ operator = \"-\"}\n    else if (\"*\" in operation){ operator = \"*\"}\n    else if (\"/\" in operation){ operator = \"/\"}\n\n    const operationsMap = {\n    \"+\": (num1, num2) =\u003e num1 + num2,\n    \"-\": (num1, num2) =\u003e num1 - num2,\n    \"*\": (num1, num2) =\u003e num1 * num2,\n    \"/\": (num1, num2) =\u003e num1 / num2,\n    }\n\n    const firstNumber = Number.parseInt(operation.split(+)[0].trim())\n    const secondNumber = Number.parseInt(operation.split(+)[1].trim())\n\n    return operationsMap[operator](firstNumber, secondNumber)\n}\n\n// DOPO IL REFACTOR\nfunction calculate(operation) {\n    const operator = extractOperator(operation)\n    const operationFunction = getOperationFunction(operator)\n    const [firstNumber, secondNumber] = extractNumbers(operation)\n    \n    return operationFunction(firstNumber, secondNumber)\n}\n```\n\nGli steps da fare durante l'estrazione di funzioni sono:\n1. Prendi il codice e lo muovi in una funzione\n```js\nfunction calculate(operation) {\n    const operator = extractOperator(operation)\n\n    const operationsMap = {\n    \"+\": (num1, num2) =\u003e num1 + num2,\n    \"-\": (num1, num2) =\u003e num1 - num2,\n    \"*\": (num1, num2) =\u003e num1 * num2,\n    \"/\": (num1, num2) =\u003e num1 / num2,\n    }\n\n    const firstNumber = Number.parseInt(operation.split(+)[0].trim())\n    const secondNumber = Number.parseInt(operation.split(+)[1].trim())\n\n    return operationsMap[operator](firstNumber, secondNumber)\n}\n\nfunction extractOperator(operation) {\n    let operator\n    if (\"+\" in operation){ operator = \"+\"}\n    else if (\"-\" in operation){ operator = \"-\"}\n    else if (\"*\" in operation){ operator = \"*\"}\n    else if (\"/\" in operation){ operator = \"/\"}\n\n    return operator\n}\n\n\n```\n2. Migliori il codice: aggiungi docstrings, lo ripulisci e se necessario rimuovi duplicazione del codice\n```js\n/**\n* Get the algebraic operators from a string representing an operation.\n*/\nfunction extractOperator(operation: string) {\n    return operation.match(/[-+*\\/]/)[0]\n}\n```\n3. Muovi le nuove funzioni in altri moduli, creandoli se necessario\n```js\n// component.js\nfunction calculate(operation) {\n    const operator = extractOperator(operation)\n    const operationFunction = getOperationFunction(operator)\n    const [firstNumber, secondNumber] = extractNumbers(operation)\n    \n    return operationFunction(firstNumber, secondNumber)\n}\n\n// handle-operations.js\nfunction getOperationFunction() {...}\n\n// data-extractors.js\nfunction extractOperator() {...}\nfunction extractNumbers() {...}\n```\n\n### Funzioni pure e side-effects\nLe funzioni possono essere di due tipi: pure e con side-effects.\n\nUna **funzione pura** ha un input e un output, non cambia variabili al di' fuori di quelle che possiede e da' sempre lo stesso risultato con lo stessso input.\n```js\nfunction giveMe5of(word) {\n    return Array.from({length: 5}, _ =\u003e word)\n}\n```\nUna **funzione con side-effects** e' una funzione che ha effetti al di' fuori del proprio scope:\n```js\nfunction handleClick(event) {\n    this.selectedItem = event.target // primo side effect: cambiare uno state della classe\n    this.clicks += 1\n    this._url.set(\"logging\")\n    console.log(event) // secondo side effect: scrivere sulla console\n    // non ritorna nulla, void\n}\n```\n\nLe funzioni con side-effects sono difficili da debuggare: tracciare il flusso della applicazione, come nel caso dell'esempio, risulta complesso (ad esempio, seguire come cambia \"this.clicks\", che magari e' anche modificato da altri metodi della classe).\nLe funzioni non pure sono anche molto difficili da testare: bisogna creare un sistema \"finto\" che possono modificare, e bisogna analizzare come questo sistema cambia ad ogni chiamata della funzione.\n\nLe funzioni pure invece sono facilmente testabili; un input ti da' sempre lo stesso output, quindi possono essere testate, modificate e ottimizzate senza paura di cambiare il flusso della applicazione.\n\n### Funzioni pure: pipes, composition e higher-order functions\n\nUsando diverse funzioni pure si possono anche creare delle astrazioni che rendono il flusso della applicazione piu' semplice (o piu' facile da modificare e mantenere).\n\nI **pipes** sono funzioni in serie, in cui l'output di una funzione viene passato come input di quella dopo.\nRisultano molto utili in caso di serializzazione di data e deserializzazione (ad esempio quando si comunica con una API esterna).\n\n**Functions compositions** sono simili ai pipes, ma si leggono da destra a sinistra.\n\n```js\n// First step\nfunction addApiCode(object, code) {\n    return {...object, code}\n}\n\n// Second step\nfunction formatDates(object) {\n    return {\n    ...object,\n    date: format(date)\n    }\n}\n\n// Last step\nfunction filterOutUnefinedValues(object) {\n    const result = {}\n    for (let [key, value] of Object.entries(object)) {\n        if (value) {\n            result[key] = value\n        }\n    }\n    return result\n}\n\n// Pipe\npipe(addApiCode, formatDates, filterOutUnefinedValues)(myObject)\n\n// Componsition\ncompose(filterOutUnefinedValues, formatDates, addApiCode)(myObject)\n// Uguale a\nfilterOutUnefinedValues(formatDates(addApiCode(myObject)))\n\n// Entrambi sono uguali a\nconst objectWithApiCode = addApiCode(myObject)\nconst objectWithApiCodeAndFormattedData = formatDates(objectWithApiCode)\nconst objectWithApiCodeAndFormattedDataWithoutUndefinedValues = filterOutUnefinedValues(objectWithApiCodeAndFormattedData)\n```\n  \n`pipe` e `compose` sono **higher-order functions**: funzioni che prendono come argomenti altre funzioni. Esse sono molto utili per rendere il codice piu' dinamico e migliorare la manutenzione del progetto.  \nAnche `map`, `forEach`, `filter` etc. sono higher-order functions.\n\n```js\nfunction removeUndefined(item) {return item === undefined}\n\n[1,2,3,undefined].filter(removeUndefined)\n// uguale a\n[1,2,3,undefined].filter(item =\u003e item === undefined)\n```\n\n---\n\n## Architettura\n\nAlcune linee guida per l'architettura delle applicazioni Angular.\n\n!! **Nota**: con metodo si intende una funzione che fa parte di una classe.\n\n### Funzioni e moduli\nI metodi che aiutano a manipolare data (formatters, extractors etc.) o helper functions vanno parametizzati, estratti dalla classe e messi in un modulo specifico.  \nCio' permette di avere funzioni pure facilmente testabili e riutilizzabili (in caso la loro logica sia condivisa in altre parti della applicazione).\n\n```js\n// Prima\nclass MyComponent {\n    filter = {};\n    handleClick() {\n        this.filter = _formatFormData();\n    };\n\n    private _formatFormData() {\n        const data = this._form.getData();\n        return {...data, date: format(data.date)};\n    };\n};\n\n// Dopo\nimport {addDateToForm} from \"data-manipulation/formatters\";\n\nclass MyComponent {\n    filter = {};\n    handleClick() {\n        this.filter = addDateToForm(this._form)\n    };\n};\n\n// Formatters.js\nfunction addDateToForm(form) {\n        const data = form.getData();\n        return {...data, date: format(data.date)};\n};\n```\n\n### Component\nI components hanno metodi che servono per:\n- Lifecycle del component\n- Gestire eventi\n- Gestire subscriptions e observables\n\nSi occupano di mostrare data all'utente e di gestire i suoi inputs.\n\n### Services\nI services vengono usati per condividere data fra components e permettere ad essi di comunicare.  \nPer questa ragione, sono \"provided in root\", rendendo la loro data in condivisione con il resto della applicazione.  \nPer questa ragione, devono avere una funzione chiamata `reset` che permetta di \"pulire\" il service quando un componente non lo usa piu'.\n\n### Data-services\nI data-services sono sevices che vengono utilizzati per esporre API endpoints ai componenti. (RFC (request for comments): Questi potrebbero anche essere esposti da moduli in realta', se non avvengono ottimizzazioni da parte di Angular).\n\n### Architettura tipo\n\n\n\n```\n-src\n|    -app\n|    |    -services\n|    |    |    -data-services\n|    |    |    |    -stores\n|    |    |    |    |    -store.data-service.ts -\u003e service\n|    |    |    |    |    -store-data-serializers.ts -\u003e module\n|    |    |    |    |    -store-data-deserializers.ts -\u003e module\n|    |    |    |    |    -store.data-service.spec.ts -\u003e service test\n|    |    |    -services\n|    |    |    |    -store-filter\n|    |    |    |    |    -store-filter.service.ts -\u003e service\n|    |    |    |    |    -store-filter-formatter.ts -\u003e module\n|    |    |    |    |    -store-filter.spec.ts -\u003e service test\n|    |    -components\n|    |    |    -store\n|    |    |    |    -store.component.ts -\u003e component\n|    |    |    |    -store.component.html -\u003e template\n|    |    |    |    -store.component.spec.ts -\u003e component test\n|    |    |    |    -store-utils.ts -\u003e module\n|    |    -tests\n|    |    |    -unit-tests\n|    |    |    |    -services\n|    |    |    |    |    -data-services\n|    |    |    |    |    |    -stores\n|    |    |    |    |    |    |    -store-data-serializers.spec.ts -\u003e module tests\n|    |    |    |    |    |    |    -store-data-deserializers.spec.ts -\u003e module tests\n|    |    |    |    |    -services\n|    |    |    |    |    |    -store-filter\n|    |    |    |    |    |    |    -store-filter-formatter.spec.ts -\u003e module tests\n|    |    |    |    -components\n|    |    |    |    |    -store\n|    |    |    |    |    |    -store-utils.spec.ts -\u003e module tests\n|    |    |    |    -utils\n|    |    |    |    |    -data-structures.spec.ts -\u003e module tests\n|    |    |    -integration-tests\n|    |    |    |    ...\n|    |    -utils\n|    |    |    -data-structures.ts -\u003e module\n```\n\n\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmochitto%2Fbest-practices","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmochitto%2Fbest-practices","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmochitto%2Fbest-practices/lists"}