Roberto Brunetti

Developing in the cloud

.NET Programming

Archives

Le Regole d'Oro per lo sviluppo mobile - Primo Episodio

Girando per varie aziende per consulenze e progettazione di architetture mi trovo spesso ad affrontare problematiche di performance o problemi sugli applicativi esistenti.

Nelle varie sessioni alle conferenze che ho tenuto (dalla Windows Professional Conference 1998, in cui ho tenuto la prima sessione in Italia su SQLCE 1.0...ve lo ricordate il primo serio mini-db  per Windows CE, alla DevLeap Conference 2007 e SQL Conference 2007) ho sempre cercato di sottilineare quanto sia importante evitare di utilizzare automatismi se non per fare prove o applicazioni molto "ristrette" sul numero di dati e funzionalità. Inevitabilmente ogni automatismo ha delle controindicazioni quindi occorre valutarne sermpre l'utilizzo.

Dopo 10 anni di mobility ho pensato di buttare giù una serie di "cose da evitare" per avere un'applicazione più semplice da manutenere, più performante e con meno casini (casini è la parola giusta) di gestione. Ovviamente ognuno è libero di fare come vuole e libero di ribattere qualunque punto, anche perchè esistono applicazioni che lavorano su 50 record al massimo e quindi forse non necessitano dell'attenzione necessaria ad applicazioni più complesse. E' altrettanto vero però che le piccole applicazioni crescono nel tempo e spesso un problema si porta dietro altri problemi.

L'esperienza di sviluppo web ha portato anche le tradizionali applicazioni client-server a lavorare con i dati in modo disconnesso con notevoli miglioramenti sui lock, sulle possibilità di eseguire elaborazioni in background (ad esempio una replica dei dati mentre l'utente lavora) e così via.

Ecco una prima lista di cose da evitare non in ordine di importanza: quando trovo 10 minuti liberi continuo la lista in vari episodi. Il tutto fa riferimento a SQLCE 2.0/3.0/3.1 e .NET CF 2.0: le ultime versioni disponibili al momento della scrittura di questo post.

  • Non usare MAI DataSet
    • sono oggetti pesanti e farraginosi
    • sono inutili in una soluzione disconnessa: le letture si fanno con il DataReader e le scritture con query di update/insert/delete
  • Non usare SqlCeResultSet
    • le performance non sono quelle promesse
    • Se usate Key-Driven o Static incorrete in lock e casini se poi volete eseguire operazioni in background
  • Lavorare sempre disconnessi dai dati
    • Non fate lock se non quando espressamente necessario alla logica applicativa
    • E' possibile fare operazioni sui dati in background
  • Usare Base Table Cursor se servono dati da una sola tabella
    • La Seek di un record su un indice ha tempi notevolmente inferiori di una SELECT
    • Un Range al posto di una WHERE ha tempi di accesso mostruosamente inferiori
  • Per questi primi punti, se volete farvi un'idea tei tempi di accesso di cui parlo date un occhio all'applicazione gratuita che ho scritto per una conferenza e che testimonia la differenze fra DataSet, ResultSet, Reader, BTC: http://thinkmobile.it/files/folders/mmdcii/entry5239.aspx. Se non avete voglia di riprovare tutti gli esempi lo zip contiene un foglio di Excel con i dati che ho raccolto eseguendo 10 volte ogni test e indicando i valori singoli e la media
  • Gli oggetti come DataSet pesano sulla memoria complessiva
    • Quando interviene il Garbage Collector, se non si possono eliminare oggetti in memoria (ad esempio il dataset è attivo e bindato ad una griglia), vengono eliminati dalla cache i metodi compilati...che dovranno essere poi ricompilati alla successiva esecuzione rallentandone l'esecuzione
  • Fare poche Open/Close al DB
    • Con SQLCE il costo di apertura e chiusura di una connessione è alto
    • Non esiste Connection Pooling per SQLCE
    • Conviene quindi lasciare aperta la connessione al DB se si cercano le prestazioni
    • Tenere quindi le connessioni statiche (con un singleton magari) nel Dal Layer
    • E' anche vero che se le connessioni devono essere più di una (lavoriamo in multithread eseguendo operazioni in parallelo) diventa più complicata la loro gestione (e chiusura).
      • Spesso, se non sono alla canna del gas, apro e chiudo le connessioni ogni volta
      • Avendo un generatore di codice diventa semplice modificare questo comporamento
      • Le connessioni comunque pesano quindi in applicazioni multi-thread pesare bene queste considerazioni
  • Merge Replication asincrona
    • Ha senso per non bloccare la User Interface
    • Ha senso per poter continuare a lavorare mentre la replica è in corso
    • Per questo dicevo di non usare lock e strumenti di accesso ai dati (come i ResultSet) che potrebbero portarsi dietro dei lock.
    • Con lock attivi alcune operazioni di Merge non si possono fare e comunque vengono rallentate moltissimo
    • Usate un Agent Profile tarato per le connessioni che utilizziamo
      • Gli Agent Profile di default prevedono alcune casistiche, ma se cercate le performance durante la replica (e i costi del GRPS/UMTS) ha senso personalizzarli
    • Usare, se lo scenario lo consente, Filtri orizzontali e verticali per minimizzare il traffico dei dati e le operazioni da effettuare server-side
    • Non usare nei filtri clausole WHERE che mimino i JOIN: usare Join filter
    • Usare il più possibile precomputed partition
  • Non concatenare MAI le stringhe, usate lo StringBuilder che evita la creazione di oggetti inutili
    • Soprattutto non farlo nei cicli !
  • Non fate Add Web Reference dai progetti di user interface
    • Usate un factory pluggabile
    • Le tecnologie cambiano (in .NET CF 3.5 arriva WCF): è importante poter cambiare il Factory visto che protocolli e tecnologie cambiano nel tempo

Torno ad un progetto, ci sentiamo presto

Posted: apr 20 2007, 12:35 by admin | with 2 comment(s) |
Filed under:

Comments

devlizard said:

Ma grande ! Questi sono i post da stampare e appendere !

Interessante notare come alcune delle "regole d'oro" valgano pari pari anche in ambiente desktop, solo che a volte il maggior numero di risorse a disposizione ti aiuta a mascherare la "cattive pratiche".

Penso allo StringBuilder vs String.Concat, piuttosto che a quel gran ciccione del DataSet :-)

# aprile 20, 2007 3:54

Roberto Brunetti said:

Ho ricevuto diverse mail sul primo episodio con richieste di chiarimenti, soprattutto per il punto apertura

# aprile 21, 2007 3:10