{"id":20504455,"url":"https://github.com/tiknil/swift-style-guide","last_synced_at":"2026-02-08T22:32:01.231Z","repository":{"id":113422242,"uuid":"67408069","full_name":"tiknil/swift-style-guide","owner":"tiknil","description":"Tiknil's style guide \u0026 coding conventions for Swift projects","archived":false,"fork":false,"pushed_at":"2021-02-10T15:55:43.000Z","size":227,"stargazers_count":1,"open_issues_count":0,"forks_count":1,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-08-12T10:32:10.204Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"http://www.tiknil.com","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tiknil.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-09-05T09:39:47.000Z","updated_at":"2021-02-10T15:55:46.000Z","dependencies_parsed_at":"2023-04-24T18:45:18.796Z","dependency_job_id":null,"html_url":"https://github.com/tiknil/swift-style-guide","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/tiknil/swift-style-guide","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tiknil%2Fswift-style-guide","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tiknil%2Fswift-style-guide/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tiknil%2Fswift-style-guide/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tiknil%2Fswift-style-guide/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tiknil","download_url":"https://codeload.github.com/tiknil/swift-style-guide/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tiknil%2Fswift-style-guide/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29247610,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-08T21:42:34.334Z","status":"ssl_error","status_checked_at":"2026-02-08T21:41:38.468Z","response_time":57,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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-11-15T19:38:07.162Z","updated_at":"2026-02-08T22:32:01.213Z","avatar_url":"https://github.com/tiknil.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# swift-style-guide\nGuida di riferimento per i progetti Swift gestiti da Tiknil e i suoi collaboratori.\n\nL'obiettivo è darsi delle **best practices** sulla stesura del codice per agevolare il lavoro in team e velocizzare la comprensione del codice.\n\n## Riferimenti\nLinee guida da cui è stato preso spunto per scrivere questo documento:\n* [RayWenderlich Swift style guide](https://github.com/raywenderlich/swift-style-guide)\n* [Swift guidelines](https://swift.org/documentation/api-design-guidelines/)\n\nIn generale **Tiknil adotta tutte le linee guida di RayWenderlich** e in questo documento riportiamo quelle che consideriamo più importanti ed eventuali modifiche o integrazioni ad esse.\n\n## Sommario\n* [Naming](#naming)\n  * [Lingua](#lingua)\n  * [Case conventions](#case-conventions)\n  * [Type inferred context](#type-inferred-context)\n* [Organizzazione del codice](#organizzazione-del-codice)\n  * [Implementazione di protocolli](#implementazione-di-protocolli)\n  * [Codice inutilizzato](#codice-inutilizzato)\n* [Indentazione](#indentazione)\n* [Design pattern](#design-pattern)\n  * [MVC](#mvc)\n  * [MVVM](#mvvm)\n  * [Inversion of Control e Dependency Injection](#inversion-of-control-e-dependency-injection)\n  * [Flow coordinator](#flow-coordinator)\n* [Struttura del progetto](#struttura-del-progetto)\n  * [Repository e CocoaPods](#repository-e-cocoapods)\n  * [Cartelle di progetto](#cartelle-di-progetto)\n* [ReactiveX](#reactivex)\n* [Esempio pratico](#esempio-pratico)\n\n## Naming\nPer facilitare la lettura del codice seguiamo i soprattutto i seguenti principi:\n* chiarezza **\u003e** brevità\n* usare `CamelCase`, mai `snake_case`\n* preferire metodi e proprietà a funzioni\n* evitare overload di metodi modificando solo il tipo ritornato\n\n### Lingua\nUsare la lingua Inglese per il codice, quella Italiana per i commenti e la documentazione del codice (ove non espressamente richiesta la lingua inglese)\n\n👍\n```Swift\nlet myColor = UIColor.white\n```\n\n👎\n```Swift\nlet mioColore = UIColor.white\n```\n\n### Case conventions\nTipi (classi) e protocolli in `UpperCamelCase`\n\nQualsiasi altra cosa in `LowerCamelCase`\n\n👍\n```Swift\nclass MyAwesomeClass { ... }\nstruct MyAwesomeStruct { ... }\nlet constant = \"http://www.tiknil.com\"\nvar variable = 3\n```\n\n👎\n```Swift\nclass myAwesomeClass { ... }\nstruct my_awesome_struct { ... }\nlet _constant = \"http://www.tiknil.com\"\nvar Variable = 3\n```\n\n### Type inferred context\nOve possibile lasciare contestualizzare al compilatore per migliorare la leggibilità del codice.\n\n👍\n```Swift\nlet selector = #selector(viewDidLoad)\nview.backgroundColor = .red\nlet toView = context.view(forKey: .to)\nlet view = UIView(frame: .zero)\n```\n\n👎\n```Swift\nlet selector = #selector(ViewController.viewDidLoad)\nview.backgroundColor = UIColor.red\nlet toView = context.view(forKey: UITransitionContextViewKey.to)\nlet view = UIView(frame: CGRect.zero)\n```\n\n## Organizzazione del codice\nNelle classi utilizzare lo [snippet di codice](https://github.com/tiknil/xcode-snippets) per la generazione dei `MARK` in modo da separare uniformemente il codice in tutte le classi secondo la seguente struttura:\n\n```Swift\n  // MARK: - Properties\n  // MARK: Class\n  \n  \n  // MARK: Public\n  \n  \n  // MARK: Private\n  \n  \n  // MARK: - Methods\n  // MARK: Class\n  \n  \n  // MARK: Lifecycle\n  \n  \n  // MARK: Public\n  \n  \n  // MARK: Private\n```\n\n### Implementazione di protocolli\nImplementare eventuali protocolli creando `extension` della classe per separare logicamente il codice per contesto.\n\n👍\n```Swift\nclass MyViewController: UIViewController {\n  // codice di classe\n}\n\n// MARK: - UITableViewDataSource\nextension MyViewController: UITableViewDataSource {\n  // implementazione dei metodi di UITableViewDataSource\n}\n\n// MARK: - UIScrollViewDelegate\nextension MyViewController: UIScrollViewDelegate {\n  // implementazione dei metodi di UIScrollViewDelegate\n}\n```\n\n👎\n```Swift\nclass MyViewController: UIViewController, UITableViewDataSource, UIScrollViewDelegate {\n  // tutti i metodi\n}\n```\n\n### Codice inutilizzato\nSempre per migliorare la leggibilità, in generale, è meglio rimuovere:\n* codice non più utilizzato o sostituito da altre parti di codice\n* vecchio codice commentato\n* metodi che chiamano semplicemente la `superclass`\n\n👍\n```Swift\noverride func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -\u003e Int {\n  return elements.count\n}\n```\n\n👎\n```Swift\n// Questo metodo non aggiunge nessuna implementazione specifica quindi è meglio ometterlo\noverride func didReceiveMemoryWarning() {\n  super.didReceiveMemoryWarning()\n  // Dispose of any resources that can be recreated.\n}\n\noverride func numberOfSections(in tableView: UITableView) -\u003e Int {\n  // #warning Incomplete implementation, return the number of sections\n  return 1\n}\n\noverride func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -\u003e Int {\n  // #warning Incomplete implementation, return the number of rows\n  return elements.count\n}\n```\n\n## Indentazione\n* Le parentesi graffe `{` `}` vanno sempre aperte sulla stessa riga e chiuse su un'altra riga.\n\u003e **CONSIGLIO:** Si può indentare automaticamente premendo `⌘+A` (seleziona tutto) e `Control+i` (indentazione automatica)\n\n👍\n```Swift\nif user.isHappy {\n  // Do something\n} else {\n  // Do something else\n}\n```\n\n👎\n```Swift\nif user.isHappy\n{\n  // Do something\n}\nelse {\n  // Do something else\n}\n```\n\n* I due punti `:` hanno sempre uno spazio a destra e zero a sinistra. Eccezioni: operatore ternario `? :`, dizionario vuoto `[:]` e `#selector` per metodi con paramteri senza nome `(_:)`.\n\n👍\n```Swift\nclass TestDatabase: Database {\n  var data: [String: CGFloat] = [\"A\": 1.2, \"B\": 3.2]\n}\n```\n\n👎\n```Swift\nclass TestDatabase : Database {\n  var data :[String:CGFloat] = [\"A\" : 1.2, \"B\":3.2]\n}\n```\n\n## Design pattern\n\n### MVC\nApple utilizza nel proprio SDK il design pattern **MVC (Model-View-Controller)**.\n\nTale pattern normalmente promette di separare in 3 livelli il codice:\n\n* Il **Model** è dove risiedono i dati dell'app. Persistenza, oggetti che rappresentano i dati, parser e networking sono normalmente in questo livello.\n* Il livello **View** è la UI dell'app. Le sue classi rappresentano un elemento visibile dall'utente e dovrebbero essere tipicamente riusabili come ad esempio un pulsante.\n* Il **Controller** ha il compito di prendere i dati dal *Model* e mostrarli nelle *View* ed elaborare le azioni dell'utente.\n\nI legami tra i 3 layer sono rappresentabili così:\n![Original MVC](https://github.com/tiknil/swift-style-guide/blob/master/images/original_mvc.png)\n\nPer come è strutturato *UIKit* la realtà è che Apple utilizza un MVC leggermente modificato:\n![Original MVC](https://github.com/tiknil/swift-style-guide/blob/master/images/apple_mvc.png)\n\nIn pratica *View* e *Controller* risultano molto legati portando a scrivere la maggioranza del codice nei **UIVIewController**. In ambito iOS viene infatti spesso associata un'altra definizione all'acronimo MVC: **Massive-View-Controller**.\n\nI problemi introdotti da questo pattern modificato sono:\n\n1. Il codice è **difficilmente testabile**\n2. **Scarsa riusabilità** delle *view*\n\nPer risolvere tali problemi Tiknil ha deciso di utilizzare il pattern MVVM descritto di seguito.\n\n### MVVM\n\nIl design pattern **MVVM (Model-View-ViewModel)** applicato all'SDK di Apple risulta una naturale evoluzione di MVC:\n![Original MVC](https://github.com/tiknil/swift-style-guide/blob/master/images/mvvm.png)\n\nIl livello **View** comprende quindi sia **UIView** che **UIViewController**:\n\nL'obiettivo del **ViewModel** è di essere una **rappresentazione astratta** della view a cui è associato. Ad esempio se la view deve mostrare nome e cognome dell'utente il viewmodel avrà due proprietà di tipo string che contengono queste informazioni.\n\nCiò introduce i seguenti vantaggi:\n\n* È possibile **sostituire la view** associata al viewmodel senza problemi.\n* È possibile separare dalla view eventuali trasformazioni dei dati presenti nel model. Esempio: formattazione di una data in base alla lingua. Questa operazione viene normalmente chiamata **Presentation logic**.\n* È possibile eseguire **test funzionali** direttamente sul viewmodel.\n\nPer un'analisi più dettagliata dell'evoluzione MVC =\u003e MVVM leggere [questo articolo](https://www.objc.io/issues/13-architecture/mvvm/) di **Ash Furrow**.\n\n### Inversion of Control e Dependency Injection\nL'*Inversion of Control* (**IoC**) è un *software design pattern* secondo il quale ogni componente dell'applicazione deve ricevere il **controllo** da un componente appartenente ad una **libreria riusabile**.\u003cbr\u003e\nL'obiettivo è quello di rendere ogni componente il più indipendente possibile dagli altri in modo che ognuno sia modificabile singolarmente con conseguente maggior riusabilità e manutenibilità.\n\nLa *Dependency Injection* (**DI**) è una forma di *IoC* dove l'implementazione del pattern avviene stabilendo le dipendenze tra un componente e l'altro tramite delle *interfacce* (chiamate **interface contracts**).\u003cbr\u003e\nA tali interfacce viene associata un'implementazione in fase di istanziazione del componente (nel *costruttore*) oppure in un secondo momento tramite *setter*.\u003cbr\u003e\nIn ogni caso è generalmente presente un oggetto **container** che si occupa di creare le istanze di ogni *interfaccia*; la configurazione di tale *container* può così influenzare le dipendenze tra i vari componenti.\u003cbr\u003e\nL'utilizzo della *DI* è molto utile per la realizzazione di test automatici, infatti modificando il *container* è possibile *mockare* le dipendenze che non si desidera testare.\n\nReferences:\n\n* [Semplice video che chiarisce il concetto di DI](https://www.youtube.com/watch?v=IKD2-MAkXyQ)\n\n### Flow coordinator\nIl *flow coordinator* pattern si occupa della gestione della navigazione dell'applicazione e della creazione/distruzione delle varie schermate quando necessario.\n\nI vantaggi dell'utilizzo di questo pattern sono:\n\n* **Decoupling fra schermate:** ogni schermata (View + ViewModel) non ha riferimenti ad altre schermate, ma espone solo un'interfaccia con eventi di navigazione che saranno interpretati dal coordinator.\n* **Facilità di cambio navigazione:** in caso sia necessario cambiare il sistema di navigazione basta apportare modifiche al coordinator senza toccare minimamente le schermate.\n* **Riusabilità del codice:** dato che View e ViewModel non si occupano di navigazione è più facile riutilizzarli anche se l'ambito di navigazione è differente.\n* **Più facile da testare:** l'assenza di navigazione in View e ViewModel semplifica la creazione di test automatici.\n\nFondamentamentalmente un *Coordinator* non è altro che un semplice oggetto che è responsabile di configurare View e ViewModel e gestirne la presentazione in un determinato flusso di navigazione.\n\nÈ opportuno che sia presente un coordinator principale, generalmente chiamato *AppCoordinator*, che si occupa dell'avvio della navigazione tramite l'avvio di vari coordinator secondari che si occupano di singoli flussi di navigazione atomicizzabili per contesto.\n\nEsempio:\n\n![Flow Coordinator pattern schema](https://github.com/tiknil/swift-style-guide/blob/master/images/flow_coordinator_pattern_schema.png)\n\nIn questo esempio l'`AppCoordinator` è il coordinator principale e all'avvio dell'app deciderà quale coordinator figlio avviare:\n\n* `OnBoardingCoordinator`: al primo avvio dell'app avvierà questo coordinator per mostrare il tutorial.\n* `AuthCoordinator`: se non è stata cachata l'autenticazione in un precedente avvio verrà avviato questo coordinator per permettere all'utente di loggarsi o registrarsi.\n* `MainCoordinator`: questo coordinator può essere avviato direttamente all'avvio se l'autenticazione è stata cachata da sessioni precedenti, oppure in seguito al completamento di un autenticazione nella sessione corrente. Esso ha la possibilità di avviare il coordinator figlio `ProfileCoordinator` per mostrare la schermata di profilo dell'utente.\n\nÈ interessante notare come sia il `ProfileCoordinator`, sia l'`AuthCoordinator` abbiano la possibilità di avviare l'`OnBoardingCoordinator` per permettere all'utente di visualizzare il tutorial quando lo desidera.\n\nNella documentazione dell'[esempio pratico](#esempio-pratico) possiamo vedere come Tiknil implementa MVVM + Coordinator nei propri progetti.\n\n## Struttura del progetto\nNelle seguenti sezioni definiamo le best practices di Tiknil per l'impostazione di un progetto iOS in Swift chiamato **AwesomeApp**.\n\n### Repository e CocoaPods\nLa root del repository avrà la seguente struttura:\n\n```\n|-- .git                         # Working copy di git\n|-- AwesomeApp                   # Codice sorgente dell'app\n|-- AwesomeAppTests              # Unit test automatici\n|-- AwesomeAppUITests            # Test automatici di UI\n|-- Pods                         # Cartella contenente le librerie CocoaPods\n|-- Podfile.lock                 # Gestione versioni dei pods. Gestito automaticamente da CocoaPods\n|-- .gitignore                   # Specifica i file da escludere dal repo\n|-- Podfile                      # Configurazione dei pod \n|-- Readme.md                    # Readme con modifiche di versione\n|-- AwesomeApp.xcodeproj         # File di progetto. Non va utilizzato\n|-- AwesomeApp.xcworkspace       # File del workspace contenente configurazione dei CocoaPods.\n```\n\nPrima del primo commit sul repository git aggiungere il file [.gitignore](https://github.com/tiknil/swift-style-guide/blob/master/resources/.gitignore).\n\n### Cartelle di progetto\nLa cartella contenente il codice sorgente dell'app avrà la seguente struttura:\n\n```\n|-- Helpers           # Classi di generico aiuto per tutto l'app. Es: Colors.swift\n|-- Models            # Tutti gli oggetti model\n|-- Coordinators      # Tutti i coordinators per gestire il flusso di navigazione dell'app\n|-- ViewModels        # Tutti i viewmodel eventualmente inseriti in sottocartelle di sezione\n|-- Views             # Tutti i viewcontroller eventualmente inseriti in sottocartelle di sezione\n    |-- Reusable      # Tutte le view riutilizzabili in altre view. Es: navigation bar custom\n|-- UI                # Storyboards e xib.\n    |-- Reusable      # Xib relativi alle view nella cartella Views/Reusable\n|-- Services          # Oggetti che forniscono servizi come networking e persistenza\n|-- Libraries         # Librerie create da Tiknil non importate come submodule\n|-- Vendors           # Librerie di terzi non importate con CocoaPods o submodule\n|-- Resources         # Assets, fonts, ecc\n|-- Application       # Info.plist, AppDelegate.swift ed eventual bridging-header.h\n```\n\nLe cartelle al primo livello le creiamo fisicamente nel file system e le importiamo in modo che creino il gruppo logico nel progetto Xcode, mentre quelle al secondo livello possiamo anche lasciarle solo come gruppi logici.\n\n## ReactiveX\n\nTiknil utilizza _[ReactiveX](https://github.com/ReactiveX/RxSwift)_ nei propri progetti sia per la manipolazione dei dati, sia per la visualizzazione di quest'ultimi nella UI.\n\n**ReactiveX** non è altro che una generica definizione di API per la programmazione asincrona che estende l'[Observer pattern](https://it.wikipedia.org/wiki/Observer_pattern) per supportare sequenze di dati/eventi e fornendo operatori per manipolarle; tale definizione viene implementata in molti linguaggi diversi permettendoci quindi di utilizzare gli stessi concetti sia su iOS che Android.\u003cbr\u003e\nNel caso di Swift tali API sono implementate nella libreria [RxSwift](https://github.com/ReactiveX/RxSwift), quindi faremo riferimento ad essa per esemplificare i concetti spiegati di seguito.\n\nCon _sequenza/stream di dati_ si intende generalmente un flusso di uno o più dati ordinati in una sequenza temporale, come ad esempio:\n\n* Click su un elemento dell'interfaccia grafica; in questo caso si tratta di stream di uno **stesso dato** nel tempo.\n* Caratteri inseriti in input dall'utente; in questo caso si tratta di stream di **dati dello stesso tipo** (stringa) nel tempo.\n* Chiamata di un'api con esito positivo o negativo; in questo caso si tratta di stream di **dati di tipo diverso** a seconda dell'esito (es: _positivo =\u003e json_, _negativo =\u003e errore_).\n* Modifiche ad una proprietà di un oggetto; in questo caso si tratta di uno stream che rappresenta lo **storico dei valori** assunti dalla proprietà.\n\nCome possiamo intuire da questi esempi è possibile creare stream di dati di qualsiasi tipo come _variabili, input utente, proprietà, cache, strutture dati_, etc.\n\nL'operazione fondamentale fornita da _ReactiveX_ è infatti l'**osservazione** di uno stream per _reagire_ di conseguenza. Nella pratica, con _osservazione_, si intende l'esecuzione di una funzione ogni volta che compare un dato sullo stream (generalmente chiamato **Evento**).\n\n**RxSwift** implementa i vari concetti reactive con le seguenti classi:\n\n* `Event`: unità di base trasportata da uno _stream_; si tratta quindi del dato vero e proprio.\u003cbr\u003e\n_Esempio: in una trasmissione video l'event rappresenta un frame del video._\n* `Observable`: flusso (_stream_) unidirezionale di eventi; come si può intuire dal nome, l'_observable_ può essere _osservato_ da altri oggetti.\u003cbr\u003e\nUn _observable_ può essere [**hot** o **cold**](https://github.com/ReactiveX/RxSwift/blob/master/Documentation/HotAndColdObservables.md):\n\t* **Hot observable:** può iniziare ad emettere eventi appena creato e chiunque inizi ad osservarlo in un secondo momento riceverà eventi solo dal momento dell'osservazione in poi.\u003cbr\u003e\n_Esempio: in una trasmissione video l'hot observable rappresenta un canale tv: esso infatti è un flusso di event (frame) continuo e gli osservatori vedono il programma da quando si sintonizzano in poi, anche se esso è già iniziato in precedenza._\n\t* **Cold observable:** aspetta ad emettere eventi fino a quando qualcuno inizia ad osservarlo, garantendo all'osservatore di ricevere l'intera sequenza.\u003cbr\u003e\n_Esempio: in una trasmissione video il cold observable rappresenta un programma tv on demand (es: Netflix) che l'utente può avviare quando vuole generando appunto uno stream di event (frame)_\n* `Observer` (o `Subscriber`): oggetto che si _sottoscrive_ ad un observable ricevendo così gli eventi emessi da esso.\u003cbr\u003e\n_Esempio: nel caso delle trasmissioni tv l'observer è il telespettatore (o più precisamente il televisore)._\n\nOgni framework reactive mette sempre a disposizione utili funzioni per **creare, combinare, filtrare e trasformare** gli stream agevolandone così la manipolazione. _ReactiveX_ chiama tali funzioni **operatori** e sono documentate [qui](http://reactivex.io/documentation/operators.html).\n\nPer maggiori informazioni consultare la documentazione di [_RxSwift_](https://github.com/ReactiveX/RxSwift/blob/master/Documentation/GettingStarted.md) e [ReactiveX](http://reactivex.io/intro.html).\n\n## Esempio pratico\nAl seguente link è disponibile il codice di un'applicazione di esempio che integra tutte le **best practice** definite in questo documento:\n\n[GotEpisodes](https://github.com/tiknil/swift-style-guide/tree/master/examples/GotEpisodes)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftiknil%2Fswift-style-guide","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftiknil%2Fswift-style-guide","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftiknil%2Fswift-style-guide/lists"}