web-dev-qa-db-fra.com

Devrions-nous éviter les fonctionnalités de langage que C ++ possède mais Java non?

Supposons que je suis limité à utiliser C++ par l'environnement dans le projet. Est-il bon d'empêcher l'utilisation de certaines fonctionnalités du langage que C++ possède mais Java n'a pas (par exemple: héritage multiple, surcharge d'opérateur)?

Je pense que les raisons sont:

  1. Comme Java est plus récent que C++, si Java ne fournit pas de fonctionnalité en C++, cela signifie que la fonctionnalité n'est pas bonne, nous devons donc éviter En l'utilisant.
  2. Le code C++ avec des fonctionnalités spécifiques C++ (par exemple: fonctions ami, héritage multiple) ne peut être maintenu ou révisé que par les programmeurs C++, mais si nous écrivons simplement C++ comme Java (sans fonctionnalité spécifique au langage C++), le code peut être maintenu ou révisé par les programmeurs C++ et Java.
  3. Il peut vous être demandé de convertir le code en Java un jour
  4. Le code sans fonctionnalités spécifiques C++ est généralement plus facile à gérer
  5. Chaque fonctionnalité spécifique au langage C++ (par exemple: l'héritage multiple) devrait avoir des alternatives à implémenter en Java. Si ce n'est pas le cas, cela signifie que le modèle de conception ou l'architecture de code est problématique.

Est-ce vrai?

112
ggrr

Non, c'est tristement et terriblement mal orienté.

  • Les fonctionnalités Java ne sont pas meilleures que les fonctionnalités C++, en particulier dans le vide.
  • Si vos programmeurs ne savent pas comment utiliser une fonctionnalité, formez ou embauchez de meilleurs développeurs; limiter vos développeurs au pire de votre équipe est un moyen rapide et facile de perdre vos bons développeurs.
  • YAGNI . Résolvez votre problème actuel aujourd'hui, pas le fantôme d'un problème futur.
306
Telastyn

Ce n'est pas parce que la syntaxe semble similaire en surface que les deux langues sont compatibles.

1, 4 et 5 sont vraiment la même question:

Maintenant, je ne suis pas fan de C++, mais dire "Code sans fonctionnalités spécifiques C++ est généralement plus maintenable" est tout simplement ridicule - croyez-vous vraiment que Java a tout bien fait et a pris toutes les bonnes fonctionnalités tout en ignorer tous les mauvais? Croyez-vous vraiment qu'il y a quelque chose qui est universellement une "mauvaise" ou une "bonne" fonctionnalité? S'il y en a, pourquoi n'avons-nous pas une seule langue qui soit purement bonne? Et non, Java certainement n'est pas cette langue. Est-ce à dire que Java et C++ sont inutiles? Bien sûr que non.

Et si vos dirigeants décident que vous allez porter sur C #, plutôt que sur Java? Non seulement C # prend en charge les opérateurs prioritaires, mais c'est également la valeur par défaut - si vous allez exiger que les gens utilisent par exemple obj.Equals(obj2) au lieu de obj == obj2, les gens vont faire des erreurs tout le temps. Même si vous ne vous en tenez qu'aux caractéristiques communes aux deux langues, il existe différentes attentes, une culture différente. Si vous faites quelque chose comme if (myField == null) en C++, les gens vont immédiatement voir que vous êtes novice. Si vous utilisez if (null == myField) en C #, les gens vont voir que vous n'êtes pas encore vraiment natif de C # - les raisons pour lesquelles les développeurs C ont appris à utiliser la variante "inversée" n'existent plus en C #.

En utilisant votre logique, nous aurions dû nous en tenir au code machine ou à Assembly ou COBOL, car pourquoi changer à quelque chose comme Pascal, alors qu'il ajoute simplement de nouvelles fonctionnalités que vos programmeurs devront apprendre? Pourquoi utiliserions-nous quelque chose comme SQL, alors qu'il n'a même pas boucles? Pourquoi utiliserions-nous quelque chose else que SQL, alors que SQL n'a pas de boucles et que X en a?

Le code C++ certainement ne peut pas être maintenu par les programmeurs Java. Je ne comprends pas d'où vous vient cette idée - que reste-t-il exactement lorsque vous limitez C++ aux seules fonctionnalités qui fonctionnent exactement de la même manière qu'en Java? Vous n'allez même pas recevoir d'appels de méthode - même pas function appels. Encore une fois, ce n'est pas parce que les deux langages utilisent des accolades que les langues sont interchangeables.

La conversion de code C++ de type Java va être extrêmement sujette aux erreurs, peu importe ce que vous faites. Il y a juste trop de différences. Si vous avez besoin de réécrire votre application dans une langue différente, pensez à des moyens raisonnables de tout modulariser, afin de pouvoir remplacer les pièces sans casser le tout. Mais au final, YAGNI - peu importe ce que vous faites, il va y avoir un coût important pour rendre votre code "prêt à être converti en Java". C'est du temps qui est probablement mieux dépensé pour ajouter ou améliorer vos fonctionnalités.

Nous utilisons différentes langues car elles nous fournissent un ensemble d'outils différent pour résoudre les problèmes. Si vous avez besoin d'exécutables qui fonctionnent "partout", optez pour Java. Si vous voulez du code qui compile "partout", C++ fonctionne très bien. Si vous voulez du code facile à comprendre et à analyser, optez pour LISP ou autre chose. Mais je peux vous dire une chose - écrire du code dans une langue comme si vous l'écriviez dans une autre est toujours une erreur, et vous en souffrirez. Sans oublier que lorsque vous embauchez réellement un gars C++, il va exécuter la seconde où il voit ce code "compatible Java-ish". Et ... le Java va faire de même. Vous savez, même en "connaissant" à la fois C++ et Java, je courrais comme un enfer :)

En fait, j'ai dû travailler sur du code C (simple) écrit par un développeur Pascal qui semblait penser comme vous. Il a utilisé #define S pour redéfinir C pour ressembler et ressembler davantage à Pascal, avec des choses comme "BEGIN se traduit par {". Le résultat était plutôt prévisible - du code que ni les développeurs ni C ni Pascal ne peuvent comprendre, et plein de bugs qui étaient le résultat de la fuite de "l'abstraction" de Pascal en plus de C. Et Pascal et C sont presque identiques = du point de vue d'aujourd'hui. Même aller C <-> C++ est beaucoup plus d'une différence, et c'est toujours des arachides à quelque chose comme C++ <-> Java.

143
Luaan

Je répondrai à vos questions dans l'ordre.

  1. Si Java ne fournit pas de fonctionnalité en C++, cela signifie que la fonctionnalité n'est pas bonne, nous devons donc éviter de l'utiliser.

Oui, toute fonctionnalité non présente dans Java est un anathème sur le disque dur. Il doit être gravé à partir de votre base de code. Ceux qui n'obéissent pas seront fouillés, leurs âmes utilisées pour apaiser les dieux du RAID .

  1. Le code C++ avec des fonctionnalités spécifiques C++ (par exemple: fonctions ami, héritage multiple) ne peut être maintenu ou révisé que par les programmeurs C++, mais si nous écrivons simplement C++ comme Java (sans fonctionnalité spécifique au langage C++), le code peut être maintenu ou révisé par les programmeurs C++ et Java.

En cas de doute, écrivez le code du membre le moins compétent de votre équipe. Le code est lu beaucoup plus souvent qu'il n'est écrit, et un code aussi intelligent que vous pouvez écrire est trop intelligent pour être lu. Les révisions de code que votre personnel de réception ne comprendra pas doivent être rejetées. Pour vous aider, apprenez-leur à programmer en Visual Basic 2.0 pendant le week-end, puis émulez leur style de codage dans la langue que vous utilisez.

  1. Il peut vous être demandé de convertir le code en Java un jour

Vrai! Mais pourquoi s'arrêter à Java? Il se peut qu'on vous demande de convertir le code en base, assembleur et/ou Perl un jour. Comme il existe des interprètes Perl dans toutes les langues, écrivez simplement votre programme sous la forme d'une longue chaîne Perl et regroupez-y les arguments dans la langue de votre choix.

Maintenant, lorsque vous devez changer de langue, il vous suffit de réécrire le code encapsulant la chaîne Perl.

  1. Le code sans fonctionnalités spécifiques C++ est généralement plus facile à gérer

Il est vrai que le code qui utilise moins de fonctionnalités est plus facile à maintenir. Et comme tous les langages sont équivalents à une machine de Turing, et qu'une machine de Turing possède le moins de fonctionnalités de n'importe quel langage de programmation, demandez à l'interpréteur Perl ci-dessus d'exécuter une machine de Turing (bande et tout) qui résout votre problème.

  1. Chaque fonctionnalité spécifique au langage C++ (par exemple: l'héritage multiple) devrait avoir des alternatives à implémenter en Java. Si ce n'est pas le cas, cela signifie que le modèle de conception ou l'architecture de code est problématique.

Les fonctionnalités spécifiques au langage C++ ont en fait une utilité précieuse. Comme ils ne sont pas Java, ils sont anathèmes, et ceux qui l'utilisent peuvent être des hérétiques de marque. Si C++ n'avait pas ces fonctionnalités de langage, vous ne seriez pas en mesure de trouver celles que vous devez sacrifier. Les fonctionnalités du langage C++ résolvent les problèmes!


Regardez, C++ et Java ont un ensemble de capacités différent. La programmation à l'intersection de C++ et Java donne un code qui a rejeté la plupart des avantages de les deux langues.

Java a été développé en partie en réaction à certains abus des fonctionnalités C++. Cela ne signifie pas que la réaction était justifiée, surtout des années après que les caractéristiques aient mûri.

Vous pouvez faire des choses horribles avec la surcharge de l'opérateur; mais aucun langage ne peut empêcher l'écriture d'un code horrible dans la langue, à moins qu'il n'empêche tout le code d'être écrit dans la langue.

Et vous pouvez également faire des choses très élégantes avec la surcharge de l'opérateur. Des choses simples, comme un nombre complexe ou une classe matricielle qui fonctionne comme un nombre complexe ou une matrice.

Attention à l'utilisation des fonctionnalités C++ non disponibles dans Java doit être considéré avec prudence. Ce n'est pas parce que votre ensemble actuel de développeurs à leur niveau de compétence actuel ne comprend pas une fonctionnalité qu'elle ne devrait jamais être utilisé; en même temps, ce n'est pas parce que vous pouvez utiliser une fonctionnalité que vous devez le faire. Cependant, dans une boutique Java, les chances sont que la résistance sera plus forte qu'elle ne devrait l'être contre les fonctionnalités non Java.

La conversion de code entre les langues se fait mieux avec une réécriture, peu importe leur similitude structurelle. Toute tentative de le faire sans une telle réécriture échouera lamentablement.

De nombreuses fonctionnalités spécifiques à C++ sont des merveilles pour la maintenance. Tapez l'effacement (comme std::function) vous permet de découpler les hiérarchies, ce qui réduit les dépendances. Les pointeurs intelligents et les durées de vie déterministes et RAII réduisent les surprises d'exécution et éloignent le passe-partout des ressources. Les vérifications de type statiques lourdes signifient que le code ne parvient pas à compiler, au lieu de ne pas fonctionner. Les mix-ins réduisent la duplication de code. ADL permet une extension indépendante ad hoc des interfaces entre les hiérarchies de types. Lambda vous permet d'écrire du code à côté de l'endroit où il est utilisé. Le transfert et le déplacement réduisent le nombre de copies et rendent la programmation de style fonctionnel (sans effet secondaire) efficace. La surcharge de l'opérateur réduit le bruit de ligne et fait ressembler davantage le code aux calculs qu'il modélise.

Méfiez-vous de la fosse de goudron de Turing. Vous pouvez implémenter tout dans n'importe quelle langue (y compris une machine de Turing brute avec bande), mais cela ne signifie pas que vous devrait. Émuler des fonctionnalités C++ à l'aide de constructions Java-esque en C++ est une idée horrible; il en résultera un code incontrôlable que personne ne pourra lire ou comprendre.

Vous pouvez prendre inspiration à partir de Java conçoit et les portez sur C++. Je suis un grand fan de prendre Python fonctionnalités du langage et les implémenter en C++, parce que j'aime la syntaxe. Mais cela ne signifie pas que j'écris mes méthodes de classe en tant que méthodes statiques prenant un self explicite, puis j'écris un wrapper qui transmet l'appel de méthode non statique vers lui.

Le C++ moderne ne ressemble pas du tout au langage Java émulé et rejeté. Ne soyez pas bloqué par les fonctionnalités d'un langage; il n'y a pas "un seul vrai langage". En savoir plus sur les nouveaux langages et leurs caractéristiques et absorbent leur caractère distinctif.

94
Yakk

Je vais juste répondre à vos raisons:

  1. Je ne comprends pas comment vous arrivez à cette conclusion. Différentes langues ont des fonctionnalités différentes. Dépend de la portée, de l'architecture du langage, parfois des préférences des créateurs et bien d'autres raisons. Certaines fonctionnalités d'une langue peuvent être mauvaises, mais votre généralisation est tout à fait erronée à mon humble avis.
  2. Écrire C++ comme Java peut conduire à un code pire. Par exemple avec C++ 11 j'évite d'utiliser new/delete, mais j'utilise des pointeurs partagés. Dans votre scénario, je ne compterais que sur new/delete Si vos programmeurs ne comprennent que Java, formez-les ou engagez-en de meilleurs.
  3. Est-ce que ça va arriver? Pourquoi n'écrivez-vous pas Java en premier lieu? Je pense que réécrire des programmes à partir de zéro dans un nouveau langage est généralement une mauvaise idée et vous auriez besoin d'un bonne justification d'un tel risque.
  4. Ce n'est qu'une hypothèse.
  5. Dépend à mon humble avis de votre scénario ou de votre cas d'utilisation.
56
Simon

Java possède des fonctionnalités que C++ ne possède pas, comme un récupérateur de place intégré, rapide et fiable, une hiérarchie d'objets à racine unique et une puissante introspection.

Les autres fonctionnalités de Java sont conçues pour fonctionner avec les fonctionnalités exclusives à Java, et de nombreuses omissions de Java des fonctionnalités C++ sont possibles car les nouvelles fonctionnalités compensent le manque. Par exemple, Java n'a pas d'objets affectés à la pile avec des destructeurs déterministes, mais a finalement des blocs (et essaie avec des ressources depuis Java 7) et le garbage collector pour combler ce manque.

C++ n'a finalement pas de blocs ni de garbage collection. Si vous n'utilisez pas de destructeurs parce qu'ils n'existent pas dans Java (je ne compte pas les finaliseurs), vous êtes au niveau C de la gestion des ressources (c'est-à-dire tous les manuels), sauf que vous ne pouvez même pas regrouper votre nettoyage dans un bloc de nettoyage auquel vous avez accès, parce que Java n'a pas non plus. Pensez-vous vraiment que cela améliore la maintenabilité?

Java a une hiérarchie d'objets globale où chaque classe dérive finalement d'Object, et les quelques types primitifs peuvent également être placés automatiquement dans ces classes. Cela permet d'écrire des conteneurs d'objets une fois, pour contenir des pointeurs vers Object. Java 5 génériques introduits, qui éliminent les transtypages nécessaires à ces conteneurs, mais compilent toujours à peu près le même code.

C++ n'a pas une telle hiérarchie. Pour faciliter l'écriture de conteneurs qui fonctionnent pour plusieurs types, vous utilisez des modèles, qui sont des modèles qui sont instanciés par le compilateur selon les besoins pour différents types. Allez-vous interdire l'utilisation de modèles (et de macros) et emprunter la route C soit en écrivant le même code conteneur encore et encore pour différents types, soit en utilisant des pointeurs void? (Attendez, Java n'a pas de pointeurs vides!) Êtes-vous sûr que cela augmenterait la maintenabilité?

Un langage décent possède une multitude de fonctionnalités conçues pour fonctionner ensemble. En interdisant les fonctionnalités du langage A parce que le langage B n'en a pas, vous paralysez le langage A, car vous n'ajoutez pas en même temps des fonctionnalités de B qui font de B un ensemble cohérent.

Cela ne veut pas dire que vous ne devez pas restreindre les fonctionnalités autorisées de C++. Le C++ est un grand langage historiquement développé qui met l'accent sur le fait de permettre au programmeur de faire ce qu'il veut plutôt que la sécurité et la facilité d'utilisation, et toutes ses fonctionnalités dans toute leur flexibilité ne sont pas nécessaires pour créer de bons programmes. Il existe de nombreuses normes de codage qui restreignent l'utilisation de certaines fonctionnalités; par exemple, les directives de Google interdisent principalement l'héritage multiple, les modèles complexes et les exceptions (bien que ce dernier soit pour des raisons historiques). Mais aucune fonctionnalité n'est interdite "car Java ne l'a pas"; les fonctionnalités sont considérées dans le cadre de C++ uniquement.

26
Sebastian Redl

J'ai débattu de l'opportunité de publier une autre réponse lorsque vous avez déjà un chiffre qui atteint des conclusions qui semblent être tout à fait raisonnables: que votre idée est fondamentalement une catastrophe qui attend de se produire. Je pense, cependant, qu'ils n'ont pas réussi à souligner certains très pertinents raisons derrière cette conclusion.

Les différences entre Java et C++ s'exécutent beaucoup plus profondément que les détails sur lesquels vous semblez avoir mis l'accent.

Par exemple, vous parlez d'interdire l'héritage multiple en C++. Tout d'abord, je ferai remarquer que cela manque tout simplement le point. Java définit les "interfaces" comme des choses distinctes des "classes". Une classe hérite d'une seule autre classe, mais peut implémenter un nombre arbitraire d'interfaces.

C++ ne sépare pas les deux concepts de cette façon. L'analogue C++ le plus proche fournit l'implémentation d'une interface en Java is héritant d'une autre classe. En tant que tel, pour garder les deux alignés raisonnablement bien, vous avez probablement - besoin pour utiliser l'héritage multiple en C++, mais vous voulez restreindre certaines de ces classes de base à peu près de la même manière Java restreint une interface par rapport à une classe (c'est-à-dire essentiellement que il spécifie les signatures de fonction mais, au moins surtout, pas les implémentations).

Cela ne fait pourtant qu'effleurer la surface des vraies différences entre les deux. En réalité, où Java est susceptible de définir des interfaces et les classes qui implémentent ces interfaces, le code C++ est beaucoup plus susceptible de définir des modèles qui fonctionneront avec any = classe qui répond à ses exigences (pas seulement celles définies spécifiquement pour implémenter les interfaces qu'il spécifie).

Si vous voulez honnêtement du code qui est essentiellement "Java en utilisant la syntaxe C++", vous devrez certainement interdire tout ce qui est similaire à ce dernier. Vous devrez restreindre votre utilisation des modèles à peu près au niveau de "conteneur de T" que Java. Malheureusement, cela entraînera du code C++ qui est un tel gâchis que personne ne peut le maintenir tel qu'il existe actuellement, sans parler de la possibilité à long terme de le traduire dans un autre langage de programmation.

Si vous voulez vraiment du code qui puisse être converti dans un autre langage à l'avenir, essayez de le rendre aussi propre et lisible que possible. L'idéal est d'écrire du pseudo-code et de le faire exécuter. Des approches C++ modernes bien écrites qui sont bien plus proches de l'idéal que le sous-ensemble que vous avez suggéré. Peu importe comment vous l'écrivez, si jamais vous traduisez en Java, vous devrez réellement traduire le code, pas seulement la syntaxe des instructions individuelles.

25
Jerry Coffin

Si vous allez écrire du code dans la langue X, passez le temps d'apprendre correctement la langue et utilisez toutes les fonctionnalités qu'il offre pour vous aider à résoudre le problème. De mauvaises choses se produisent lorsque vous essayez de faire une traduction "Word pour Word" d'une langue à une autre, que ce soit du japonais vers l'anglais ou Java vers C++. Il est préférable de commencer par une bonne compréhension de résoudre le problème et exprimer la solution de la manière la plus naturelle pour la langue utilisée.

Il y a des années, j'ai vu un programme C sans indentation et chaque déclaration commençait dans la colonne 7, car l'auteur du code était un programmeur Fortran qui se trouvait utiliser C. Les autres programmeurs Fortran étaient nerveux à propos de ces nouveautés appelées pointeurs. Je n'ai pas eu le cœur de mentionner pointeurs vers pointeurs, je pense qu'ils se seraient évanouis sur place.

Imaginez embaucher quelqu'un pour maintenir ce code à l'avenir. Si c'est du bon code C++, vous pourrez embaucher un développeur C++ compétent et il devrait être en mesure de trouver son chemin. Si c'est "Java en C++", alors ni C++ ni Java auront du mal à comprendre le code.

11
Tom Penny

Toutes vos raisons peuvent être réfutées:

Si Java ne fournit pas une fonctionnalité qui a C++, cela signifie que la fonctionnalité n'est pas bonne, nous devons donc éviter de l'utiliser.

Cela ne signifie pas que la fonctionnalité n'est pas bonne (aucune fonctionnalité ne peut être intrinsèquement mauvaise). Cela signifie seulement que la fonctionnalité a été fréquemment utilisée à mauvais escient (ou impossible à implémenter en raison de concepts fondamentaux, comme les pointeurs directs par rapport à la récupération de place). Java par définition vise à être plus facile et plus convivial pour les programmeurs, d'où la suppression de fonctionnalités qui se sont avérées être facilement exploitables.

Le code C++ avec des fonctionnalités spécifiques C++ (par exemple: fonctions ami, héritage multiple) ne peut être maintenu ou révisé que par les programmeurs C++, mais si nous écrivons simplement C++ comme Java (sans fonctionnalité spécifique au langage C++), le code peut être conservé ou révisé par les programmeurs C++ et Java.

Oh, c'est possible? Voyons le code C++ le plus simple:

int len = mystring->size();

Oups, aucune fonctionnalité "spécifique au langage" n'est utilisée, mais elle est déjà impossible à gérer par les développeurs de Java! Parce que dans Java vous déréférencez avec "." alors qu'ici c'est "->.

Il se peut qu'on vous demande un jour de convertir le code en Java

Ou C #. Ou Haskell. Ou Python. Ou Ruby. Ou COBOL (oui, vous pouvez!). Comment pouvez-vous dire l'avenir?

Le code sans fonctionnalités spécifiques C++ est généralement plus facile à gérer.

Exactement opposé. Chaque fonctionnalité a été introduite afin de rendre la programmation plus facile donc plus maintenable. Par exemple: prendre un programme fonctionnant sur des flotteurs. Maintenant, mettez-le à niveau pour gérer les nombres complexes. La surcharge de l'opérateur à la rescousse!

Chaque fonctionnalité spécifique au langage C++ (par exemple: l'héritage multiple) devrait avoir des alternatives à implémenter en Java. Si ce n'est pas le cas, cela signifie que le modèle de conception ou l'architecture de code est problématique.

Mais Java A HÉRITAGE multiple! Cela s'appelle "interface". L'implémentation de Java est une solution de contournement problématique pour éviter le diamant redouté causé par le fait que tout dérive de Object. Cela se fait en introduisant interface dont le seul but est d'être quelque chose qui ne dérive pas de Object. C++ n'a jamais eu ce problème - il n'y a pas de base commune obligatoire, donc chaque classe peut fonctionner comme une interface sans le diamant redouté.

Note latérale: Java a récemment introduit ... des méthodes concrètes dans les interfaces. Ajout d'une fonctionnalité C++ a toujours dû résoudre un problème qui n'était jamais là.

Vous n'avez également mentionné que très peu de "choses que C++ possède mais pas Java". L'une des plus grandes différences entre C++ et Java est le contrôle de la disposition de la mémoire. Vous pouvez créer un tableau de pointeurs vers des objets (tout comme en Java) OR vous pouvez créer un bloc de mémoire contigu. Maintenant, si je devais m'inquiéter d'une fonctionnalité C++ qui pourrait induire en erreur les développeurs de Java, quelque chose d'aussi caché et subtil que celui-ci se classerait sur ma liste beaucoup plus qu'évident et reconnaissable à première vue, comme l'héritage multiple ou les opérateurs surchargés .

Conclusion: le code propre est un code propre. Java ou C++ - même différence. Restez simple. Les complications inutiles sont la principale cause de mauvais code.

7
Agent_L

Il y a déjà de bons points dans d'autres réponses, mais j'aimerais apporter une réponse plus complète, en répondant à vos questions et déclarations individuellement.


Si Java ne fournit pas de fonctionnalité en C++, cela signifie que la fonctionnalité n'est pas bonne, nous devons donc éviter de l'utiliser.

Cela a été assez bien répondu: Java n'est pas "les bonnes parties" de C++, et il n'y a aucune raison de le penser.

En particulier, bien que les mérites de chaque fonctionnalité C++ individuelle puissent être discutés, de nombreuses fonctionnalités de C++ 11/C++ 14 qui ne font pas partie de Java Java ne sont pas nécessairement exclues car le Java les concepteurs pensaient que c'était une mauvaise idée. Par exemple, jusqu'à la version 8, Java n'avait pas de lambdas, mais ils ont été introduits en C++ dans la norme C++ 11. Avant Java 8, votre supposition que les fonctionnalités C++ manquantes dans Java étaient manquantes par conception car elles ne sont "pas bonnes") ont laissé entendre que les lambdas en tant que fonction de langage ne sont "pas bons" (à la grande horreur des LISPers partout dans le monde, bien qu'ils soient probablement assez horrifiés pour entendre que vous semblez réellement comme Java). Java ont apposé leur tampon d'approbation (TM) sur les lambdas, ils sont donc maintenant une bonne chose.

Pour creuser un peu plus profondément, même en Java 8, les lambdas-as-closures ne sont pas aussi flexibles que les lambdas de C++ 14, mais cela peut être dû aux limitations de l'architecture JVM plutôt qu'une décision consciente selon laquelle l'approche plus flexible est mauvaise du point de vue de la conception du langage.


Le code C++ avec des fonctionnalités spécifiques C++ (par exemple: fonctions ami, héritage multiple) ne peut être maintenu ou révisé que par les programmeurs C++, mais si nous écrivons simplement C++ comme Java (sans fonctionnalité spécifique au langage C++), le code peut être maintenu ou révisé par les programmeurs C++ et Java.

C'est la principale chose à laquelle je voulais répondre.

D'une manière générale, il peut être utile d'obtenir des revues de code de programmeurs qui ne connaissent pas intimement le langage que vous utilisez. Ils peuvent vous fournir de précieux commentaires sur la clarté de vos noms de fonction/méthode et vos commentaires, et (comme votre question l'indique correctement) si la langue est similaire à une ou plusieurs langues qu'ils connaissent déjà, ils peuvent être en mesure de suivre le flux de programme de base et potentiellement attraper des erreurs logiques.

Cependant, il est pas le cas où ce type de révision sera jamais "aussi bon que" ou "équivalent à" la critique de développeurs qui connaissent réellement la langue que vous utilisez. Essentiellement, c'est parce que faire une langue regarder comme une autre masquera généralement les différences subtiles, tout en faisant une langue se comporter comme une autre (en particulier dans le cas de C++ et Java) peut ne pas être idiomatique pour le langage et/ou peut être trop déroutant pour les réviseurs.

Tout d'abord, réfléchissons à ce que cela signifierait de faire ressembler C++ à Java. Comme cas simple, vous pouvez utiliser new pour instancier des objets, tout comme en Java:

Foo foo = new Foo();

Mais les objets instanciés de cette façon utilisent -> Au lieu de . Pour appeler des méthodes, donc si vous voulez que la méthode appelle ressemble à Java, vous devez plutôt écrire:

Foo& foo = *new Foo();

Mais ce n'est pas idiomatique; en particulier, la mémoire doit être nettoyée plus tard en utilisant delete &foo, qui certains développeurs C++ expérimentés pourraient même ne pas réaliser que c'est du code légal . Quoi qu'il en soit, il y a des symboles amusants qui ne ressemblent pas à Java, donc nous ne pouvons pas tout à fait faire en sorte que le langage "ressemble" à Java. (Vous pourriez éliminer *new En utilisant #define New *new, Ou pire, #define new *new, Mais alors vous ne faites que supplier vos collègues développeurs de vous haïr.) Et, comme mentionné ci-dessus , delete n'existe pas en Java, donc dans tous les cas (comme mentionné dans une autre réponse), vous ne pouvez jamais vraiment faire "utiliser" l'objet comme il le fait dans Java sans fuites de mémoire.

Mais le C++ moderne comprend des pointeurs partagés intelligents, qui se comportent un peu comme les références de variables gérées en mémoire de Java. Donc partout dans Java que vous pouvez écrire Foo foo = new Foo();, vous pouvez plutôt écrire:

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

Maintenant, vous utilisez une fonctionnalité de langage qui ressemble beaucoup à Java sous le capot. Mais soudain, vous avez beaucoup à expliquer aux réviseurs non C++: qu'est-ce que c'est que shared_ptr? Quels sont les "pièges" subtils et délicats de make_shared? (Il utilise le transfert parfait, qui présente certains cas d'échec et peut entraîner l'appel du "mauvais" constructeur.) Pourquoi les méthodes doivent-elles être appelées avec ->, Mais en utilisant . Avec certains méthodes est autorisé par le compilateur? (shared_ptr A ses propres méthodes.) Si la méthode Foo::reset(void) existe, un développeur imprudent peut essayer de l'appeler avec foo.reset(), qui (s'il n'y en a qu'une partagée un pointeur pointant vers cette instance de Foo lorsque l'appel se produit) supprimera la mémoire sous-jacente et annulera foo, et Java ne sont pas susceptibles d'attraper cela problème.

De plus, C++ a beaucoup de pièges qui sont spécifiques à langue . Pour autant que je sache, la plupart des développeurs C++ apprennent à surmonter ces écueils en développant progressivement leur propre idiome pour des pratiques C++ "sûres", ce qui est souvent quelque peu unique pour eux ou pour leur équipe de développement (voir par exemple la réponse existante qui mentionne le Les pratiques de codage de Google et le commentaire à ce sujet disant que "les vétérans chevronnés du C++ rejettent généralement les directives de codage de Google"). Toutes les affirmations selon lesquelles le langage pourrait être trop compliqué, semble-t-il (selon mon expérience, au moins), sont généralement rencontrées avec une certaine variation de "bien, arrêtez de l'utiliser mal". Je me rends compte que c'est une vision très négative de la communauté C++, et il y a certainement des développeurs expérimentés plus disposés à aider les apprenants de langue, mais il y a le fait semble être une certaine défensive par exemple comportement indéfini (voir par exemple une grande partie de la discussion dans mon lien "pièges" ci-dessus).

Les développeurs Java ne seront tout simplement pas utiles pour trouver et corriger ces pièges via la révision du code.


Il peut vous être demandé de convertir le code en Java un jour.

Il est tout à fait valable - louable même - d'essayer de prendre en compte ce qui pourrait arriver à votre code à l'avenir pendant que vous êtes dans la phase de conception.

Mais, tout d'abord, cette considération particulière semble être une possibilité à distance: le code est généralement soit réutilisé tel quel (par exemple, vous pouvez brancher tout ou partie du code C++ fonctionnel dans un futur Java Java utilisant une interface JNI) ou entièrement réécrit plutôt que directement "transcrit" manuellement.

Et, deuxièmement, vous direz plus tard,

Chaque fonctionnalité spécifique au langage C++ (par exemple: l'héritage multiple) devrait avoir des alternatives à implémenter en Java ....

Cela annule essentiellement votre point "convertir en Java". Si le logiciel est écrit en C++ idiomatique puis converti en Java idiomatique, il n'y a aucune raison de s'attendre à ce que cette conversion soit (ou puisse!) Être effectuée en appliquant un mappage un-à-un précis des fonctionnalités C++ à Java fonctionnalités.


Le code sans fonctionnalités spécifiques C++ est généralement plus facile à gérer.

Ce que vous entendez ici n'est pas clair, mais je suis en fait un peu d'accord avec cela: à moins que vous ne soyez très prudent, et même lorsque vous le faites, les fonctionnalités C++ peuvent entraîner des problèmes de maintenabilité. Le C++ FQA Lite (un site Web critique de la langue et de ses adhérents de quelqu'un qui semble au moins le comprendre assez bien) déclare que

... 80% des développeurs comprennent au plus 20% de la langue. Ce n'est pas le même 20% pour différentes personnes, alors ne comptez pas sur elles pour comprendre le code de l'autre.

S'IL VOUS PLAÎT NOTE: Si vous êtes un fan de C++ et que vous arrivez à ce point dans ma réponse et que vous êtes enclin à sauter vers le bas dans les commentaires pour faire valoir que le l'auteur de la FQA ne comprend pas réellement le C++ ou est malhonnête dans la plupart de ses arguments, notez que (1) exactement deux phrases après que je le cite, je reconnais que la FQA est une source très biaisée, et (2) il ne le fait pas vraiment important pour ce que j'essaie de dire si l'auteur FQA comprend ou non le C++, et je n'essaie pas de bash C++, et vous devriez lire le reste de l'article sans supposer que je suis anti-C++ juste parce que je 'ai cité la FQA. Fin de la note.

De même, Linus Torvalds déteste C++ pour cette raison essentiellement (avertissement: le lien implique beaucoup de jurons, dans un style Linus tristement célèbre).

Évidemment, ce sont très des biais biaisés sur le sujet, mais même les partisans de C++ disent souvent que vous ne devriez pas utiliser l'intégralité de l'ensemble des fonctionnalités du langage (encore une fois, consultez les directives de codage de Google; aussi, Bjarne Stroustrup, le créateur de C++, a déclaré publiquement: "Dans C++, il y a un langage beaucoup plus petit et plus propre qui peine à sortir").

Je pense donc qu'il y a un certain mérite à l'idée que les fonctionnalités C++ pourraient être trop faciles à utiliser à mauvais escient, surtout si vous venez d'un arrière-plan Java. De plus, il y a du mérite à l'idée d'atténuer ces problèmes en vous limitant à un sous-ensemble de la langue.

Cependant, décider lequel sous-ensemble à utiliser basé sur un langage différent ne pas semble être la bonne approche, à moins que le "langage différent" soit C, car il y a vraiment est un sous-ensemble de type C du langage C++. (Linus fait référence à cela dans sa diatribe ci-dessus, et Scott Meyers se réfère même à ce sous-ensemble comme un "sous-langage".) Le paradigme d'exécution de Java (garbage collection, exécuté sur une machine virtuelle) est si fondamentalement différent de C++ qu'il est il n'est pas clair qu'il existe des leçons utiles à tirer de l'utilisation de C++ à partir de celui-ci, et comme indiqué ci-dessus, essayer de tirer des leçons sur C++ directement à partir de Java peut conduire à un code très non idiomatique.

Au lieu de cela, essayez de définir votre "sous-ensemble acceptable" de la langue en comprenant comment la langue peut être utilisée de manière idiomatique. Si vous voulez un sous-ensemble assez restrictif qui profite toujours de nombreuses fonctionnalités de C++ au-delà de ce que propose C, la directive de codage Google susmentionnée pourrait être un bon point de départ. Bien sûr, vous obtiendrez les développeurs qui disent qu'il n'y a "aucun argument rationnel" pour certaines des restrictions de Google , mais à moins que vous ne cherchiez à embaucher Alexandrescu loin de son travail sur le langage D (qui lui-même devrait vous dire quelque chose), ce n'est probablement pas grave. C'est certainement mieux que d'essayer de transformer C++ en Java.

Un autre bon point de départ pour un ensemble de directives de code est les nouvelles directives de base C++ , un travail en cours de Bjarne Stroustrup et Herb Sutter.

La seule autre façon de combler les lacunes du C++ est de choisir un langage différent. On dirait que vous aimez Java, et vous pensez qu'il y a une chance que ce projet soit converti en Java éventuellement. Comme indiqué dans une autre réponse, vous pouvez simplement ... commencer avec Java.

Il y a deux raisons pour lesquelles vous pourriez vraiment vraiment avoir besoin pour utiliser autre chose que Java:

  1. Vous avez vraiment besoin des performances d'exécution. Dans ce cas, le traitement du C++ comme c'est Java ne vous aidera probablement pas réellement, car les techniques de type Java telles que les pointeurs partagés dégradent vos performances d'exécution.
  2. Vous avez besoin du logiciel pour travailler sur une plate-forme obscure qui ne prend pas encore en charge la JVM. Dans ce cas, vous êtes probablement coincé avec des langues qui ont des frontends GCC ou Clang. C et C++ sont des candidats évidents, mais vous pouvez également examiner quelque chose comme Rust. (Prise rapide: je n'ai pas utilisé Rust largement, mais il a l'air génial et je suis impatient de travailler sur un projet majeur Rust dès que possible, et je pense que tous ceux qui envisagent de démarrer un projet C++ devraient envisager Rust comme alternative.)

Chaque fonctionnalité spécifique au langage C++ (par exemple: l'héritage multiple) devrait avoir des alternatives à implémenter en Java. Si ce n'est pas le cas, cela signifie que le modèle de conception ou l'architecture de code est problématique.

J'ai déjà abordé cette question un peu, mais j'ai intentionnellement omis votre deuxième phrase.

Je ne suis pas convaincu que quelque chose comme constexpr, qui n'aurait aucun sens dans un langage partiellement JIT comme Java, soit une indication d'architecture invalide. Je suis plus ouvert à l'idée qu'une utilisation excessive de la méta-programmation de modèles pourrait être plus problématique que cela ne vaut, surtout maintenant que constexpr existe pour faire une évaluation de fonction au moment de la compilation, mais cela ressort clairement du cas de constexpr qu'il n'y a pas de défaut design si vous l'utilisez: vous vous assurez simplement que certains calculs se produisent avant même d'exécuter le code, ce qui est une formidable amélioration des performances (voir par exemple cette entrée pour le problème à n corps de The Benchmark Game , qui surpasse toutes les autres entrées sauf une autre écrite en C++, et est deux fois plus rapide que la plus rapide Java = mise en œuvre).

6
Kyle Strand

Non, vous ne devriez généralement pas écrire C++ comme c'était Java, et vous certainement ne pas omettre les fonctionnalités du langage C++ qui ne sont pas présentes en Java.

Pour une chose, Java est un ramasse-miettes et n'a donc pas d'équivalent du mot clé C++ "delete". D'accord, vous implémentez un programme sans supprimer, car selon vos règles, ce n'est pas autorisé.

Félicitations, vous avez maintenant une fuite de mémoire;). Ce n'est pas théorique non plus - j'ai vu cette situation exacte se produire dans un jeu open source.

De même, Java n'a rien de semblable à des pointeurs C++, ce qui exclut un lot de conventions d'appel de fonction courantes .

Il y a des fonctionnalités de C++ que vous devriez peut-être éviter (voir ci-dessous), mais "ne pas être en Java" n'est pas un bon test décisif.


De meilleures directives seraient les suivantes:

  1. Écrivez du code adapté à votre langue, à votre environnement et à vos outils.
  2. Écrivez du code que votre équipe peut comprendre.
  3. Assurez-vous que votre équipe est compétente dans le domaine donné.

L'élément (3) signifie que vous ne devriez pas avoir de code Java programmeurs en C++ sans les former en C++. Il y a quelques différences subtiles mais très importantes qu'ils pourraient ne pas apprendre s'ils essayent de traiter comme un étrange dialecte de Java.

L'élément (2) signifie que, si votre équipe est spécifiquement mal à l'aise avec l'héritage multiple (par exemple), et s'il existe une solution adéquate qui n'utilise pas il, alors il peut être préférable d'utiliser cette solution alternative. Cependant, cela dépend spécifiquement de votre équipe. D'un autre côté, si votre équipe est plus mal à l'aise avec cette solution alternative qu'avec l'héritage multiple, utilisez l'héritage multiple!


Enfin, il existe des fonctionnalités de langage C++ que l'on devrait sans doute éviter. Si vous voulez savoir ce que c'est, demandez aux programmeurs C++ , plutôt qu'aux programmeurs d'un langage différent. Quelques exemples pour commencer sont arithmétique du pointeur (pas de consensus universel) et goto.

6
Ethan Kaminski

Supposons que je suis limité à utiliser C++ par l'environnement dans le projet. Est-il bon d'empêcher l'utilisation de certaines fonctionnalités de langage que C++ possède mais Java n'a pas (par exemple: héritage multiple, remplacement de l'opérateur)?

Non.

Si "par l'environnement du projet" vous êtes limité à utiliser C++, alors il y a peu, voire pas du tout, de point réflexion sur toute autre technologie, peu importe combien vous pourriez personnellement préférer/espérer pour l'utiliser/l'évangéliser.
Que la "technologie X" ou "Y" prenne en charge une fonctionnalité donnée devrait avoir sans aucune incidence sur la façon dont vous construisez votre application C++.
C'est une application C++, probablement pour une "bonne raison" (maintenant ou dans le passé), vous devriez donc l'écrire comme une application C++, en utilisant tout ce que cette "boîte à outils" particulière fournit.

Si et quand il est nécessaire de porter l'application vers une autre technologie, alors (et niquement alors) vous pourriez envisager des fonctionnalités sur d'autres plates-formes. Il ne sert à rien de "vous couper le nez pour contrarier votre visage" au cas où quelque chose pourrait se produire. N'oubliez pas, cependant, que la réécriture en gros est une opération coûteuse et risquée que la direction est peu susceptible d'entreprendre sans une très bonne raison de le faire.

Il y a eu un débat similaire ("à utiliser ou à ne pas utiliser") il y a quelques années dans le monde Visual Basic [.Net], où quelqu'un avait la brillante idée que vous devriez écrire des applications Visual Basic sans utiliser le [langage de base] fonctionnalité fournie par l'espace de noms Microsoft.VisualBasic. Ce serait comme essayer d'écrire une application C++ sans l'espace de noms std ::; D'accord, c'est possible, mais pourquoi diable quelqu'un dans son bon sens prendrait-il la peine de le faire?

5
Phill W.

Les réponses actuelles disent toutes que c'est une mauvaise chose à faire, car vous devriez profiter du langage que vous utilisez et expliquer pourquoi une fonctionnalité C++ n'est pas "mauvaise" simplement parce qu'elle n'est pas en jave. Je vais répondre à cela sous un angle différent.

C'est une chose d'éviter la fonctionnalité C++ complexe comme l'héritage multiple, la surcharge d'opérateur et la définition de votre propre modèle.

Mais tout problème qui fait plus que la tâche la plus simple:

  • alloue de la mémoire,
  • relie cet argent avec des points
  • alors construisez des structures de données
  • permet ensuite à la mémoire d'être réutilisée en toute sécurité pour le faire

Il n'y a pas de sous-ensemble commun de Java et C++ qui permet ce qui précède, donc ce que vous demandez est impossible à faire. (Si vous posiez des questions sur Java et C #, vous auriez beaucoup plus de chances, car ils utilisent tous les deux des collecteurs d'ordures.)

Cependant, vous pourriez exiger que le code soit écrit afin qu'un développeur Java puisse comprendre ce qui se passe (mais pas le "comment" détaillé) et cela serait judicieux.

Vous pouvez également concevoir votre propre langage que vous avez implémenté en C++ et Java .....

2
Ian

Personne ne devrait écrire de code que les autres codeurs ne comprennent pas. Si vous pensez que le verrouillage linguistique est un problème, attendez d'avoir le verrouillage développeur. L'un est plus susceptible de vous tenir en otage que l'autre.

Il n'y a vraiment aucune raison technique. Ce que vous avez créé est un scénario où un langage a été utilisé pour une raison quelconque, mais de nombreux développeurs actuels et éventuellement futurs ne le comprennent pas vraiment.

Je suppose que Java sont susceptibles d'écrire C++ comme ils écrivent en Java, alors pourquoi en faire une règle. Vous découvrirez peut-être certaines fonctionnalités spécifiques C++ qui sont plus faciles à implémenter et à maintenir avec un petite instruction/documentation C++ pour vos développeurs Java que la grosse boule de Java avec lequel ils seraient autrement coincés).

Cela a été un argument sur les problèmes des programmeurs BASIC passant aux langages orientés objet. Ce n'est pas qu'ils implémentent OOP s'entraîne au détriment des nouveaux développeurs qui ne le comprennent pas, mais qu'ils ne l'implémentent pas du tout. S'ils le font, ils se trompent généralement. Si quelque chose est mal fait, il doit être retiré quelle qu'en soit la raison.

À part quelqu'un qui copie et colle du code à l'aveugle, il va le faire dans de nombreux domaines qu'il ne comprend pas de toute façon.

0
JeffO