Cosa significa questa affermazione sul fatto che C # e Java siano la metà di una lingua? [chiuso]


32

Nell'articolo: Perché POCO , c'è questa frase:

Maciej Sobczak dice bene: "Non mi piace quando qualcuno mi dà la metà della lingua e mi dice che è per la mia protezione".

Non capisco cosa significhi, anche se C # è di proprietà di Microsoft e Java è di proprietà di Oracle , non significa che posseggano metà del linguaggio, vero? Non ho trovato alcuna prova per provare quella frase e sono davvero curioso di questo. E ancora più curioso della parte "per la mia protezione".


12
Ho interpretato questo come una critica contro il lasciare che il programmatore faccia cose come allocare liberamente e liberare memoria e quel tipo di "protezione", ma non sono sicuro se quello fosse il punto che stava cercando di fare.
Kayaman,

15
Non sono sicuro esattamente, perché l'articolo da cui cita sembra essere morto, ma sembra che stia dicendo che a Java e C # mancano alcune caratteristiche più "pericolose" o controverse di C ++, come eredità multipla o metaprogrammazione di modelli.
GoatInTheMachine,

3
Manca il contesto della citazione (il link è 404), quindi l'unica cosa che troverai qui sono le persone che indovinano ciò che probabilmente intendeva dire, o (più probabilmente) le persone che presentano la propria opinione. Se vuoi davvero conoscere il contesto, cioè cosa c'è nella pagina persa, la soluzione migliore è probabilmente quella di scrivere direttamente l'autore o forse provare a trovare la pagina persa attraverso la macchina del ritorno o simili.
JacquesB,

2
L'affermazione non ha senso, anche se puoi gestirla, non sempre vuoi esporre ogni possibile aspetto dello sviluppo del software in una lingua. Sicuramente potresti non avere problemi a leggere il codice di gestione della memoria, ma altri sviluppatori potrebbero non essere incredibilmente entusiasti di mantenere quel codice. È simile al concetto di incapsulamento. Inoltre, C # ti consente di accedere a un bel po 'di roba, direttive del compilatore, attributi speciali e riflessione, non che si debba usare quelle cose, comunque.
Mark Rogers,

32
Per il tuo bene, non prestare attenzione alle persone che pensano che una lingua debba avere tutte le caratteristiche del C ++ per essere considerata "reale" e "completa". Non prestare attenzione alle persone che pensano che la sicurezza del tipo, la sicurezza della memoria e un comportamento ben definito siano "ruote di allenamento". La correttezza sta diventando l'aspetto più importante del software nella maggior parte dei settori e le persone che sono orgogliose di non preoccuparsene diventeranno presto irrilevanti.
Theodoros Chatzigiannakis,

Risposte:


162

Sobczak non sta parlando della proprietà aziendale. La "mezza" lingua che gli manca è tutte quelle cose che non puoi fare in molte lingue moderne, anche se come esperto di computer ben istruito sa che potrebbero essere rese possibili: ereditare da tutte le classi che desideri. Assegna qualsiasi oggetto a qualsiasi altro senza vincoli di tipo. Controlla l'allocazione e libera le risorse manualmente invece di affidarti al compilatore e al runtime per farlo per lui.

Il fatto è che tutte quelle restrizioni sono state introdotte nei linguaggi di programmazione per un motivo. Abbiamo fatto abbiamo lingue che hanno permesso tutto questo. Nel corso del tempo abbiamo scoperto che il programmatore medio sta meglio con una certa quantità di restrizioni e di tenuta della mano, perché il potenziale di fare errori davvero cattivi è semplicemente troppo grande per valere la potenza e l'espressività aggiuntive.

(Ovviamente, questo a volte infastidisce i programmatori che non avrebbero davvero bisogno di così tanta mano. Le loro lamentele sono a volte legittime. Ma le persone sono notoriamente cattive nel valutare le proprie capacità, e molti che pensano di non aver bisogno delle garanzie fanno, in anzi, ne hanno davvero bisogno. Non è sempre facile distinguere i veri intellettuali superiori che si sentono frenati dalle restrizioni nei linguaggi di alto livello dei programmatori medi che pensano solo che lamentarsi li renderà superiori o che non lo sanno meglio.)


67
Questa è la mia risposta goto .
Neil,

71
Inoltre aggiungerei che non esistono intelletti superiori che non hanno bisogno di restrizioni. È sempre sicuro supporre che prima o poi tutti si incasino. E di solito maggiore è l'intelletto, maggiore è l'errore.
Neil,

29
C'è un po 'di più in Java e C # che semplicemente impedire alle persone di spararsi ai piedi. La gestione della memoria ha richiesto una notevole quantità di tempo e sforzi per gli sviluppatori prima che arrivasse la garbage collection, ad esempio, ed è difficile eseguire correttamente la gestione manuale della memoria. La garbage collection migliora la produttività del programmatore.
Robert Harvey,

12
@RobertHarvey Sono d'accordo al 100%. Essendo un programmatore C ++ da molto tempo, ero scettico sulla gestione automatica della memoria quando mi spostavo su C #. Una volta superato questo, è stato incredibilmente liberatorio non doversi preoccupare del 99% delle volte. Mi ha liberato il mio cervello di pensare invece ad altri problemi.
17 del 26

8
"Assegna qualsiasi oggetto a un altro senza vincoli di tipo." ... Allora dynamic,?
Arturo Torres Sánchez,

34

Questo è spiegato abbastanza bene nella fonte originale della citazione :

Ho deciso di saperne di più sul C ++ e ne sono diventato fedele appassionato - questo include il mio interesse per il modo in cui questa lingua probabilmente evolverà. Inoltre, ho notato che sono necessarie le tecniche più avanzate e all'avanguardia per sviluppare utili librerie , non le applicazioni reali. Tenendo presente questo, ho provato a scrivere un paio delle mie librerie per scopi diversi (vedi la mia pagina di download) e provo anche a guardare oltre le spalle degli sviluppatori di C ++ Boost (vedi la mia pagina dei link) per sapere cosa tecniche di fascia alta sono. Trascorrere tempo nello sviluppo di librerie che dovrebbero essere generiche e utili allo stesso tempo è davvero impegnativo. Ecco perché i programmatori non smettono mai di imparare.

[...]

Continuo a giocare con C ++ e le tecniche per scrivere software robusto. Per ottenere una prospettiva più ampia nel campo del software affidabile, ho deciso di investire un po 'di tempo nell'apprendimento di Ada (e cose correlate), che è una lingua che sembra essere completamente abbandonata dal business anche se era Ada che è stata davvero progettata per complessi e affidabili sistemi. Devo ammettere che l'apprendimento di Ada è stato davvero utile per me, nel senso che mi ha permesso di dare uno sguardo più nuovo al mio lavoro e ai miei approcci di sviluppo. Soprattutto, alcune delle idee del mondo Ada possono essere più o meno direttamente applicate al C ++ con buoni risultati nel campo della solidità e della correttezza.

[...]

OK, ho dimenticato. Ho giurato un giorno di non imparare Java. Ma l'ho fatto. Bene, nella misura in cui mi permette di leggere e scrivere codice funzionante. Ho letto "Thinking in Java" (disponibile on-line, gratuito) e "Core Java" (non online, non gratuito), sono stato anche indirettamente coinvolto in alcuni sviluppi Java e ... Beh, non compro esso. Semplicemente non mi piace quando qualcuno mi dà la metà della lingua e mi dice che è per la mia protezione. È come un martello di carta, reso leggero in modo che nessuno si faccia male quando si colpisce il dito ... Lo stesso vale per C #. Scelgo la mazza d'acciaio, così posso essere sicuro che quando voglio giocare macho, resisterà.
La domanda è: perché così tante persone lo usano (Java, C #, ecc.)? Hmmm ... Forse perché è molto buono in alcuni posti. Ma ci sono situazioni in cui sia la lingua che la libreria mostrano che sono state progettate piuttosto per le applet (inizialmente) che per diventare utility fai-tutto. Promette solo troppo e dà troppo poco per quanto riguarda la tecnologia catch-all. O come soluzione che potrebbe scavare su qualsiasi competizione ..

Mi piace il C ++ quando è necessaria la massima potenza e la prospettiva più ampia. Nei luoghi in cui l'espressività del C ++ non è un must, linguaggi come Tcl o Python sembrano adattarsi al conto. Non solo sono aperti riguardo alla loro evoluzione, ma è possibile estenderli e incorporarli, a seconda delle esigenze particolari. Vedo molte possibilità sognare in quelle tecnologie. Tendo anche ad abbandonare C come linguaggio per la programmazione regolare - questa sembra essere una scelta ragionevole solo come obiettivo per la generazione di codice, altrimenti è troppo soggetta a errori. Oggi Ada è la mia seconda scelta probabile per progetti più seri, a condizione che io abbia la libera scelta (che, sfortunatamente, non è il caso per la maggior parte del tempo).

Quindi, in altre parole, all'autore di quella citazione piace il C ++, e non gli piace Java, e sente che a Java manca metà del C ++. E questo è tutto quello che c'è da sapere su quella citazione.


18
Ironia della sorte, non gli piace C esattamente la stessa ragione per cui gli piace C ++, è molto aperto, consentendo molta potenza e molti errori.
GreySage,

8
Considera C ++ più espressivo di Python
benxyzzy,

12
@GreySage Anche questo ha attirato la mia attenzione ... C è troppo soggetto a errori ma C # non ti dà abbastanza potenza? C è così lontano dal C ++? C # non ha angoli "non sicuri" che ti danno più controllo? Interessante mix di opinioni che è certo ...
WernerCD

10
@WernerCD non può davvero parlare di C # non sicuro, ma C e C ++ non hanno praticamente nulla in comune, tranne che è possibile battere uno snippet C90 di base in un C ++ valido - snippet su cui il compilatore non si strozzerà.
Quentin,

23

L'articolo collegato al blog che hai pubblicato è stato rimosso, quindi è difficile essere sicuri, ma come dice Kilian, è probabile che quando dice "metà lingua" significa che C # e Java sembrano C ++ ma con un sacco di caratteristiche e costrutti rimossi per renderli più facili da usare o più sicuri.

Nel 2006, quando questo è stato scritto, quando C # era relativamente giovane e Java era in molti modi immaturo, e quando la potenza contro la sicurezza sembrava un compromesso in cui si poteva sceglierne solo uno, questa non era una posizione totalmente irragionevole da prendere .

In questi giorni questa posizione non è affatto ragionevole. Pensando solo ai linguaggi tradizionali, C # e Java sono maturati enormemente, prendendo in prestito funzionalità da altri linguaggi (in particolare funzionali) per promuovere la scrittura di codice sicuro. Abbiamo anche lingue come Rust e Swift che sono state costruite da zero per farlo.

Se qualcuno guarda in basso una lingua perché ti tiene la mano, o dice che una lingua difficile da usare è in qualche modo una buona cosa, prenderei qualsiasi cosa dicessero con un granello di sale. Devi solo guardare al numero imbarazzante di bug trovati nel codice da cui dipendiamo ogni giorno, scritti dalle menti più brillanti del settore, che sarebbero stati banalmente evitati usando linguaggi "sicuri", per capire perché.


6
Sono d'accordo con la tua posizione nell'ultimo paragrafo. Il C ++ dovrebbe essere chiamato "Fountain of Exploits".
Caleb Mauer,

3
Inoltre, a complemento del secondo paragrafo, sia Java che C # hanno pesantemente paralizzato la sintassi C e C ++ per vari motivi, tra cui gli allettanti sviluppatori C / C ++ con la promessa di una curva di apprendimento inferiore. Man mano che sono maturati, hanno aggiunto le loro caratteristiche e il loro sapore, ma agli inizi era più facile vederli come "C ++ ma meno potenti" poiché erano posizionati più direttamente come alternativa al C ++.
Harrison Paine,

12

Guardando indietro agli archivi , sembra che questa citazione risalga al 2003 (nonostante l'articolo che la citasse fosse del 2006). A quel tempo, C # era nella versione 1. x , e mancava molte delle sue funzionalità moderne :

Nuove caratteristiche

C # 2.0

  • Generics
  • Tipi parziali
  • Metodi anonimi
  • iteratori
  • Tipi nullabili
  • Getter / setter accessibilità separata
  • Conversioni di gruppi di metodi (delegati)
  • Co-e contro-varianza per i delegati
  • Classi statiche
  • Inferenza delegata

C # 3.0

  • Variabili locali tipizzate implicitamente
  • Inizializzatori di oggetti e raccolte
  • Proprietà implementate automaticamente
  • Tipi anonimi
  • Metodi di estensione
  • Espressioni di query
  • Espressione lambda
  • Alberi di espressione
  • Metodi parziali

C # 4.0

  • Binding dinamico
  • Argomenti nominati e facoltativi
  • Co-e contravarianza generica
  • Tipi di interoperabilità incorporati ("NoPIA")

C # 5.0

  • Metodi asincroni
  • Attributi delle informazioni sul chiamante

C # 6.0

  • Compilatore-come-un-servizio (Roslyn)
  • Importazione di membri di tipo statico nello spazio dei nomi
  • Filtri di eccezione
  • Attendere blocchi di cattura / finalmente
  • Inizializzatori di proprietà automatiche
  • Valori predefiniti per le proprietà solo getter
  • Membri con espressione corporea
  • Propagatore null (operatore null-condizionale, controllo null sintetico)
  • Interpolazione di stringhe
  • nome dell'operatore
  • Inizializzatore del dizionario

C # 7.0

  • Fuori variabili
  • Corrispondenza del modello
  • Le tuple
  • Deconstruction
  • Funzioni locali
  • Separatori di cifre
  • Letterali binari
  • Restituzioni di riferimento e locali
  • Tipi di ritorno asincroni generalizzati
  • Costruttori e finalizzatori corposi di espressione
  • Getter e setter corposi di espressione

C # 7.1

  • Principale asincrono
  • Espressioni letterali predefinite
  • Nomi di elementi tupla dedotti

- "C Sharp" , Wikipedia (riferimenti e collegamenti rimossi)

È probabilmente più comprensibile che C # sembrasse una mezza lingua in quel contesto, poiché mancava molto di ciò che C # è oggi. È strano pensare che non avesse nemmeno staticlezioni!

Mancavano anche altre cose, dal momento che C # era legato a .NET. Ad esempio, WPF non era in circolazione allora; era tutto WinForms.


le classi statiche possono essere una cattiva scelta di una caratteristica mancante visto che Java non le possiede ancora (il tipo C #). A meno che questo non sia un jab su Java?
user253751

1
@immibis Non è una pugnalata intenzionale a Java, ma, davvero, vero? staticle classi sembrano una caratteristica così primitiva; In un certo senso immaginavo che fossero pre-datate lezioni istanziate.
Nat

2
Sembra dire che i getti del motore a pistoni precedessero i getti del motore a reazione; una "classe non istanziata" è generalmente chiamata modulo o spazio dei nomi , tranne nei linguaggi in cui tutto il codice deve trovarsi all'interno di una classe. (O chiamare una bicicletta un'automobile manuale, o chiamare un telefono fisso un cellulare fisso, o ...)
user253751

@Nat - Avere classi statiche è bello, ma non averle cambia assolutamente nulla. Puoi semplicemente rendere statici tutti i membri della classe e tutto ciò che perdi sono alcuni tipi di errori del compilatore se dimentichi che la classe doveva rimanere statica.
Jirka Hanika,

@JirkaHanika Sì, in ogni caso non sono un grande fan delle staticlezioni. Onestamente l'ho scelto come caratteristica da richiamare perché mi è sembrato una parte davvero semplice e primitiva di C #; Non ho considerato che non fossero in Java.
Nat

3

Si lamentava della mancanza di funzionalità linguistiche che consentissero un controllo approfondito. Questi includono strumenti per

  • Applicazione dell'immutabilità (come la constparola chiave C ++ )
  • Controllo della durata e della proprietà degli oggetti
  • Controllo dell'utilizzo della memoria, della copia e dello stile di allocazione

Questo mi ricorda una delle mie critiche a Java:

tutto è un puntatore, ma i puntatori non esistono.

Negli oggetti C ++, puntatori e riferimenti sono tre concetti distinti con una semantica chiara. In Java hai solo lo pseudo-oggetto-puntatore. Combinando questi e evitando la vera semantica del puntatore, il modello a oggetti è meno chiaro.

In un programma C ++ ben definito il programmatore può aspettarsi che i riferimenti siano validi e non nulli. A causa del suo modello semplificato, Java non può offrire le stesse garanzie.

I sintomi di questo modello meno chiaro includono il modello di oggetti null e i condizionali yoda come 5.equals(potentiallyNullIntegerReference).


5
Questo è molto confuso. Puntatori (nel senso logico esistono in Java) non puoi semplicemente rovinarti. Il punto centrale della semplificazione del modello è consentire maggiori garanzie. La logica che puoi assumere di più sul codice in una lingua avrà meno restrizioni è al contrario. Più restrizioni -> più garanzie.
JimmyJames,

1
@JimmyJames la frase significa che, anche se tutte le classi java hanno una semantica di riferimento implicita (yuck, btw), non puoi avere un puntatore reale. Ad esempio, non è possibile ottenere un "riferimento" a un riferimento. Questo paralizza la lingua in diversi luoghi, a volte richiede soluzioni folli (vedi Map.mergequando vuoi semplicemente aggiornare un valore in una mappa).
Quentin,

3
@JimmyJames: alcuni tipi di garanzie utili non possono essere praticamente offerti senza imporre alcune restrizioni. Inoltre, alcune utili ottimizzazioni potrebbero richiedere l'imposizione di alcune restrizioni. Alcune lingue, tuttavia, impongono restrizioni inutili che non offrono alcuna garanzia utile ai programmatori e non dovrebbero essere necessarie per eseguire utili ottimizzazioni. Alcune restrizioni sono semplicemente sbagliate.
supercat

3
@JimmyJames: D'altra parte, alcune delle restrizioni più fondamentali di Java e C # "modalità provvisoria" consentono loro di offrire una garanzia molto utile che C ++ non può: qualsiasi riferimento (che in C ++ sarebbe un puntatore) che sia mai osservato per identificare un oggetto particolare non sarà mai osservato per identificare nient'altro .
supercat

3
Potete fornire alcune citazioni per supportare la vostra risposta? Ad esempio, AFAIK, la pagina non menziona const. Si fa menzione "programmazione funzionale", tuttavia, il linguaggio che usa come esempio è Scheme, che è non è un linguaggio funzionale puro (in effetti, i progettisti del Piano sono attenti a evitare l'uso della parola "funzione" e parlare " procedure "), quindi sembra che stia usando l'interpretazione" FP di prima classe "di FP e non quella di" trasparenza referenziale ".
Jörg W Mittag,

1

Sono d'accordo con la risposta di @Kilian ma aggiungerò alcuni elementi.

1- In esecuzione su una macchina virtuale non sul sistema operativo

Poiché Java e C # sono in esecuzione su una macchina virtuale, è logicamente prevedibile che non si possa fare esattamente ciò che si desidera quando si è direttamente sul sistema operativo, poiché è probabile che si danneggi qualcosa nella VM. Inoltre, essendo Java orientato come indipendente dalla piattaforma, è ancora più logica.

2- Tonnellate di applicazioni non richiedono che tu abbia bisogno di quel tipo di cose.

Ci sono tonnellate di applicazioni che in realtà non hanno bisogno di te per scavare attraverso molti dettagli, ma se lo fai con una lingua che ti richiede di farlo, ottieni:

  • Più rischi di avere bug a causa di quelle cose inutili.
  • Maggiori costi di sviluppo, gestione della memoria e test richiedono tempo e denaro!

3- La lingua è fatta su una scelta ponderazione costo / utilizzo / rischi, come ... tutto.

Con C ++ puoi fare praticamente quello che vuoi, questa è la scelta delle persone C ++. Tuttavia, più c'è, più è necessario gestire.

Quindi cose come l'ereditarietà multipla non rinunciano solo al fatto che sono pericolose, ma rinunciano perché implementarle ha un costo (sviluppo, manutenzione), tutto per quello per una funzionalità che raramente viene utilizzata correttamente e può generalmente riscritto in modo diverso.


Il costo reale dell'ereditarietà multipla risiede nel fatto che non è possibile mantenere entrambe le seguenti garanzie: (1) Se un membro della classe base Bviene sovrascritto nella classe media M, Bla sua versione sarà accessibile solo attraverso M" s override; (2) dato qualsiasi riferimento di tipo T, convertendolo in qualsiasi super-tipo e viceversa Tprodurrà un riferimento equivalente all'originale. Entrambe queste garanzie sono utili e sostenere l'eredità multipla richiederebbe di rinunciarne almeno una.
Supercat,

-1

Metti semplicemente tutte le restrizioni in linguaggi di alto livello come C # e Java per proteggere il programmatore. Esistono non tanto per proteggere il programmatore da se stesso, quanto piuttosto per proteggere il programmatore da altri programmatori!

Quante volte, come programmatori, incontriamo librerie che erano assolutamente terribili nelle loro pratiche di codifica e progettazione ma che siamo stati costretti a usare per un motivo o per l'altro?

Questi programmi hanno in genere i tratti distintivi del vecchio metodo procedurale di programmazione, con mancanza di incapsulamento, un sacco di scritture di memoria diretta con errori di acquisizione o gestione piccoli o nulli. I Segfault perseguono in massa quando tentano di usarli in qualsiasi progetto su larga scala.

È qui che linguaggi come Java e C # sono estremamente utili; non è che a loro piaccia il fatto che non ci permettono di fare tutte le cose ordinate che fanno altre lingue, è che ci godiamo la mancanza di mal di testa che dobbiamo sopportare perché altri programmatori abuserebbero delle cose ordinate che altre lingue possono fare.

Le interfacce meritano qualsiasi tipo di compromesso in termini di memoria o velocità di esecuzione nella mia mente. Spero che tu possa vedere che in qualsiasi tipo di applicazione mission-critical limitata nel tempo, tutte quelle protezioni, una corretta gestione degli errori e in generale la certezza che la memoria non venga sottratta sono buone cose!


questo non sembra offrire nulla di sostanziale rispetto ai punti formulati e spiegati nelle precedenti 5 risposte
moscerino del

1
They exist not so much to protect the programmer from him/herself, but rather to protect the programmer from other programmers!o è per proteggere altri programmatori dal programmatore?
Tobia Tesan,

@TobiaTesan Anche questo :)
Akumaburn il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.