Dovremmo evitare le funzionalità del linguaggio che ha C ++ ma Java no?


110

Supponiamo che io sia limitato a usare C ++ dall'ambiente nel progetto. È utile impedire l'uso di alcune funzionalità del linguaggio di C ++ ma Java non ha (ad esempio: ereditarietà multipla, sovraccarico dell'operatore)?

Penso che le ragioni siano:

  1. Poiché Java è più recente di C ++, se Java non fornisce una funzionalità di C ++, significa che la funzionalità non è buona, quindi dovremmo evitare di usarla.
  2. Il codice C ++ con funzionalità specifiche di C ++ (ad esempio: funzioni amico, ereditarietà multipla) può essere gestito o esaminato solo dai programmatori C ++, ma se scriviamo semplicemente C ++ come Java (senza funzionalità specifica del linguaggio C ++), il codice può essere gestito o rivisto da entrambi Programmatori C ++ e Java.
  3. Un giorno ti potrebbe essere chiesto di convertire il codice in Java
  4. Il codice senza funzionalità specifiche C ++ è generalmente più gestibile
  5. Ogni caratteristica specifica del linguaggio C ++ (ad esempio: ereditarietà multipla) dovrebbe avere alternative da implementare in Java. In caso contrario, ciò significa che il modello di progettazione o l'architettura del codice è problematico.

È vero?


7
Se guardi i tuoi suggerimenti stai parlando di creare uno standard di codifica. Il fatto che tu stia creando e seguendo uno standard è in realtà ciò che aumenterà la manutenibilità.
Brandin,

63
Il codice Java dovrebbe essere limitato anche alle funzionalità, che si trovano anche in linguaggio C ++? Quindi non usare ad esempio Java volatile, l'accesso ai membri della classe pacchetto-privato, reflection / introspection, finally-block, eccezioni controllate e così via? L'intera domanda non ha molto senso ... C ++ e Java sono superficialmente simili, ma alla fine linguaggi molto diversi.
hyde,

5
Come si evolvono le lingue se le persone non sono disposte a usare nuove funzionalità? Lo scopo delle nuove funzionalità è di semplificarti la vita risolvendo problemi comuni. Se gli utenti non utilizzano nuove funzionalità, non c'è motivo per nessuno di implementarle.
Matteo

72
Se vuoi Java, usa Java. Se usi C ++, usa C ++, non un'imitazione orribile e distorta di Java con sintassi C ++. L'uso del C ++, ma limitandoti al set di funzionalità di Java, ti dà il peggio di entrambi i mondi.
Jerry Coffin,

11
Saresti sorpreso da quanto velocemente le differenze ti morderanno (e duramente ). SomeObject a = previousObject;fa cose molto diverse in Java e C ++. In Java copia un riferimento, mentre in C ++ copia l'oggetto. In Java, le modifiche a ainteresserebbero anche l'oggetto precedente. In C ++, hai due oggetti separati.
Clockwork-Muse

Risposte:


307

No. Questo è terribilmente e terribilmente fuorviato.

  • Le funzionalità Java non sono in qualche modo migliori delle funzionalità C ++, specialmente nel vuoto.
  • Se i programmatori non sanno come utilizzare una funzione, formare o assumere sviluppatori migliori; limitare i tuoi sviluppatori al peggio del tuo team è un modo semplice e veloce per perdere i tuoi bravi sviluppatori.
  • YAGNI . Risolvi il tuo vero problema oggi, non il fantasma di qualche problema futuro.

6
Recentemente è stata posta una domanda sugli sviluppatori che esaminano il codice in una lingua che normalmente non scrivono. Penso che la saggezza si applichi qui: un buon sviluppatore individuerà molti errori di base in quasi tutte le lingue, ma ogni lingua ha così tante gotchya che si ottiene il massimo beneficio quando gli sviluppatori in lingua fanno la revisione. Questo è vero anche se il tuo C ++ è "solo funzionalità Java".
corsiKa

5
+1 Oltre al secondo punto. L'OP dovrebbe impiegare del tempo per leggere le "Best Practices in C ++" per decidere quali funzionalità dovrebbero usare. Le mie ultime informazioni su C ++ sono che le funzioni degli amici e l'eredità multipla sono considerate cattive pratiche . Cose come i modelli e il sovraccarico dell'operatore sono buone pratiche IMHO se le usi saggiamente.
some_coder il

4
@some_coder: è tutta una questione di sapere quando e dove. Quando eseguo una programmazione basata su criteri, eredito dalle (eventualmente più) classi politiche per estendere la struttura della mia classe host con i membri che tali classi politiche richiedono per funzionare. È proprio come funziona. Inoltre, operator<<( ostream &, T const & )viene solitamente implementato tramite friend. Questo è il problema con le affermazioni generali su ciò che è una buona caratteristica del linguaggio e che è una cattiva: sono buoni consigli, tranne quando non lo sono ...
DevSolar,

142

Solo perché la sintassi sembra simile in superficie non significa che le due lingue siano compatibili.

1, 4 e 5 sono davvero la stessa domanda:

Ora, non sono un fan di C ++, ma dire "Il codice senza funzionalità specifiche di C ++ è di solito più gestibile" è semplicemente ridicolo: credi davvero che Java abbia fatto tutto bene e abbia preso tutte le buone funzionalità ignorando tutte quelle cattive? Credi davvero che ci sia qualcosa che è universalmente una funzionalità "cattiva" o "buona"? Se c'è, perché non abbiamo una lingua puramente buona? E no, Java certamente non è quella lingua. Ciò significa che Java e C ++ sono inutili? Ovviamente no.

Cosa succede se i tuoi leader decidono che stai per eseguire il port su C #, piuttosto che su Java? Non solo C # supporta gli operatori prioritari, ma è anche l'impostazione predefinita: se hai bisogno che le persone usino, ad esempio, obj.Equals(obj2)invece di obj == obj2, le persone commetteranno continuamente errori. Anche se si mantengono solo le caratteristiche comuni delle due lingue, ci sono aspettative diverse , una cultura diversa. Se fai qualcosa come if (myField == null)C ++, le persone vedranno immediatamente che sei un principiante. Se usi if (null == myField)in C #, le persone vedranno che non sei ancora veramente C # nativo - i motivi per cui gli sviluppatori C hanno imparato a usare la variante "capovolta" non esistono più in C #.

Usando la tua logica, avremmo dovuto rimanere bloccati con il codice macchina o assembly o COBOL, perché perché mai cambiare in qualcosa come Pascal, quando aggiunge solo nuove funzionalità che i tuoi programmatori dovranno imparare? Perché dovremmo mai usare qualcosa come SQL, quando non ha nemmeno dei loop ? Perché dovremmo mai usare qualcos'altro oltre a SQL, quando SQL non ha loop e X lo fa?

Il codice C ++ non può certamente essere gestito dai programmatori Java. Non riesco a capire da dove sia venuta questa idea: cosa rimane esattamente quando limiti C ++ solo alle funzionalità che funzionano esattamente come in Java? Non riceverai nemmeno chiamate di metodo, nemmeno chiamate di funzione . Ancora una volta, solo perché entrambi i linguaggi usano parentesi graffe, ciò non significa che le lingue siano in alcun modo intercambiabili.

La conversione di codice C ++ simile a Java sarà estremamente soggetta a errori, qualunque cosa tu faccia. Ci sono troppe differenze. Se ti interessa dover riscrivere la tua applicazione in una lingua diversa, pensa a modi ragionevoli di modularizzare tutto, in modo da poter sostituire le parti senza rompere il tutto. Ma alla fine, YAGNI - qualunque cosa tu faccia, ci sarà un costo significativo per rendere il tuo codice "pronto per la conversione in Java". È molto probabilmente molto meglio spendere tempo per aggiungere o migliorare le tue funzionalità.

Usiamo lingue diverse perché ci forniscono una serie diversa di strumenti per risolvere i problemi. Se hai bisogno di eseguibili che funzionano "ovunque", vai con Java. Se vuoi un codice che compili "ovunque", C ++ funziona bene. Se vuoi un codice che sia facile da capire e da analizzare, scegli LISP o altro. Ma posso dirti una cosa: scrivere codice in una lingua come se lo stessi scrivendo in un'altra è sempre un errore, e soffrirai. Per non parlare del fatto che quando assumi effettivamente un ragazzo C ++, eseguirà il secondo in cui vede quel codice "Java-ish compatibile". E ... il ragazzo Java farà lo stesso. Sai, anche "conoscendo" sia C ++ che Java, correrei da morire :)

In realtà ho dovuto lavorare sul (semplice) codice C scritto da uno sviluppatore Pascal che sembrava pensare come te. Ha usato #defines per ridefinire C per sembrare e sembrare più simile a Pascal, completo di cose come "BEGIN si traduce in {". Il risultato è stato piuttosto prevedibile: codice che né gli sviluppatori C né Pascal sono in grado di comprendere, e pieno di bug che sono stati il ​​risultato della "astrazione" che perde di Pascal in cima a C. E Pascal e C sono quasi identici dal punto di vista di oggi. Anche andare in C <-> C ++ è molto più di una differenza, e questo è ancora noccioline a qualcosa come C ++ <-> Java.


9
"Se vuoi un codice che sia facile da capire e da analizzare, scegli LISP o altro." Non sarei d'accordo con quello. Lisp è banale da analizzare, ma proprio per questo - perché è stato creato in un'epoca in cui la conoscenza dei parser e i principi alla base della loro costruzione effettiva era ancora agli inizi, e quindi hanno puntato e sono andati con la cosa più ridicolmente semplicistica ciò potrebbe funzionare: non si ottengono molti vantaggi sintattici delle lingue moderne. Quindi è facile da analizzare, ma per niente facile da capire . C'è un motivo per cui la gente lo chiama "Perso tra parentesi superflue".
Mason Wheeler,

9
@MasonWheeler È una questione di gusti - i programmatori C lo chiamavano così, non LISPers: P. Conta le parentesi: ce ne sono molte quante nel tuo tipico programma C ++. La vera differenza è la loro posizione ( myFunc()contro (myFunc)), e questo ha un'ottima ragione. I linguaggi basati su LISP sono ancora molto popolari, specialmente con le persone di matematica / fisica. La cosa principale è che i linguaggi LISPy non hanno molta familiarità con i moderni programmatori in stile C, ma questo non è certo un motivo per ignorarlo. Schema, Clojure e, in una certa misura, le lingue basate su ML (OCaml, F # ...) sono davvero LISPy.
Luaan,

4
@Luaan Posso dirti con certezza che LISP NON è popolare in fisica. Le due lingue dominanti nel campo sono FORTRAN e C ++. FORTRAN è "popolare" perché in esso sono stati scritti tanti vecchi codici, ma quasi tutti i nuovi programmi sono scritti in C ++. Come fisico di ricerca, non ho mai incontrato o sentito parlare di un programma LISP. Per non dire che non esistono, ma le lingue non sono sicuramente popolari .
James Matta,

4
@Luaan Potremmo aver bisogno o meno di altri sviluppatori software. Sicuramente non abbiamo bisogno di più laureati in CS. È come dire "abbiamo bisogno di più ingegneri strutturali, quindi abbiamo bisogno di più laureati in fisica teorica".
Miles Rout,

4
@ user1717828 È per evitare i deliziosi effetti del mistyping if (myField == null)come if (myField = null), che compilerà semplicemente C / C ++, ma probabilmente non farà ciò che intendevi. D'altra parte, if (null = myField)genererà un errore, poiché non è possibile assegnare a una costante.
Wlerin,

94

Risponderò alle tue domande in ordine.

  1. Se Java non fornisce una funzionalità di C ++, significa che la funzionalità non è buona, quindi dovremmo impedirne l'utilizzo.

Sì, qualsiasi funzione non presente in Java è un anatema sul disco rigido. Deve essere masterizzato dalla tua base di codice. Coloro che non obbediranno saranno sradicati, le loro anime erano solite placare gli dei RAID.

  1. Il codice C ++ con funzionalità specifiche di C ++ (ad esempio: funzioni amico, ereditarietà multipla) può essere gestito o esaminato solo dai programmatori C ++, ma se scriviamo semplicemente C ++ come Java (senza funzionalità specifica del linguaggio C ++), il codice può essere gestito o rivisto da entrambi Programmatori C ++ e Java.

In caso di dubbi, scrivi il codice per il membro meno competente della tua squadra. Il codice viene letto molto più spesso di quanto sia scritto e il codice più intelligente che puoi scrivere è troppo intelligente per essere letto. Le recensioni di codice che il personale della reception non capirà dovrebbero essere respinte. Per aiutare, insegna loro come programmare in Visual Basic 2.0 nel fine settimana, quindi emula il loro stile di programmazione in qualunque lingua tu stia usando.

  1. Un giorno ti potrebbe essere chiesto di convertire il codice in Java

Vero! Ma perché fermarsi a Java? È possibile che ti venga richiesto di convertire il codice in basic, assembler e / o perl un giorno. Dato che ci sono interpreti perl in ogni lingua là fuori, scrivi semplicemente il tuo programma come una lunga stringa perl e metti in campo gli argomenti nella lingua scelta.

Ora, quando è necessario cambiare lingua, è sufficiente riscrivere il codice che avvolge la stringa perl.

  1. Il codice senza funzionalità specifiche C ++ è generalmente più gestibile

È vero che il codice che utilizza meno funzionalità è più facile da mantenere. E poiché tutti i linguaggi sono equivalenti a una Turing Machine e una Turing Machine ha il minor numero di funzioni rispetto a qualsiasi linguaggio di programmazione, l'interprete perl di cui sopra esegue effettivamente una Turing Machine (nastro e tutto) che risolve il problema.

  1. Ogni caratteristica specifica del linguaggio C ++ (ad esempio: ereditarietà multipla) dovrebbe avere alternative da implementare in Java. In caso contrario, ciò significa che il modello di progettazione o l'architettura del codice è problematico.

Le funzionalità specifiche del linguaggio C ++ hanno effettivamente un uso prezioso. Dato che non sono Java, sono anatemi e coloro che lo usano possono essere etichettati come marchi. Se il C ++ non avesse quelle caratteristiche del linguaggio, non saresti in grado di trovare quelle che devi sacrificare. Le funzionalità del linguaggio C ++ risolvono i problemi!


Guarda, C ++ e Java hanno un diverso set di funzionalità. La programmazione nell'intersezione di C ++ e Java comporta un codice che ha eliminato la maggior parte dei vantaggi di entrambi i linguaggi.

Java è stato sviluppato in parte come reazione ad un abuso delle funzionalità C ++. Ciò non significa che la reazione sia stata giustificata, soprattutto anni dopo, quando le caratteristiche sono maturate.

Puoi fare cose orribili con il sovraccarico dell'operatore; ma nessuna lingua può impedire che un codice orribile venga scritto nella lingua, a meno che non impedisca che tutto il codice venga scritto nella lingua.

E puoi anche fare cose molto eleganti con il sovraccarico dell'operatore. Cose semplici, come un numero complesso o una classe matrice che funziona come un numero complesso o una matrice.

Le precauzioni sull'uso delle funzionalità C ++ non disponibili in Java devono essere visualizzate con cautela. Solo perché il tuo attuale set di sviluppatori al loro attuale livello di abilità non capisce una caratteristica non significa che non dovrebbe mai essere usata; allo stesso tempo, solo perché puoi usare una funzione, non significa che dovresti. Tuttavia, in un negozio pesante di Java, le probabilità sono che la resistenza sarà più forte di quanto dovrebbe essere contro le caratteristiche non Java-esque.

La conversione del codice tra le lingue viene eseguita al meglio con una riscrittura, indipendentemente da quanto siano strutturalmente simili. Qualsiasi tentativo di farlo senza una tale riscrittura fallirà miseramente.

Molte funzionalità specifiche di C ++ sono prodigi per la manutenzione. La cancellazione del tipo (come std::function) consente di disaccoppiare le gerarchie, riducendo le dipendenze. Puntatori intelligenti, tempi di vita deterministici e RAII riducono le sorprese in fase di esecuzione e allontanano la piastra di controllo delle risorse. Controlli statici pesanti indicano che la compilazione del codice non riesce, invece di non funzionare. I mix-in riducono la duplicazione del codice. ADL consente l'estensione indipendente ad hoc delle interfacce tra gerarchie di tipi. Lambda ti consente di scrivere il codice accanto a dove viene utilizzato. L'inoltro e lo spostamento riducono le copie e rendono efficiente la programmazione in stile funzionale (senza effetti collaterali). Il sovraccarico dell'operatore riduce il rumore di linea e rende il codice più simile alla matematica che sta modellando.

Fai attenzione alla fossa di Turing Tar. Puoi implementare tutto in qualsiasi lingua (inclusa una Turing Machine grezza con nastro), ma ciò non significa che dovresti . Emulare funzionalità C ++ usando costrutti Java-esque in C ++ è un'idea orribile; si tradurrà in un codice non mantenibile che nessuno può leggere o comprendere.

Puoi trarre ispirazione dai progetti Java e portarli su C ++. Sono un grande fan di prendere le funzionalità del linguaggio Python e di implementarle in C ++, perché mi piace la sintassi. Ma ciò non significa che scrivo i miei metodi di classe come metodi statici prendendo un sé esplicito, quindi scrivo un wrapper che inoltra ad esso la chiamata del metodo non statico.

Il C ++ moderno non è molto simile al linguaggio emulato e rifiutato da Java. Non essere bloccato dalle funzionalità di una lingua; non esiste un "unico vero linguaggio". Scopri nuove lingue e le loro caratteristiche e assorbi il loro carattere distintivo.


1
-1, prolisso e poco chiaro.
Djechlin,

4
-1 argomento
polemico

28
+1, corretta decostruzione delle domande poste e ho riso :)
cat

11
+1. Divertente ma mantiene il punto. Molto chiaro per le persone che lo leggono.
Luis Masuelli,

14
"La programmazione nell'intersezione di C ++ e Java ha come risultato un codice che ha eliminato la maggior parte dei vantaggi di entrambi i linguaggi." Colpire nel segno! +1
Ajedi32

56

Risponderò alle tue ragioni:

  1. Non capisco come arrivi a questa conclusione. Lingue diverse hanno caratteristiche diverse. Dipende dall'ambito, dall'architettura del linguaggio, a volte dalle preferenze dei creatori e da molte altre ragioni. Alcune caratteristiche di una lingua possono essere cattive, ma la tua generalizzazione è chiaramente IMHO errata.
  2. Scrivere C ++ proprio come Java può portare a un codice peggiore. Ad esempio, al giorno d'oggi con C ++ 11, evito di usare new / delete, ma uso puntatori condivisi. Nel tuo scenario farei affidamento solo su nuovo / elimina. Se i tuoi programmatori comprendono solo Java, allenali o assumine di migliori.
  3. Probabilmente succederà? Perché non scrivi in ​​Java in primo luogo? Penso che riscrivere i programmi da zero in una nuova lingua sia generalmente una cattiva idea e avresti bisogno di una giustificazione davvero buona per un tale rischio.
  4. Questo è solo un presupposto.
  5. Dipende fortemente da IMHO sullo scenario o sul caso d'uso.

27
E deleteneanche i programmatori Java lo userebbero .
Paŭlo Ebermann,

8
Ho dovuto riparare le perdite di memoria causate dai programmatori Java che non lo sapevano delete. Da quello che ricordo, in almeno uno di questi casi, newneanche l' allocazione dinamica ( ) era necessaria.
Ethan Kaminski,

16
@EthanKaminski Sì, è così che puoi facilmente individuare un principiante C ++, in particolare qualcuno che proviene da un background Java o simile. Smetti di usare il nuovo per tutto, dannazione!
Luaan,

1
@ PaŭloEbermann Sì, anche peggio.
Simon,

1
"Nel tuo scenario farei affidamento solo su new / delete" - divertente, avrei pensato che un linguaggio C ++ "solo funzioni simili a Java" sarebbe da usare esclusivamente make_shared.
Kyle Strand,

26

Java ha caratteristiche che C ++ non ha, come un garbage collector integrato, veloce e affidabile, una gerarchia di oggetti a radice singola e una potente introspezione.

Le altre funzionalità di Java sono progettate per funzionare insieme alle funzionalità esclusive di Java e molte delle omissioni di Java di funzionalità C ++ sono possibili perché le nuove funzionalità compensano la mancanza. Ad esempio, Java non ha oggetti allocati in pila con distruttori deterministici, ma ha finalmente blocchi (e prova con risorse da Java 7) e il Garbage Collector per compensare questa mancanza.

C ++ non ha finalmente blocchi o garbage collection. Se non usi i distruttori perché non esistono in Java (non conto i finalizzatori), sei al livello C della gestione delle risorse (cioè tutto il manuale), tranne per il fatto che non puoi nemmeno raggruppare la pulizia in un blocco di pulizia a cui vai, perché Java non ha neanche goto. Pensi davvero che migliora la manutenibilità?

Java ha una gerarchia di oggetti generale in cui ogni classe deriva in ultima analisi da Object, e anche i pochi tipi primitivi possono essere inseriti automaticamente in tali classi. Ciò consente di scrivere contenitori di oggetti una volta, per contenere i puntatori a Object. Java 5 ha introdotto i generici, che eliminano i cast richiesti da tali contenitori, ma si compilano ancora più o meno nello stesso codice.

C ++ non ha una tale gerarchia. Per facilitare la scrittura di contenitori che funzionano per più tipi, si utilizzano modelli, che sono progetti che vengono istanziati dal compilatore in base alle necessità per tipi diversi. Proibirai l'uso di modelli (e macro) e seguirai il percorso C scrivendo lo stesso codice contenitore più e più volte per tipi diversi o usando i puntatori vuoti? (Aspetta, Java non ha puntatori vuoti!) Sei sicuro che ciò aumenterebbe la manutenibilità?

Un linguaggio decente ha una moltitudine di funzioni progettate per lavorare insieme. Vietando le funzioni dalla lingua A perché la lingua B non le possiede, stai paralizzando la lingua A, perché non stai allo stesso tempo aggiungendo funzionalità dalla B che rendono B un tutto coerente.

Questo non vuol dire che non devi limitare le funzionalità consentite di C ++. Il C ++ è un grande linguaggio storicamente sviluppato che enfatizza il consentire al programmatore di fare ciò che desidera in termini di sicurezza e facilità d'uso, e non tutte le sue caratteristiche in tutta la sua flessibilità sono necessarie per costruire buoni programmi. Esistono molti standard di codifica che limitano l'uso di alcune funzionalità; ad esempio, le linee guida di Google vietano principalmente l'ereditarietà multipla, i modelli complessi e le eccezioni (anche se l'ultimo è per motivi storici). Ma nessuna funzionalità è vietata "perché Java non ce l'ha"; le funzionalità sono considerate nell'ambito del solo C ++.


27
I veterani esperti di C ++ di solito rifiutano le linee guida per la codifica di Google. Il C ++ moderno è di gran lunga migliore proprio perché utilizza queste funzionalità. Sì, lo rende ancora più diverso.
Jan Hudec,

17
Nota che C ++ non ha finalmente i blocchi, ma ha RAII, che è molto meglio nella maggior parte dei casi. E, ancora, diverso.
Jan Hudec,

7
Java Objectè praticamente un void*per la maggior parte degli usi - Ancora, schifo.
Quentin,

1
Oltre alla scelta delle funzionalità, c'è la questione dello stile e del linguaggio. I programmi sono generalmente più facili da leggere e mantenere se usano i normali modi di dire per la lingua in cui sono stati scritti. Anche se si potesse scrivere una parte di un programma C ++ usando solo funzioni simili a Java, il risultato sarebbe strano, C ++ su palafitte.
Patricia Shanahan,

2
Vorrei votare questa risposta per essere sulla strada giusta ("non farlo"), ma non sopporto la premessa di base che Java sia in qualche modo "più avanzato" del C ++. C ++ non ha bisogno di un garbage collector o di una gerarchia di oggetti a radice singola, allo stesso modo in cui Java non ha bisogno di ... err ... mi dispiace non so come finire la frase, perché mi mancano distruttori deterministici in Java, e finallynon è un sostituto per loro. Le due lingue sono sostanzialmente diverse.
DevSolar,

25

Ho discusso se preoccuparmi di pubblicare un'altra risposta quando hai già un numero che raggiunge quelle che sembrano essere conclusioni del tutto ragionevoli: la tua idea è fondamentalmente un disastro in attesa di accadere. Penso, tuttavia, che non siano riusciti a sottolineare alcune ragioni altamente rilevanti alla base di tale conclusione.

Le differenze tra Java e C ++ sono molto più profonde dei dettagli su cui sembra che tu ti sia concentrato.

Ad esempio, si parla di proibire l'ereditarietà multipla in C ++. In primo luogo, farò notare che questo non è semplicemente il punto. Java definisce "interfacce" come cose separate da "classi". Una classe eredita da un'altra classe, ma può implementare un numero arbitrario di interfacce.

C ++ non separa i due concetti in questo modo. L'analogo C ++ vicini fornisce ad attuare un'interfaccia in Java è eredita da un'altra classe. Pertanto, per mantenere i due allineati ragionevolmente bene, è probabilmente necessario utilizzare l'ereditarietà multipla in C ++, ma si desidera limitare alcune di quelle classi base in modo approssimativo allo stesso modo in cui Java limita un'interfaccia rispetto a una classe (ovvero, essenzialmente che specifica le firme delle funzioni ma, almeno per lo più, non le implementazioni).

Questo a malapena sta graffiando la superficie delle reali differenze tra i due. In realtà, dove è probabile che il codice Java definisca le interfacce e le classi che implementano tali interfacce, è molto più probabile che il codice C ++ definisca alcuni modelli che funzioneranno con qualsiasi classe che soddisfi i suoi requisiti (non solo quelli definiti specificamente per implementare l'interfaccia (s) specifica).

Se onestamente vuoi un codice che è fondamentalmente "Java che utilizza la sintassi C ++", dovrai quasi sicuramente vietare qualsiasi cosa simile a quest'ultima. Dovrai limitare l'uso dei modelli a circa il livello di "contenitore di T" supportato dai generici Java. Sfortunatamente, ciò comporterà un codice C ++ che è un tale casino che nessuno può mantenerlo come esiste ora, per non parlare della possibilità a lungo termine di tradurlo in qualche altro linguaggio di programmazione.

Se vuoi davvero il codice che può essere convertito in un'altra lingua in futuro, cerca di renderlo il più pulito e leggibile possibile. L'ideale è scrivere pseudo-codice e farlo eseguire ancora. Approcci C ++ moderni ben scritti che idealizzano molto più da vicino del sottoinsieme che hai suggerito. Non importa come lo scrivi, se mai traduci in Java, dovrai effettivamente tradurre il codice, non solo la sintassi delle singole istruzioni.


Molte funzionalità di C ++ possono essere utilizzate in alcuni modi che si adattano perfettamente ai concetti di Java e altri che non lo fanno. Alcune parti di un programma richiedono qualcosa al di fuori del sottoinsieme sovrapposto della funzionalità dei linguaggi, e il tentativo di scrivere parti come "Java usando la sintassi C ++" produrrà un casino orribile. D'altra parte, molte altre parti del codice potrebbero aver bisogno di qualcosa al di fuori del sottoinsieme condiviso, e provare a rimanere all'interno del condiviso per quelle parti del codice in cui non c'è motivo convincente per uscire al di fuori di esso potrebbe essere utile.
supercat

Presumibilmente dove dici "potrebbe aver bisogno", intendi davvero: "potrebbe non aver bisogno"? Supponendo di sì, allora tenderei ad essere d'accordo.
Jerry Coffin,

Sì. Se diventa necessario supportare una piattaforma che supporta Java ma non C ++, quasi sicuramente parti del codice dovranno essere riscritte da zero e non importa se quelle parti sono state scritte usando alcune tecniche compatibili con Java, dal momento che ' Verrò riscritto comunque. Potrebbe essere possibile scrivere altre parti, tuttavia, in modo da consentire la migrazione senza una riscrittura completa e, in alcuni casi, il costo aggiuntivo necessario per farlo potrebbe essere minimo.
supercat

4
@supercat: OTOH, dato il numero di piattaforme che supportano Java ma non C ++, questo mi sembra quasi una soluzione alla ricerca di un problema.
Jerry Coffin,

Per un po ', il supporto del browser per le applet Java era migliore rispetto alle applet C ++. Il supporto del browser per JavsScript (nessuna relazione con Java), tuttavia, è migliorato abbastanza da essere sostanzialmente sostituito da entrambi.
supercat

11

Se hai intenzione di scrivere codice in lingua X, trascorri il tempo per imparare correttamente la lingua e utilizzare tutte le funzionalità offerte per aiutarti a risolvere il problema. Le cose brutte accadono quando provi a fare una traduzione "parola per parola" da una lingua all'altra, che sia dal giapponese all'inglese o da Java al C ++. È molto meglio iniziare con una buona comprensione del problema ed esprimere la soluzione nel modo più naturale per la lingua utilizzata.

Anni fa ho visto un programma C che non aveva alcun rientro e ogni affermazione era iniziata nella colonna 7, perché l'autore del codice era un programmatore Fortran che utilizzava C. Altri programmatori Fortran erano nervosi per queste nuove cose chiamate puntatori. Non avevo il coraggio di menzionare i puntatori ai puntatori, penso che sarebbero svenuti sul posto.

Immagina di assumere qualcuno per mantenere questo codice in futuro. Se è un buon codice C ++, sarai in grado di assumere uno sviluppatore C ++ competente e dovrebbero essere in grado di orientarsi. Se è "Java in C ++", né gli sviluppatori C ++ né Java potranno facilmente comprendere il codice.


7

Tutti i tuoi motivi possono essere confutati:

Se Java non fornisce una funzionalità di C ++, significa che la funzionalità non è buona, quindi dovremmo impedirne l'utilizzo.

Ciò non significa che la funzionalità non sia buona (nessuna funzionalità può essere intrinsecamente negativa). Significa solo che la funzione è stata spesso utilizzata in modo improprio (o impossibile da implementare a causa di concetti fondamentali, come i puntatori diretti contro la garbage collection). Java per definizione mira a essere più facile e più adatto ai programmatori, quindi la rimozione di funzionalità che si sono dimostrate facilmente abusabili.

Il codice C ++ con funzionalità specifiche di C ++ (ad esempio: funzioni amico, ereditarietà multipla) può essere gestito o esaminato solo dai programmatori C ++, ma se scriviamo semplicemente C ++ come Java (senza funzionalità specifica del linguaggio C ++), il codice può essere gestito o rivisto da entrambi Programmatori C ++ e Java.

Oh può essere? Vediamo il codice C ++ più semplice:

int len = mystring->size();

Spiacenti, non è stata utilizzata alcuna funzionalità "specifica della lingua", ma non è ancora raggiungibile dagli sviluppatori Java! Perché in Java dereference con "." mentre qui è "->.

Un giorno ti potrebbe essere chiesto di convertire il codice in Java

O C #. O Haskell. O Python. O Ruby. O COBOL (sì, puoi!). Come puoi dire al futuro?

Il codice senza funzionalità specifiche C ++ è generalmente più gestibile.

Esatto contrario. Ogni funzione è stata introdotta per rendere la programmazione più semplice e quindi più gestibile. Ad esempio: prendere un programma che funziona su float. Ora aggiornalo per gestire numeri complessi. Operatore sovraccarico in soccorso!

Ogni caratteristica specifica del linguaggio C ++ (ad esempio: ereditarietà multipla) dovrebbe avere alternative da implementare in Java. In caso contrario, ciò significa che il modello di progettazione o l'architettura del codice è problematico.

Ma Java ha eredità multiple! Si chiama "interfaccia". L'implementazione Java è una soluzione problematica per evitare il temuto diamante causato dal fatto che tutto derivi Object. Viene fatto introducendo interfacequale unico scopo è essere qualcosa da cui non deriva Object. Il C ++ non ha mai avuto questo problema: non esiste una base comune obbligatoria, quindi ogni classe può funzionare come interfaccia senza il temuto diamante.

Nota a margine: Java ha recentemente introdotto ... metodi concreti nelle interfacce. Aggiunta una funzionalità che C ++ ha sempre dovuto risolvere un problema che non c'era mai.

Hai anche menzionato solo pochissime "cose ​​che C ++ ha ma Java no". Una delle maggiori differenze tra C ++ e Java è il controllo sul layout della memoria. È possibile creare una serie di puntatori agli oggetti (proprio come in Java) O è possibile creare blocchi di memoria contigui. Ora, se dovessi preoccuparmi di una funzionalità C ++ che potrebbe fuorviare gli sviluppatori Java, qualcosa di così nascosto e sottile come questo sarebbe nella mia lista molto più in alto di quanto ovvio e riconoscibile a prima vista cose come eredità multipla o operatori sovraccarichi.

In conclusione: il codice pulito è un codice pulito. Java o C ++ - stessa differenza. Mantienilo semplice. Le complicazioni inutili sono la principale causa di codice errato.


Java offre alcune funzionalità e garanzie che sarebbero insopportabili in un linguaggio che offre tutte le funzionalità di C ++. Un linguaggio non può, ad esempio, consentire il caricamento di tipi dinamici e l'intera gamma di cast di Java che preservano l'identità, offrendo al contempo le forme generalizzate di ereditarietà multipla incluse in C ++.
supercat

@supercat Non capisco perché lo dici qui. La domanda non riguarda le funzionalità Java che non possono essere riprodotte in C ++, ma le funzionalità C ++ che Java ha scartato.
Agent_L

Il mio punto è che alcune funzionalità di Java non sono incluse in C ++, ma piuttosto che alcune funzionalità di Java sono fondamentalmente incompatibili con altre funzionalità incluse in C ++, in modo tale che nessun linguaggio possa avere tipi che supportano entrambi (linguaggi come C ++ / CLI hanno tipi che supportano le funzionalità C ++ e tipi che supportano le funzionalità Java-ish, ma abitano effettivamente in universi separati con interoperabilità limitata).
supercat

6

No, generalmente non dovresti scrivere C ++ come se fosse Java e non dovresti assolutamente omettere le funzionalità del linguaggio C ++ che non sono presenti in Java.

Per prima cosa, Java viene raccolto in modo inutile e quindi non ha un equivalente della parola chiave "elimina" C ++. Va bene, quindi implementate un programma senza cancellare, perché secondo le vostre regole, non è permesso.

Congratulazioni, ora hai una perdita di memoria;). Neanche questo è teorico - ho visto accadere esattamente questa situazione in un gioco open source.

Allo stesso modo, Java non ha nulla di simile ai puntatori C ++, che esclude molte convenzioni di chiamata di funzioni comuni.

Ci sono funzionalità di C ++ che dovresti forse evitare (vedi sotto), ma "non essere in Java" non è un buon tornasole.


Linee guida migliori sarebbero le seguenti:

  1. Scrivi il codice appropriato per la tua lingua, ambiente e strumenti.
  2. Scrivi un codice comprensibile per il tuo team .
  3. Assicurati che il tuo team sia competente nel dominio specificato.

Item (3) significa che non dovresti avere il codice dei programmatori Java in C ++ senza averli addestrati in C ++. Ci sono alcune differenze sottili ma molto importanti che potrebbero non imparare se stanno cercando di trattarlo come uno strano dialetto di Java.

L'articolo (2) significa che, se la tua squadra è a disagio con l'ereditarietà multipla (ad esempio) e se esiste una soluzione adeguata che non la utilizza, allora potrebbe essere meglio usare quella soluzione alternativa. Tuttavia, questo dipende in particolare dalla tua squadra. D'altra parte, se la tua squadra è più a disagio con quella soluzione alternativa che con l'ereditarietà multipla, usa l'ereditarietà multipla!


Infine, ci sono funzionalità linguistiche di C ++ che, probabilmente, si dovrebbero evitare. Se vuoi sapere cosa sono, chiedi ai programmatori C ++ , piuttosto che ai programmatori di una lingua diversa. Alcuni esempi con cui iniziare sono l' aritmetica del puntatore (nessun consenso universale) e goto.


6

Ci sono già alcuni punti positivi in ​​altre risposte, ma vorrei fornire una risposta più completa, rispondendo alle vostre domande e dichiarazioni singolarmente.


Se Java non fornisce una funzionalità di C ++, significa che la funzionalità non è buona, quindi dovremmo impedirne l'utilizzo.

La risposta è stata abbastanza buona: Java non è "la parte buona" di C ++, né c'è motivo di pensarlo.

In particolare, sebbene i meriti di ogni singola caratteristica C ++ siano discutibili, molte delle caratteristiche di C ++ 11 / C ++ 14 che non fanno parte di Java non sono necessariamente escluse perché i progettisti Java pensavano che fossero una cattiva idea. Ad esempio, fino alla versione 8, Java non aveva lambda, ma erano stati introdotti in C ++ nello standard C ++ 11. Prima di Java 8, il tuo presupposto che le funzionalità C ++ mancanti da Java mancassero dal punto di vista della progettazione perché "non buone" avrebbero implicato che lambdas come funzionalità del linguaggio non fosse "buono" (con orrore dei LISPer ovunque, sebbene siano probabilmente abbastanza inorridito da sentire che apparentemente in realtà ti piace Java). Ma ora i designer Java hanno messo il loro Stamp of Approval (TM) su lambdas, quindi ora sono una buona cosa.

Per scavare un po 'più a fondo, anche in Java 8, le lambda come chiusure non sono flessibili come le lambde di C ++ 14, ma ciò potrebbe essere dovuto alle limitazioni dell'architettura JVM piuttosto che alla decisione consapevole che l'approccio più flessibile è negativo da un prospettiva di progettazione del linguaggio.


Il codice C ++ con funzionalità specifiche di C ++ (ad esempio: funzioni amico, ereditarietà multipla) può essere gestito o esaminato solo dai programmatori C ++, ma se scriviamo semplicemente C ++ come Java (senza funzionalità specifica del linguaggio C ++), il codice può essere gestito o rivisto da entrambi Programmatori C ++ e Java.

Questa è la cosa principale a cui volevo rispondere.

In linea di massima, potrebbe essere utile ottenere revisioni del codice da programmatori che non hanno familiarità con la lingua che si sta utilizzando. Possono darti un prezioso feedback sulla chiarezza dei nomi e dei commenti della funzione / metodo e (come implica correttamente la tua domanda) se la lingua è simile a una o più lingue che già conoscono, potrebbero essere in grado di seguire il flusso del programma di base e potenzialmente rilevare errori logici.

Tuttavia, non è possibile che questo tipo di recensione sia mai "valida" o "equivalente a" recensione di sviluppatori che conoscono effettivamente la lingua che stai utilizzando. In sostanza, questo è perché fare una lingua sguardo come un altro in genere nascondono sottili differenze, pur facendo una lingua si comportano come un altro (in particolare nel caso di C ++ e Java) possono essere un-idiomatica della lingua e / o potrebbe essere ancora troppo confuso per i recensori.

Innanzitutto, pensiamo a cosa significherebbe far sembrare Java "C ++". Come semplice caso, puoi usare newper creare un'istanza di oggetti, proprio come in Java:

Foo foo = new Foo();

Ma gli oggetti istanziati in questo modo usano ->invece di .chiamare i metodi, quindi se vuoi che le chiamate ai metodi appaiano come Java, devi invece scrivere:

Foo& foo = *new Foo();

Ma questo non è idiomatico; in particolare, la memoria deve essere successivamente ripulita utilizzando delete &foo, che alcuni sviluppatori C ++ esperti potrebbero non realizzare nemmeno un codice legale . In entrambi i casi, ci sono divertenti simboli non-Java-like sparse in tutto, in modo che non può abbastanza rendere il linguaggio "assomigliare" Java. (Potresti eliminare *newusando #define New *new, o, peggio, #define new *newma poi stai solo chiedendo ai tuoi colleghi sviluppatori di odiarti.) E, come detto sopra, deletenon esiste in Java, quindi in ogni caso (come menzionato in un'altra risposta ) non puoi mai far "sembrare" l'utilizzo degli oggetti come in Java senza perdite di memoria.

Ma il moderno C ++ include puntatori condivisi intelligenti, che si comportano in modo molto simile ai riferimenti variabili gestiti dalla memoria di Java. Quindi ovunque in Java che potresti scrivere Foo foo = new Foo();, puoi invece scrivere:

std::shared_ptr<Foo> foo = std::make_shared<Foo>();

Ora stai usando una funzionalità linguistica che in realtà è molto simile a quella di Java. Ma improvvisamente hai molto da spiegare ai revisori non C ++: che cos'è questa shared_ptrroba? Quali sono i "trucchi" delicati e delicati make_shared? (Utilizza l'inoltro perfetto, che presenta alcuni casi di errore e può portare alla chiamata del costruttore "sbagliato".) Perché i metodi devono essere chiamati con ->, ma l'utilizzo .con alcuni metodi è consentito dal compilatore? ( shared_ptrha i propri metodi.) Se il metodo Foo::reset(void)esiste, uno sviluppatore inconsapevole potrebbe provare a chiamarlo con il foo.reset()quale (se c'è solo un puntatore condiviso che punta a quell'istanza di Fooquando si verifica la chiamata) eliminerà la memoria sottostante e annullerà foo, e È probabile che gli sviluppatori Java non rilevino questo problema.

Inoltre, C ++ ha un sacco di insidie che sono specifici per la lingua. Come meglio posso dire, la maggior parte degli sviluppatori di C ++ impara a gestire queste insidie ​​sviluppando gradualmente il proprio linguaggio per pratiche "sicure" in C ++, che è spesso in qualche modo unico per loro o per il loro team di sviluppo (vedere ad esempio la risposta esistente che menziona il Le pratiche di codifica di Google e il commento su di esso affermano che "I veterani C ++ stagionati di solito rifiutano le linee guida di codifica di Google"). Tutte le affermazioni secondo cui il linguaggio potrebbe essere troppo complicato, a quanto pare (almeno nella mia esperienza), in genere si incontrano alcune variazioni di "beh, smetti di usarlo nel modo sbagliato". Mi rendo conto che questa è una visione fortemente negativa della comunità di ++ C, e ci sono certamente sviluppatori esperti più disposti a dare una mano lingua-studenti, ma non lo fa sembra essere una certa capacità difensiva ad esempio su comportamenti indefiniti (vedi ad esempio gran parte della discussione nel mio link "insidie" sopra).

Gli sviluppatori Java semplicemente non saranno utili per trovare e correggere queste insidie ​​tramite la revisione del codice.


Un giorno ti potrebbe essere chiesto di convertire il codice in Java.

È del tutto valido - lodevole, persino - provare a tenere conto di ciò che potrebbe accadere al tuo codice in futuro mentre sei in fase di progettazione.

Ma, in primo luogo, questa particolare considerazione sembra una possibilità remota: il codice è in genere o riutilizzato così com'è (ad esempio è possibile collegare parte o tutto il codice C ++ funzionante in un futuro software Java utilizzando un'interfaccia JNI) o riscritto del tutto piuttosto che direttamente "trascritto" manualmente.

E, in secondo luogo, in seguito dici:

Ogni caratteristica specifica del linguaggio C ++ (ad esempio: ereditarietà multipla) dovrebbe avere alternative da implementare in Java ....

Questo essenzialmente annulla il punto "converti in Java". Se il software è scritto in C ++ idiomatico e quindi convertito in Java idiomatico, non c'è motivo di aspettarsi che questa conversione sarebbe (o potrebbe!) Essere eseguita applicando un mapping uno-a-uno preciso delle funzionalità C ++ alle funzionalità Java.


Il codice senza funzionalità specifiche C ++ è generalmente più gestibile.

Non è chiaro cosa intendi qui, ma in realtà sono in qualche modo d'accordo con una parte di questo: a meno che tu non sia molto attento e anche quando stai attento, le funzionalità C ++ possono portare a problemi di manutenibilità. Il C ++ FQA Lite (un sito Web critico nei confronti del linguaggio e dei suoi aderenti da parte di qualcuno che almeno sembra effettivamente capirlo abbastanza bene) afferma che

... L'80% degli sviluppatori comprende al massimo il 20% della lingua. Non è lo stesso 20% per persone diverse, quindi non contare su di loro per capire il codice reciproco.

NOTA BENE: se sei un fan del C ++ e arrivi a questo punto nella mia risposta e ti senti propenso a saltare ai commenti per sostenere che l'autore del FQA in realtà non capisce il C ++ o è disonesto nella maggior parte dei suoi argomenti , nota che (1) esattamente due frasi dopo averlo citato, riconosco che la FQA è una fonte molto distorta, e (2) non ha importanza per quello che sto cercando di dire se l'autore della FQA capisce o meno C ++ e non sto provando a bash su C ++ e dovresti leggere il resto del post senza dare per scontato che sono anti-C ++ solo perché ho citato l'FQA. Fine della nota

Allo stesso modo, Linus Torvalds odia il C ++ essenzialmente per questo motivo (attenzione: il collegamento implica molte imprecazioni, in vero stile Linus).

Ovviamente, si tratta di considerazioni molto distorte sulla questione, ma anche i sostenitori del C ++ spesso dicono che non dovresti usare l'intero set di funzionalità del linguaggio (ancora una volta, vedi le linee guida per la codifica di Google; inoltre, Bjarne Stroustrup, il creatore di C ++ , ha dichiarato pubblicamente, "All'interno del C ++, c'è un linguaggio molto più piccolo e più pulito che lotta per uscire").

Quindi penso che ci sia un certo merito all'idea che le funzionalità C ++ potrebbero essere troppo facili da usare in modo improprio, specialmente se si proviene da uno sfondo Java. Inoltre, c'è il merito all'idea di alleviare questi problemi limitandoti ad alcuni sottogruppi della lingua.

Tuttavia, decidere quale sottoinsieme utilizzare in base a un linguaggio diverso non sembra l'approccio giusto, a meno che il "linguaggio diverso" sia C, poiché esiste davvero un sottoinsieme simile al C del linguaggio C ++. (Linus si riferisce a questo nel suo rant sopra, e Scott Meyers si riferisce persino a questo sottoinsieme come un "sotto-linguaggio"). Il paradigma di runtime di Java (raccolta dei rifiuti, in esecuzione su una macchina virtuale) è così sostanzialmente diverso da quello di C ++ che è non è chiaro che ci siano utili lezioni da trarre sull'uso del C ++ da esso, e come notato sopra, provare a trarre lezioni sul C ++ direttamente da Java può portare a un codice molto non idiomatico.

Invece, prova a definire il tuo "sottoinsieme accettabile" della lingua sulla comprensione di come la lingua può essere utilizzata in modo idiomatico. Se si desidera un sottoinsieme abbastanza restrittivo che sfrutta ancora molte delle funzionalità di C ++ oltre a ciò che offre C, la linea guida di codifica di Google di cui sopra potrebbe essere un buon punto di partenza. Certo, otterrai sviluppatori che affermano che "non c'è alcun argomento razionale" per alcune delle restrizioni di Google , ma a meno che tu non stia cercando di assumere Alexandrescu lontano dal suo lavoro sul linguaggio D (che a sua volta dovrebbe dirti qualcosa), questo è probabilmente va bene. È sicuramente meglio che provare a trasformare C ++ in Java.

Un altro buon punto di partenza per una serie di linee guida sul codice è il nuovo C ++ Core Guidelines , un work-in-progress di Bjarne Stroustrup e Herb Sutter.

L'unico altro modo per affrontare le carenze del C ++ è scegliere una lingua diversa. Sembra che tu ti piaccia Java e pensi che alla fine questo progetto possa essere convertito in Java. Come notato in un'altra risposta, potresti semplicemente ... iniziare con Java.

Ci sono due motivi per cui potresti davvero dover usare qualcosa di diverso da Java:

  1. Hai davvero bisogno delle prestazioni di runtime. In questo caso, trattare C ++ come se fosse Java probabilmente non ti aiuterà, perché tecniche simili a Java come i puntatori condivisi peggiorano le prestazioni di runtime.
  2. È necessario che il software funzioni su una piattaforma oscura che non supporta ancora JVM. In questo caso, probabilmente sei bloccato con le lingue che hanno frontend GCC o Clang. C e C ++ sono candidati ovvi, ma potresti anche esaminare qualcosa come Rust. (Quick plug: non ho usato Rust in modo estensivo, ma sembra fantastico e sono ansioso di lavorare su un grande progetto Rust appena posso, e penso che tutti coloro che stanno prendendo in considerazione l'avvio di un progetto C ++ dovrebbero considerare Rust come alternativa.)

Ogni caratteristica specifica del linguaggio C ++ (ad esempio: ereditarietà multipla) dovrebbe avere alternative da implementare in Java. In caso contrario, ciò significa che il modello di progettazione o l'architettura del codice è problematico.

L'ho già affrontato in qualche modo, ma ho intenzionalmente escluso la tua seconda frase.

Non sono convinto che qualcosa del genere constexpr, che non avrebbe alcun senso in un linguaggio parzialmente JIT come Java, sia un'indicazione di architettura non valida. Sono più aperto all'idea che un uso eccessivo della meta-programmazione dei template potrebbe essere più un problema di quanto non valga la pena, specialmente ora che constexpresiste per fare la valutazione delle funzioni in fase di compilazione, ma è chiaro dal caso constexprche non ci sono difetti di progettazione se si lo stai usando: stai semplicemente assicurando che alcuni calcoli si verifichino anche prima di eseguire il codice, il che è un incredibile miglioramento delle prestazioni (vedi ad esempio questa voce per il problema n-body di The Benchmark Game , che supera ogni altra voce tranne un'altra scritto in C ++,


5
L'autore di FQA rientra sicuramente nel gruppo "capire al massimo il 20% della lingua". Ci sono alcune risposte che sono effettivamente sbagliate, e molte altre ancora che mancano il punto, illustrate con Strawman dopo Strawman.
Ben Voigt,

2
Molte (quasi tutte?) Delle lamentele nel CQ FQA sono senza senso. Le lingue moderne sono enormi. Il C ++ è piuttosto piccolo rispetto a Python, Ruby, Perl e sì, Java. Poni una domanda di base in quelle lingue su StackOverflow e la prima risposta è quasi inevitabilmente sulla falsariga di "Perché non l'hai fatto import SomeVeryBasicPackagee semplicemente fatto questo ?" Fare una domanda avanzata e la prima risposta è quasi inevitabilmente sulla falsariga di "Perché non hai import SomeMagicalPackagee basta fare che ?"
David Hammen,

1
@DavidHammen Penso che la divisione 80/20 si riferisca alle funzionalità del linguaggio di base, non solo ai componenti di libreria standard, nel qual caso le lingue che menzioni, con la possibile eccezione di Perl, in realtà non sembrano essere così grandi e complicate come C ++. In ogni caso, quella era una parte molto piccola della mia risposta e ho riconosciuto che si trattava di una fonte distorta.
Kyle Strand,

1
Le lingue VM / gestite sono ovviamente molto più complicate sotto la superficie, ma intendo complicate dal punto di vista dell'uso.
Kyle Strand,

1
Non ho idea se la tua teoria sia corretta, anche se nel mio caso ho sicuramente imparato C ++ e C separatamente e la mia classe C ++ è stata davvero approfondita. Ma la citazione completa sulla divisione 20/80 è che ogni programmatore conosce un diverso 20% della lingua, il che non sarebbe spiegato dalla maggior parte dei programmatori a cui viene insegnata la parte C della lingua in modo indipendente. Ad ogni modo, se desideri spiegare in dettaglio in che modo il C ++ consente una programmazione più solida (presumo di aver visto prima ma non capisco), probabilmente faremmo meglio a farlo in una chat room o qualcosa piuttosto che nei commenti qui .
Kyle Strand,

5

Supponiamo che io sia limitato a usare C ++ dall'ambiente nel progetto. È utile impedire l'uso di alcune funzionalità del linguaggio di C ++ ma Java non ha (ad esempio: ereditarietà multipla, sostituzione dell'operatore)?

No.

Se "dall'ambiente del progetto" sei limitato all'utilizzo del C ++, allora c'è poco o nessun punto nel pensare anche a qualsiasi altra tecnologia, non importa quanto potresti preferire / sperare di usarlo / evangelizzarlo personalmente.
Il fatto che "Technology X" o "Y" supporti una determinata funzionalità non dovrebbe avere alcuna influenza sul modo in cui si crea l'applicazione C ++.
È un'applicazione C ++, presumibilmente per qualche "Good Reason" (ora o in passato), quindi dovresti scriverla come un'applicazione C ++, usando tutto ciò che quel particolare "toolbox" fornisce.

Se e quando c'è un Requisito per il porting dell'applicazione su qualche altra tecnologia allora (e solo allora) potresti considerare le funzionalità su altre piattaforme. Non ha senso "tagliare il naso per far dispetto al tuo viso" sulla possibilità che qualcosa possa accadere. Ricorda, tuttavia, che la riscrittura all'ingrosso è un'operazione costosa e rischiosa che è improbabile che la direzione intraprenda senza un'ottima ragione per farlo.

C'è stato un dibattito simile ("da usare o non usare") qualche anno fa nel mondo di Visual Basic [.Net], in cui Qualcuno aveva la brillante idea che dovresti scrivere applicazioni di Visual Basic senza usare alcun [linguaggio di base] funzionalità fornita dallo spazio dei nomi Microsoft.VisualBasic. Sarebbe come provare a scrivere un'applicazione C ++ senza lo std :: namespace; OK, è possibile, ma perché mai qualcuno nella propria mente dovrebbe preoccuparsi di farlo?


1
All'ultimo punto su Visual Basic: il problema con tali librerie di fornitori è che sono proprietarie. Usarli significa incatenarsi a quel venditore. Al venditore piacerà essere incatenato, ma a lungo termine: non è possibile utilizzare il software di un altro fornitore senza riscrivere tutto ciò che si basa su funzionalità specifiche del fornitore. Più si utilizza la funzionalità specifica del fornitore, maggiore è il costo della modifica dei fornitori, che consente al fornitore di forzare le modifiche su di te. Questo è uno dei motivi per cui il software libero (come in libertà!) È un grosso problema.
cmaster

La Microsoft.VisualBasiccosa dello spazio dei nomi è un po 'allungata. Sono passati molti anni dall'ultima volta che l'ho usato, ma almeno all'inizio era principalmente finalizzato alla retrocompatibilità con VB6 (e / o per far sentire i programmatori VB6 "a casa"); forniva principalmente funzionalità che erano già disponibili nel resto del framework in una forma più moderna (e meglio integrata), quindi nei nuovi progetti raramente aveva senso utilizzarla. Al contrario, lo std::spazio dei nomi è dove risiede l'intera libreria standard - evitarlo sarebbe come evitare l'intero BCL in .NET.
Matteo Italia,

2

Le risposte attuali dicono che questa è una brutta cosa da fare, in quanto dovresti sfruttare il linguaggio che stai usando e spiegare anche perché una funzione C ++ non è "cattiva" solo perché non è in jave. Risponderò da una prospettiva diversa.

Una cosa è evitare la complessa funzionalità C ++ come l'ereditarietà multipla, il sovraccarico dell'operatore e la definizione del proprio modello.

Ma qualsiasi problema che fa più del semplice compito:

  • alloca memoria
  • collega quei soldi insieme ai punti
  • quindi costruisci strutture di dati
  • quindi consente di riutilizzare la memoria quando è sicuro farlo

Non esiste un sottoinsieme comune di Java e C ++ che consenta quanto sopra, quindi ciò che stai chiedendo è impossibile da fare. (Se chiedessi di Java e C # avresti molte più possibilità, dato che usano entrambi i garbage collector.)

Tuttavia potresti richiedere che il codice sia scritto in modo che uno sviluppatore Java possa capire cosa fa (ma non il "come" dettagliato) e questo sarebbe sensato.

Potresti anche progettare il tuo linguaggio implementato sia in C ++ che in JAVA .....


0

Nessuno dovrebbe scrivere alcun codice che altri programmatori non capiscono. Se ritieni che il blocco della lingua sia un problema, attendi fino a quando non avrai il blocco degli sviluppatori. Uno ha maggiori probabilità di tenerti in ostaggio rispetto all'altro.

Non ci sono davvero ragioni tecniche. Quello che hai creato è uno scenario in cui un linguaggio è stato usato per qualsiasi motivo, ma molti sviluppatori attuali e forse futuri non lo capiscono davvero.

Suppongo che gli sviluppatori Java probabilmente scriveranno C ++ nel modo in cui scrivono in Java, quindi perché renderlo una regola. Potresti scoprire alcune caratteristiche specifiche di C ++ che sono più facili da implementare e gestire con un po 'di istruzioni / documentazione C ++ per i tuoi sviluppatori Java rispetto alla grande sfera di pasticcio Java con cui altrimenti verrebbero bloccati.

Questo è stato un argomento sui problemi dei programmatori BASIC che passano a linguaggi orientati agli oggetti. Non è che implementano pratiche OOP a detrimento di nuovi sviluppatori che non lo capiscono, ma che non lo implementano affatto. Se lo fanno, di solito sbagliano. Se qualcosa viene fatto male, deve essere rimosso indipendentemente dal motivo.

Oltre a qualcuno che copia e incolla alla cieca il codice, lo farà in molte aree che non capisce comunque.

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.