features · Sep 3, 2014

Quire: costruire una grande applicazione con Dart

✦
Tradotto dall'IA
· Visualizza in inglese

Applicazione Quire realizzata con il linguaggio di programmazione Dart

Ultimo aggiornamento: 28 maggio 2026

TL;DR

Quire (53.992 righe, 1.620 KB di Dart) è stato costruito nel 2014 con Dart sia sul client che sul server, usando DQuery e Bootjack al posto di AngularDART o Polymer.dart per avere un controllo più fine del DOM. Le scelte di fondo (tipizzazione forte su tutto lo stack, modelli di dati condivisi tra client e server, event loop sul server e tree shaking per l'output JS) reggono ancora nel 2026.

Quire non è la prima applicazione web scritta in Dart e non sarà l'ultima, ma potrebbe essere la prima a fare tanto affidamento su Dart, sia lato client che lato server.

Logo del linguaggio di programmazione Dart e framework per l'applicazione web Quire

È un divertente gestore di attività con una struttura ad albero fin nel profondo. Il progetto conta 53992 righe, 1620 KB di codice Dart, ed è costruito con alcune librerie open source della community.

Chi ha costruito Quire?

Prima di iniziare a lavorare a questo progetto, eravamo appassionati di Dart noti come il team Rikulo, e avevamo già rilasciato diverse librerie Dart: framework UI, libreria UI, web server, server di messaggistica, client per database e altro ancora.

Quando Dart è uscito nel 2011, eravamo tutti entusiasti del suo valore futuro e abbiamo subito iniziato a usarlo in piccole parti di alcuni progetti. Alla fine siamo passati a costruire un'applicazione completa, scritta in gran parte in Dart. Qui vorremmo condividere con umiltà un po' della nostra esperienza, nella speranza di darti qualche informazione utile sullo sviluppo in Dart.

Perché Quire ha scelto Dart invece di JavaScript?

Le ragioni per scegliere Dart sono moltissime. Le più importanti per noi sono queste:

  • Il solido sistema di tipi di Dart ci protegge da innumerevoli piccoli errori. Dart Editor, l'IDE ufficiale, segnala subito gli errori di tipo, offre il completamento automatico e rende più semplice il tracciamento.
  • Riteniamo che il modello di ereditarietà basato su classi sia molto più intuitivo di quello basato su prototipi.
  • Dart offre la possibilità di usare lo stesso linguaggio sia sul client che sul server, condividendo lo stesso modello di dati e la stessa base di codice.
  • Dart risolve la maggior parte delle trappole di JavaScript. Non è perfetto in questo, ma elimina il 99% delle vecchie brutte sorprese.
  • Dart offre già oggi alcune funzionalità molto apprezzate di JavaScript Harmony: Future (promise), Arrow Function e così via.
  • Dart è sostenuto da un team solido, con molte librerie ufficiali di alta qualità e API ben organizzate. Dart è ancora in evoluzione, ma la specifica è già abbastanza stabile.
  • Lato server preferiamo il modello a event loop al multi-threading.
  • Dart esegue il tree shaking quando viene compilato in JavaScript. (Vedi sotto.)

Ci sono anche degli svantaggi nello scegliere Dart:

  • La community di Dart è molto più piccola di quella di JavaScript.
  • La comunicazione tra Dart e JavaScript non è banale.
  • In un linguaggio fortemente tipizzato è più difficile fare il polyfill delle API.
  • Le prestazioni di Dart Editor non sono ottimali per i progetti di grandi dimensioni (per ora).

Grazie al supporto della tipizzazione forte, scrivere in Dart è molto più affidabile che scrivere in JavaScript. Inoltre Dart è meno verboso di Java e a volte (per esempio con le function expression) lo è persino meno del JavaScript puro. In generale lavorare con Dart è piacevole, a parte alcuni aspetti:

  • I campi final devono essere inizializzati nell'initializer, prima del corpo del costruttore.
  • La specifica dei mixin è ancora piuttosto acerba e non verrà corretta prima della versione 2.0.
  • Non esistono parametri di tipo generico per le dichiarazioni di funzione, ma solo per le classi. (Naturalmente questo aumenterebbe il carico di lavoro del compilatore.)

Come funziona Dart lato client?

Finché la VM di Dart non arriverà su Chrome, per distribuire il prodotto bisogna compilarlo in JavaScript. Esistono moltissimi linguaggi che compilano in JavaScript, ma Dart si distingue per qualche vantaggio in più.

  • In fase di sviluppo eseguiamo Dart in modo nativo su Dartium, un browser derivato da Chromium con una VM Dart integrata. In questa fase non serve compilare, e ci risparmiamo innumerevoli interruzioni.
  • Nei test e in produzione compiliamo in JavaScript ed eseguiamo su tutti i principali browser. Il compilatore da Dart a JavaScript esegue il tree shaking, che elimina dal risultato il codice inutilizzato. Questo riduce moltissimo le dimensioni del nostro codice JavaScript.

Perché usare Dart lato server?

Dart lato server non è mai stato un tema caldo nella community Dart, ma lo consideriamo un ottimo candidato come linguaggio di programmazione per il server, perché:

  • Un servizio web, per sua natura asincrona, funziona molto bene con il modello a event loop (rispetto al multi-threading).
  • Il codice lato server richiede molta più robustezza e sicurezza di quello lato client. Un linguaggio fortemente tipizzato è davvero utile in questo.

Correlato: Quire ottiene la certificazione ISO per proteggere i tuoi dati — la stessa attenzione alla robustezza e alla sicurezza lato server si ritrova anni dopo nella certificazione formale di Quire per la protezione dei dati.

Quali librerie usa Quire nel suo stack Dart?

Quire è costruito con circa 30 librerie importate, di cui 10 provengono dalla community, mentre le altre sono rilasciate dal team Dart. Se sei un esperto di Dart potresti immaginare che ci siano AngularDART e Polymer.dart, ma in realtà mancano entrambi.

Non usiamo AngularDART, perché:

  • Vogliamo un controllo sottile del DOM.
  • Usiamo linee guida architetturali particolari per progettare la struttura del client, e il paradigma è diverso dalla logica di Angular.
  • Quando abbiamo valutato AngularDART, generava un grande overhead sulle dimensioni del codice JavaScript compilato, ma la situazione è molto migliorata.

Non usiamo nemmeno Polymer.dart, perché:

  • A causa dell'incapsulamento e del re-targeting degli eventi, lo ShadowDOM non riesce a collaborare con i framework orientati ai selettori, come Bootstrap.
  • Non è possibile iniettare stili dall'esterno dello ShadowDOM. Se un set di componenti di terze parti è fatto con Polymer, per gli utenti è quasi impossibile cambiarne l'aspetto. Aggiornamento: da dicembre 2013 è possibile modificare lo stile interno dall'esterno. Vedi Shadow DOM 201.

Cosa sono DQuery e Bootjack?

Le pietre angolari del nostro stack lato client sono DQuery e Bootjack, due progetti open source rilasciati dal team Rikulo:

  • DQuery è un porting parziale di jQuery in Dart, incentrato sul sistema di event delegation di jQuery.
  • Bootjack è un porting completo di Bootstrap 3, con CSS e API quasi identici.

Abbiamo costruito il nostro stack applicativo in questo modo per sfruttare le conoscenze e le competenze maturate nel mondo JavaScript.

Cos'è il web server Stream?

Stream è il nostro web server, scritto in puro Dart, con funzionalità di routing, filtri, MVC lato server e altro. Stream funziona senza intoppi con il modello a event loop. Scrivere un gestore di richieste significa semplicemente concatenare una sequenza di routine non bloccanti.

Non è solo più produttivo, ma anche più piacevole da usare rispetto al tradizionale modello multi-threading. Scaliamo il nostro servizio web e gestiamo HTTPS con nginx, delegando le richieste a Stream. Con questa architettura possiamo avviare e arrestare singolarmente le VM Dart e aggiornare il server senza interrompere l'attività degli utenti.

Conclusione

Lavorare con Dart è stata un'esperienza piacevole e non vediamo l'ora di assistere a nuovi sviluppi entusiasmanti nella community Dart. Ultima cosa, ma non meno importante: se sei curioso di scoprire cosa puoi realizzare con Dart, vieni a provare la nostra app, Quire. È gratis!

Scopri di più su come Quire è stato poi reinventato e ricostruito come Mark II.

Diagramma dell'architettura di Quire che mostra l'implementazione client-server in Dart

Quali lezioni di questa realizzazione del 2014 valgono ancora nel 2026?

Da quando è stato scritto questo articolo, sia il linguaggio Dart sia la base di codice di Quire sono cambiati molto. Dart 2.0 (sistema di tipi solido) è arrivato nel 2018, Dart 3.0 (null safety, record, pattern) nel 2023, e Flutter ha cambiato il panorama delle UI multipiattaforma (anche il team mobile di Quire è passato a Flutter). Ma le decisioni architetturali di fondo descritte sopra reggono meglio di quanto si potrebbe pensare.

La tipizzazione forte su client e server paga ancora. Gli errori di runtime che un sistema di tipi forte intercetta in fase di build sono sempre gli stessi. JavaScript si è avvicinato alla tipizzazione con TypeScript, ma uno stack tipizzato end-to-end resta raro. La classe di bug citata da Simon (innumerevoli piccoli errori) è ancora quella che uno stack non tipizzato porta in produzione.

Condividere i modelli di dati tra client e server fa ancora risparmiare lavoro. Il problema di duplicare i modelli (uno in JS, uno in Python, che divergono in silenzio) è lo stesso nel 2026 come nel 2014. Anche la soluzione (un solo linguaggio end-to-end) è la stessa. I team TypeScript-on-Node costruiscono architetture in stile Quire proprio per questo motivo.

L'event loop continua a battere il multi-threading per i web server. Node, Deno, Bun e lo stesso pattern Stream di Dart sono d'accordo su questo. La discussione si riapre ogni pochi anni e arriva sempre alla stessa conclusione.

Il tree shaking conta di più, non di meno. Nel 2014 il compilatore Dart con tree shaking era un elemento distintivo. Nel 2026 è il minimo indispensabile per qualsiasi pipeline di build destinata a JS. Webpack, Rollup, esbuild e Vite lo fanno tutti. La lezione resta valida; gli strumenti si sono allineati.

Le preoccupazioni sullo ShadowDOM del 2014 sono per lo più risolte. Polymer.dart è stato deprecato. I Web Components sono maturati. I motivi addotti da Simon per evitare Polymer (iniezione di stili, collaborazione con i framework) sono stati infine risolti dalla piattaforma. Il principio generale (evitare i framework all'avanguardia per il cuore di un'app in produzione) vale ancora nel 2026 per qualunque sia il framework "entusiasmante" del momento.

Correlato: Come è fatta: una Sequenza Temporale mobile basata su Flutter — uno sguardo a come il team mobile di Quire ha usato Flutter per costruire una Visualizzazione Sequenza temporale.

Quali sono gli errori più comuni nella scelta di un linguaggio per una grande app web?

Scegliere lo stack linguistico per un'applicazione destinata a durare anni è una delle poche decisioni ingegneristiche costose da rimettere in discussione. Quando i team sbagliano, di solito ricadono in quattro schemi.

1. Scegliere per default il linguaggio con la community più grande. JavaScript ha la community più grande, ma "più grande" non significa "più adatto al tuo problema". Un linguaggio con un sistema di tipi forte, buoni strumenti e una community più piccola può battere un ecosistema sterminato con garanzie deboli. La dimensione della community conta, ma non è l'unica cosa che conta.

2. Scegliere uno stack con linguaggi diversi per client e server. Ogni modello di dati duplicato è un bug in attesa di esplodere. I team che usano Ruby sul server e JS sul client si portano dietro quel costo per sempre. I team che condividono un solo linguaggio su entrambi i fronti (Dart, TypeScript, Kotlin) evitano un'intera classe di bug.

3. Adottare la tecnologia all'avanguardia prima che si stabilizzi. Nel 2014 il team di Quire ha evitato AngularDART e Polymer.dart perché entrambi avevano questioni architetturali aperte. AngularDART ha cambiato rotta radicalmente e Polymer è stato deprecato. La regola generale (lascia che un framework si dimostri in produzione su larga scala prima di scommettere su di esso il cuore della tua app) vale ancora nel 2026 per qualunque sia il framework "entusiasmante" del momento.

4. Rinunciare al sistema di tipi per una velocità di breve periodo. I linguaggi non tipizzati sembrano più veloci nella prima settimana. Al sesto mese, il tempo risparmiato viene più che restituito in tempo di debug. I team di ingegneria che hanno vissuto su larga scala sia stack non tipizzati sia tipizzati non tornano quasi mai indietro di loro spontanea volontà.

La scommessa del team di Quire su Dart nel 2014 appare ragionevole col senno di poi non perché Dart sia diventato dominante (non lo è diventato), ma perché i criteri di fondo (tipizzazione, condivisione tra client e server, event loop, tree shaking) sono diventati il consenso del settore nel decennio successivo.

Le decisioni che sono invecchiate bene sono stati i principi ingegneristici di fondo, non le scelte di strumenti specifici. Questo schema di solito vale per qualsiasi scelta di linguaggio fatta nell'incertezza: scegli in base a principi che puoi difendere tra dieci anni, non in base a una popolarità che puoi misurare oggi.

Unisciti a oltre 100.000 team che usano il software di project management Quire — registrati gratis

Domande frequenti

Con quale linguaggio è costruito Quire?

Dart, sia sul client che sul server. L'applicazione conta circa 54.000 righe di codice Dart, con circa 30 librerie importate.

Perché Quire ha scelto Dart invece di JavaScript o TypeScript?

Tipizzazione forte, un modello di ereditarietà basato su classi e un solo linguaggio su client e server. Dart offriva inoltre alcune funzionalità moderne prima che fossero diffuse in JavaScript.

Perché Quire non ha usato AngularDART o Polymer.dart?

Il team voleva un controllo del DOM più fine di quello consentito dal binding di AngularDART, e i modelli architetturali di Quire non corrispondevano alla logica di Angular. Polymer.dart è stato evitato perché all'epoca lo ShadowDOM entrava in conflitto con i selettori in stile Bootstrap. Polymer è stato poi deprecato, il che ha confermato la scelta.

Cosa sono DQuery e Bootjack?

Librerie open source del team Rikulo (il team di ingegneria di Quire). DQuery è un porting parziale di jQuery in Dart, incentrato sull'event delegation. Bootjack è un porting completo di Bootstrap 3 con CSS e API quasi identici.

Che cos'è Stream nello stack di Quire?

Il web server di Quire, scritto in puro Dart, che usa il modello a event loop. Routing, filtri e MVC lato server sono integrati. Quire esegue Stream dietro nginx, che gestisce scalabilità e HTTPS.

Simon Pai
Co-Founder at Bookshow