Lo scorso decennio circa c'è stato un acceso dibattito tra sostenitori della TipizzazioneForte e sostenitori della TipizzazioneDebole sia tra "accademici" che tra professionisti sul campo e le ragioni dei primi si sono rivelate corrette.
L'idea è che più cose il compilatore sa più "servizi" può dare automaticamente al programmatore aumentandone la produttività e la qualità del codice prodotto. E Don Box stesso ribadisce in "Essential .NET vol.1" l'importanza dello strong-typing per .NET.
Oggi possiamo toccare con mano nel .NET Framework i vantaggi a cui ha portato la TipizzazioneForte: non mancano esempi .NET di servizi che sono possibili grazie allo strong-typing e che invece sono inefficaci nelle parti di codice dove non c'è lo strong-typing. Abbozzo un elenco:
alto numero di errori di programmazione scoperti a compile-time invece che a run-time (...dal cliente)
ottimizzazioni delle prestazioni e della occupazione di memoria fatte dal compilatore (es. inlining, espressioni costanti risolte a compile-time, ottimizzazione dei loop su array/collezioni, ... )
possibilità di individuare errori logici di programmazione (codice irraggiungibile salti condizionali dall'esito costante, ...)
possibilità di fare ispezioni automatiche del codice e individuare potenziali errori (convenzioni, prestazioni, sicurezza, ...FxCop)
controllo automatico del Versioning e della Compatibilità di versioni
...
La TipizzazioneDebole offre al programmatore la possibilità di posticipare il momento in cui diventa noto il tipo di un argometo o di una variabile permettendo al codice di funzionare con una varietà di tipi che magari a compile-time non erano nemmeno noti o magari non esistevano neanche.
In sostanza chi sviluppa codice applicativo non ha scuse per non scrivere codice fortemente tipizzato (se non la mancanza di volontà o capacità). In .NET 2.0 i Generics sono stati introdotti proprio per questo motivo perché anche MS va in questa direzione.
Qualcuno potrebbe obiettare che .NET al suo interno (nella sua implementazione) in alcuni casi per quanto pochi usa la TipizzazioneDebole. Le ragioni per cui lo fa sono 2:
l'ereditarietà multipla in .NET non c'è e quindi obbligare il programmatore a simulare l'ereditarietà (con una interfaccia + una classe di aiuto da richiamare) per accedere a certe funzionalità (es. remoting, serializzazione...) avrebbe ridotto la produttività e aumentato i possibili errori.
la volontà di rendere disponibili automaticamente alcune funzionalità (es. delegate, ...) a tutti i tipi creati da un programmatore senza bisogno di richiedere nemmeno di ereditare da una classe o interfaccia (anche se l'ereditarietà multipla ci fosse).
In questi casi .NET al suo interno usa la tipizzazione debole ma lo fa per generare dinamicamente in memoria il codice fortemente tipizzato con l'aiuto della Reflection e con il CodeDom (ossia applica il ParadigmaDiProgrammazioneGenerativa). Questa compilazione riduce i problemi dovuti alla tipizzazione debole (verifica automatica della correttezza del codice e ottimizzazione delle prestazioni) mente i programmatori MS si fanno carico dei restanti servizi di cui non possono usufruire a causa della tipizzazione debole pur di semplificare la vita agli utilizzatori del loro framework (nei casi elencati sopra).
Gli autori dell'articolo sono di Microsoft Corporation, è applicabile a .NET di sicuro. Sono daccordo con l'articolo che mi aiuta a chiare, intendo che secondo me:
è positivo che un linguaggio favorisca la tipizzazione forte e fornisca costrutti (come in .NET l'ereditarietà di classe e di interfaccia, la covarianza e controvarianza, i generics) che diminiuscono i casi in cui è necessario ricorrere alla tipizzazione debole;
è positivo che un linguaggio oltre ai costrutti per la tipizzazione forte abbia anche i costrutti per la tipizzazione debole (come in .NET variabili e parametri di tipo Object, il casting dinamico detto anche downcasting, la Reflection, Emit e CodeDOM, documenti XML senza XSL schema, tabelle applicative Sql note solo a run-time);
è compito del progettista (quindi la discussione dal linguaggio si sposta sulla progettazione):
individuare quali elementi di flessibilità sono utili ad un componente per soddisfare la necessità di future evoluzioni, di configurazione, estensione e persionalizzazione in base a requisiti utente reali
determinare la solizione fortemente tipizzata che soddisfa questi requisiti e quella debolmente tipizzata e pesare vantaggi e stavatggi in relazione ai requisiti utente reali
validare la soluzione che ha trovato con una metrica macroscopica: se in un componente la tipizzazione debole supera il 20% c'è la probabilità del 80% che il progettista non abbia indagato abbastanza soluzioni che impliegano la tipizzazione forte (con i miglioramenti del .NET 2.0 i casi in cui è conveniente o addirittura necessario ricorrere alla tipizzazione debole è di molto diminuito).
I sintomi più evidenti che noto quando la tipizzazione debole è stata usata troppo o male sono:
giungono più segnalazioni di errori run-time dagli utenti finali dovuti ad errori di programmazione sul tipo di un dato (linguaggio, db, xml, etc.)
giungono più segnalazioni di errori sui dati o sui risultati elaborati dovuti ad errori di programmazione sul tipo di un dato (linguaggio, db, xml, etc.)
il programmatore fa fatica a capire il codice scritto da altri, leggendo le firme dei metodi e i tipi dei parametri non ricava informazioni utili, per avere informazioni deve entrare nel dettaglio dei singoli algoritmi.
il programmatore fa fatica a testare il codice applicativo che scrive o a scrivere unit test (perché non può fare affidamento sui tipi di dato di parametri, valori di ritorno, property etc.
I sintomi più evidenti che noto quando la tipizzazione forte è stata usata troppo o male sono:
una parte consistente di richieste di piccole modifiche richiedono al programmatore di intervenire in diverse parti del codice con un grosso dispendio di tempo
una parte consistente di piccole aggiunte richiedono al programmatore la continua creazione di nuovi tipi e nuove elaborazioni
le richieste di configurazioni o personalizzazioni di un programma per un cliente che si vorrebbe risolvere agendo sul .Config e/o scrivendo estensioni richiedono invece modifiche al codice di diverse classi.
Sono sempre stato un fan sfegatato della tipizzazione forte, ciononostante i vantaggi della tipizzazione debole sono innumerevoli (in primis la flessibilità).
Ora, penso che sia interessante la possibilità di avere entrambe i modelli. Nei web services, durante la creazione dei messaggi, è possibile definire una tipizzazione forte aggiungendone una debole (Any). Questo porta innumerevoli vantaggi anche per il versioning.
Pierre Greborio [2005-07-21]
Lorenzo Barbieri è Senior Consultant in ""ObjectWay"" (http://www.objectway.it), ha pluriennale esperienza nella realizzazione di progetti basati su architetture Microsoft. Laureato in Ingegneria Informatica al Politecnico di Milano, oggi si occupa dell'implementazione di soluzioni basate su Microsoft .NET e Windows Server System. E' Microsoft Certified Trainer, MCSD e MCDBA, autore di numerosi articoli per le principali riviste IT e speaker in corsi e conferenze in Italia e all'estero. '''Dal gennaio 2006 è Microsoft MVP nella categoria Windows - Virtual Machines'''
Lorenzo Barbieri è Senior Consultant in ""ObjectWay"" (http://www.objectway.it), ha pluriennale esperienza nella realizzazione di progetti basati su architetture Microsoft. Laureato in Ingegneria Informatica al Politecnico di Milano, oggi si occupa dell'implementazione di soluzioni basate su Microsoft .NET e Windows Server System. E' Microsoft Certified Trainer, MCSD e MCDBA, autore di numerosi articoli per le principali riviste IT e speaker in corsi e conferenze in Italia e all'estero. '''Dal gennaio 2006 è Microsoft MVP nella categoria Windows - Virtual Machines'''