sabato, novembre 29, 2008

C#: Perdita di eleganza?

La prima volta che incontrai sulla mia strada il linguaggio C# fu nel 2003, era ancora un linguaggino molto molto MOLTO Java-style, quasi clone, con alcune features in più come boxing e unboxing, property, delegate, eventi e qualcosina d'altro.

Oggi, alla release 3.5 del .NET framework, assistiamo ad una evoluzione del linguaggio a dir poco sconvolgente! Lo dico in senso positivo da un certo punto di vista, in senso negativo da un altro:

Lati positivi dell'evoluzione del linguaggio C#
  1. Aggiunte features che permettono di modellare il software in maniera più flessibile, vedasi generics con constraints;
  2. Aggiunte features che semplificano la realizzazione di pattern comuni in maniera meno verbosa, vedasi iteratori e delegate.. anche se già dalla prima versione;
  3. Aggiunti strumenti per la cooperazione tra sviluppatori, vedasi classi e metodi parziali.
Lati negativi dell'evoluzione del linguaggio C#
  1. Metodi estesi, non hanno ancora un corrispettivo nell'esperienza comune (pattern che li vedano come strumento da utilizzare realmente);
  2. Metodi partial: si tratta in fondo di metodi virtual non puri ma senza codice (solo più efficienti.. ma i compilatori d'oggi risolvono anche quel problema!);
  3. generics: ancora problemi con i vincoli, da aggiungere features in questo caso:
    class Classe where T: operator > {...}
Insomma.. butto il sassolino: trovo che l'entropia di C# stia aumentando, portando ai problemi di utilizzo di ADA e Haskel! Voi che ne dite?

5 commenti:

nataluca ha detto...

Diciamo che negli ultimo due o tre anni l'evoluzione di Java e C# li sta portando alla complessità che dovevano/volevano eliminare quando sono stati progettati.
La potenza semantica aumenta da un lato ed è estremamente positivo ma la complessità aumenta dall'altro... se va avanti così tanto meglio un ADA-- :)

Unknown ha detto...

C# (.NET), come tutti gli altri linguaggi, è uno strumento. Quello che lo strumento ti permette di fare è un conto, quello che tu decidi di fare con lo strumento è un altro. Credo che occorra sempre capire SE e COME sfruttare le nuove feature. Alcune forse è opportuno evitarle come la peste. Altre si possono sfruttare, in maniera intelligente. Si può programmare benissimo il ASP classico o malissimo il Java ;-)

Gabriele Lombardi ha detto...

Concordo, concordo pienamente sull'importanza relativa al come uno strumento venga utilizzato, non sono comunque convinto del fatto che questo renda corretta la scelta di inserire funzionalità non complete o non coerenti tra loro, ad esempio i generics in C# attualmente non permettono di imporre vincoli sugli operatori, questa è una feature "lasciata a metà"!

Vorrei aggiungere, tutte le funzionalità che non sporcano il linguaggio sono ben accette; ma se per essere aggiunte creano confusione, rendono "pericoloso" il loro utilizzo o rendono "sporca" la sintassi allora prima mi chiederei se servono veramente. Un esempio? Non credo che in Java serva la dynamic method invocation:

http://www.baptiste-wicht.com/2010/04/java-7-more-dynamics/

la reputo inutile e pericolosa, dove "inutile" significa che quello che si può fare con si può fare anche senza (tramite reflection), inoltre è "pericolosa" perché permette di creare in maniera più rapida e semplice codice bacato per mancanza di "pezzi".

Insomma C#, Java o chi che sia, a mio avviso lo strumento deve fittare le esigenze evitando di creare pericoli, in questo caso i pericoli riguardano la creazione di architetture SW non pulite e/o non estendibili, l'introduzione delle interfacce remava a favore, altre funzionalità remano contro. Ti piacerebbe avere un'auto con un tasto per l'autodistruzione? E' una funzionalità, non usarla se sei a bordo no? ;)

Unknown ha detto...

Assolutamente d'accordo.
Il mio commento (ero sempre io quello sopra) era un po' più generico e relativo al fatto che spesso si inorridisce (io per primo, nonostante sia molto "MS-oriented") di fronte a scelte architetturarli del linguaggio che, come rilevi, vanno un tantino contro alcuni principi/pattern/regole (...o buon senso) che ormai davamo per assodati. Se fosse un mondo perfetto, avremmo un linguaggio perfetto. Non è un mondo perfetto, abbiamo molte scelte ognuna con pro e contro. Il succo è che oggi (ma questa è la mia personale esperienza) in C# ci sono più pro che contro. Purtroppo ci sono anche i "pulsanti per l'autodistruzione". Non premiamoli e sfruttimo invece tutti i pro. E' una posizione chiaramente più pratica e meno filosofica, questo è palese ;-)

Gabriele Lombardi ha detto...

Non ho dubbi su questo, a livello pratico concordo, bisogna identificare ciò che ha senso usare e come va usato per trarre vantaggio massimo da qualunque strumento. A livello pratico, questo il modus operandi, a livello di sviluppo di linguaggi di programmazione, quindi per chi deve mettersi dietro le quinte e decidere le features del linguaggio, reputo errori (umani e non banali da comprendere a livello di design del linguaggio) gli inserimenti di features tipo "pulsante di autodistruzione". Ada è schiattato come linguaggio perché faceva troppo, non perché fosse poco potente. Le interfacce in Java hanno aggiunto a livello di design un boost tale da essere state poi scopiazzate (e migliorate) da molti altri linguaggi. L'overloading degli operatori del C++ non ha subito la stessa diffusione.. perché non aggiungono nulla ma rendono pericoloso il linguaggio, perché "a.concatenate(b)" è chiaro e "a + b" meno (nonostante in Java sporchevolmente si sia inserito questo caso particolare, viene sconsigliato da tutti per vari motivi). L'ereditarietà multipla è potente.. si ma non serve a nulla infatti la maggior parte dei linguaggi di nuova generazione non la permette. Se domani si svegliassero e decidessero di aggiungere l'ereditarietà multipla al C# (e nel CIL) farebbero una cazzata.. a mio avviso.