Supposons que je suis limité à l’utilisation de C ++ par l’environnement du projet. Est-il bon d'empêcher l'utilisation de certaines fonctionnalités du langage que C ++ possède mais que Java n'a pas (par exemple: héritage multiple, surcharge d'opérateur)?
Je pense que les raisons sont:
- Comme Java est plus récent que C ++, si Java ne fournit pas une fonctionnalité dont C ++ dispose, cela signifie que la fonctionnalité n'est pas bonne, nous devons donc éviter de l'utiliser.
- Le code C ++ avec des fonctionnalités spécifiques à C ++ (par exemple, les fonctions ami, l'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 deux. Programmeurs C ++ et Java.
- On vous demandera peut-être de convertir le code en Java un jour.
- Le code sans fonctionnalités spécifiques à C ++ est généralement plus facile à gérer
- 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 du code est problématique.
Est-ce vrai?
java
c++
code-quality
ggrr
la source
la source
volatile
, l'accès aux membres d'une classe privée par le paquet, la réflexion / l'introspection, enfin-les blocs, les exceptions vérifiées, etc. Toute la question n'a pas beaucoup de sens ... C ++ et Java sont superficiellement similaires, mais finalement des langages très différents.SomeObject a = previousObject;
fait des choses très différentes en Java et en C ++. En Java, il copie une référence, tandis qu'en C ++, il copie l'objet. En Java, les modifications apportéesa
affectent également l'objet précédent. En C ++, vous avez deux objets distincts.Réponses:
Non, c’est lamentablement et terriblement mal avisé.
la source
operator<<( ostream &, T const & )
est généralement mis en œuvre viafriend
. Voilà le problème avec les déclarations générales sur ce qui constitue une bonne fonctionnalité linguistique et une mauvaise: elles sont de bons conseils, sauf lorsqu'elles ne le sont pas ...Ce n'est pas parce que la syntaxe semble similaire à première vue que les deux langages sont compatibles.
1, 4 et 5 sont vraiment la même question:
Maintenant, je ne suis pas un fan de C ++, mais dire que "Code sans fonctionnalités spécifiques à C ++ est généralement plus facile à gérer" est tout simplement ridicule - croyez-vous vraiment que Java a tout bon, et a pris toutes les bonnes fonctionnalités tout en ignorant toutes les mauvaises? Croyez-vous vraiment qu'il y a quelque chose qui est universellement une fonctionnalité "mauvaise" ou "bonne"? Si c'est le cas, pourquoi n'avons-nous pas une langue purement bonne? Et non, Java n’est certainement pas ce langage. Est-ce que cela signifie que Java et C ++ sont inutiles? Bien sûr que non.
Que se passe-t-il si vos dirigeants décident que vous allez porter en C #, plutôt qu'en Java? Non seulement C # soutien aux opérateurs majeur, mais il est aussi la valeur par défaut - si vous allez obliger les gens à utiliser , par exemple au
obj.Equals(obj2)
lieu deobj == obj2
, les gens vont faire des erreurs tout le temps. Même si vous vous en tenez uniquement aux caractéristiques communes des deux langues, il existe des attentes différentes , une culture différente. Si vous faites quelque chose commeif (myField == null)
en C ++, les gens verront que vous êtes novice immédiatement. Si vous utilisezif (null == myField)
en C #, les gens verront que vous n'êtes pas encore vraiment natif en 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 devrions nous en tenir à du code machine, à un assemblage ou à un COBOL, car pourquoi changer en quelque chose comme Pascal, cela ajoute-t-il de nouvelles fonctionnalités que vos programmeurs devront apprendre? Pourquoi utiliserions-nous quelque chose comme SQL, alors qu'il n'y a même pas de boucles ? Pourquoi utiliserions-nous autre chose que SQL, alors que SQL n'a pas de boucles et que X en a ?
Le code C ++ ne peut certainement pas être maintenu par les programmeurs Java. Je ne comprends pas où vous avez eu cette idée. Que reste-t-il exactement lorsque vous limitez le C ++ aux seules fonctionnalités qui fonctionnent exactement comme en Java? Vous n'allez même pas recevoir d'appels de méthode, pas même d' appels de fonction . 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 sera extrêmement sujette aux erreurs, peu importe ce que vous ferez. Il y a trop de différences. Si vous souhaitez réécrire votre application dans une autre langue, réfléchissez à des moyens raisonnables de tout modéliser, afin de pouvoir remplacer les pièces sans casser le tout. Mais à la fin, YAGNI - peu importe ce que vous ferez, il en coûtera beaucoup pour que votre code soit "prêt à être converti en Java". Ce temps est très probablement mieux dépensé pour ajouter ou améliorer vos fonctionnalités.
Nous utilisons des langages différents car ils nous fournissent un ensemble d’outils différents pour résoudre les problèmes. Si vous avez besoin d'exécutables fonctionnant "partout", utilisez Java. Si vous voulez un code qui compile "partout", C ++ fonctionne bien. Si vous voulez un code facile à comprendre et à analyser, utilisez LISP ou autre. 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 allez en souffrir. Sans parler du fait que lorsque vous embauchez un responsable C ++, il s'exécutera à la seconde où il verra ce code "compatible Java-ish". Et ... le gars de Java va faire la même chose. Vous savez, même en "sachant" à la fois en C ++ et en Java, je courrais comme l'enfer :)
En fait, je devais travailler sur du code C (clair) écrit par un développeur Pascal qui semblait penser comme vous. Il avait l'habitude
#define
de redéfinir C pour qu'il ressemble davantage à Pascal, avec des choses comme "BEGIN se traduit par {". Le résultat était plutôt prévisible - un code que ni les développeurs C ni Pascal ne peuvent comprendre, et plein de bogues qui résultaient de la "abstraction" fuyante de Pascal au-dessus de C. Et Pascal et C sont presque identiques du point de vue actuel. Même aller en C <-> C ++ est beaucoup plus d'une différence, et c'est encore une cacahuète à quelque chose comme C ++ <-> Java.la source
myFunc()
par rapport à(myFunc)
), et cela a une très bonne raison. Les langages basés sur LISP sont toujours très populaires, en particulier auprès des maths / physics. Le principal est que les langages LISPy sont très peu familiers des programmeurs modernes de style C - mais ce n’est pas une raison pour l’ignorer. Scheme, Clojure et, dans une certaine mesure, les langages basés sur ML (OCaml, F # ...) sont vraiment très LISPES.if (myField == null)
queif (myField = null)
, qui compilera très bien C / C ++, mais probablement pas faire ce que vous aviez l' intention. D'autre part,if (null = myField)
jettera une erreur, car vous ne pouvez pas affecter une constante.Je vais répondre à vos questions dans l'ordre.
Oui, toute fonctionnalité non présente en 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 rejoués, leur âme apaisée pour apaiser les dieux du RAID.
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'a été écrit et un code aussi intelligent que vous pouvez écrire est trop intelligent pour être lu. Les révisions de code que votre personnel à la réception ne comprendra pas devraient être rejetées. Pour vous aider, apprenez-leur à programmer Visual Basic 2.0 au cours du week-end, puis émulez leur style de codage dans la langue que vous utilisez.
Vrai! Mais pourquoi s'arrêter à Java? Vous pouvez être invité à convertir le code en base, en assembleur et / ou en 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 associez-y des arguments dans la langue de votre choix.
Maintenant, lorsque vous avez besoin de changer de langue, réécrivez simplement le code qui enveloppe la chaîne Perl.
Il est vrai que le code utilisant moins de fonctionnalités est plus facile à gérer. Et comme toutes les langues sont équivalentes à une machine de Turing, et qu'une machine de Turing possède le moins de fonctionnalités qu'un langage de programmation, demandez à l'interprète perl ci-dessus d'exécuter une machine de Turing (bande et tout) qui résout votre problème.
Les fonctionnalités spécifiques au langage C ++ ont en réalité une utilisation précieuse. Comme ils ne sont pas Java, ils sont anathèmes et ceux qui les utilisent peuvent être considérés comme des hérétiques. Si C ++ n'avait pas ces fonctionnalités de langage, vous ne pourriez pas 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 de Java produit un code qui a jeté la plupart des avantages des deux langages.
Java a été développé partiellement en réaction à certains abus des fonctionnalités C ++. Cela ne veut pas dire que la réaction était justifiée, surtout des années après que les traits aient mûri.
Vous pouvez faire des choses horribles avec la surcharge de l'opérateur; mais aucune langue ne peut empêcher un code horrible d'être écrit dans la langue, à moins que cela 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.
La prudence concernant l'utilisation de fonctionnalités C ++ non disponibles en Java doit être considérée avec prudence. Ce n'est pas parce que votre groupe actuel de développeurs, au niveau de compétences actuel, ne comprend pas qu'une fonctionnalité ne doit jamais être utilisée; En même temps, le fait d’utiliser une fonctionnalité ne signifie pas que vous devriez le faire. Cependant, dans un magasin Java-lourd, les chances sont que la résistance sera plus forte qu'elle ne devrait l'être contre les fonctionnalités non-Java.
La conversion du code entre les langues s’effectue mieux avec une réécriture, quelle que soit leur structure. 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. Le type 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 au moment de l'exécution et éloignent les ressources des ressources. De lourdes vérifications de types statiques signifient que la compilation du code échoue, au lieu de ne pas fonctionner. Les mixages 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 optimisent l'efficacité de la programmation de style fonctionnel (sans effets secondaires). La surcharge des opérateurs réduit le bruit de ligne et rend le code plus proche des calculs qu’il modélise.Attention à la fosse de Turing Tar. Vous pouvez tout implémenter dans n'importe quelle langue (y compris une machine de Turing avec bande crue), mais cela ne veut pas dire que vous devriez le faire . Émuler des fonctionnalités C ++ à l'aide de constructions Java-esque en C ++ est une idée horrible. il en résultera un code inaccessible que personne ne peut lire ni comprendre.
Vous pouvez vous inspirer des conceptions Java et les transférer en C ++. Je suis un grand fan des fonctionnalités du langage Python et de leur implémentation en C ++, parce que j'aime la syntaxe. Mais cela ne signifie pas que j'écrive mes méthodes de classe en tant que méthodes statiques prenant un self explicite, puis écris un wrapper qui lui transmet l'appel de méthode non statique.
Le C ++ moderne ne ressemble pas tellement au langage Java imité et rejeté. Ne vous laissez pas enfermer par les caractéristiques d'une langue. il n'y a pas "une seule langue vraie". En savoir plus sur les nouvelles langues et leurs caractéristiques, et absorber leur caractère distinctif.
la source
Je vais juste répondre à vos raisons:
la source
delete
plus.delete
. D'après mes souvenirs, dans au moins un de ces cas, l'allocation dynamique (new
) n'était pas nécessaire non plus.make_shared
.Java possède des fonctionnalités que C ++ n’a pas, comme un récupérateur de place intégré, rapide et fiable, une hiérarchie d’objets à racine unique et une introspection puissante.
Les autres fonctionnalités de Java sont conçues pour fonctionner avec les fonctionnalités exclusives à Java. De nombreuses omissions de fonctionnalités C ++ par Java sont possibles, car les nouvelles fonctionnalités compensent ce manque. Par exemple, Java n’a pas d’objets alloués à la pile avec des destructeurs déterministes, mais a finalement des blocs (et des ressources d’essai depuis Java 7) et le garbage collector pour compenser ce manque.
C ++ n'a finalement pas de blocs ou de garbage collection. Si vous n'utilisez pas de destructeurs car ils n'existent pas en Java (je ne compte pas les finaliseurs), vous êtes au niveau C de la gestion des ressources (c.-à-d. Tout manuel), sauf que vous ne pouvez même pas grouper votre nettoyage. dans un bloc de nettoyage que vous devez, car Java ne l’a pas non plus. Pensez-vous vraiment que cela améliore la maintenabilité?
Java a une hiérarchie d'objets globale dans laquelle chaque classe dérive finalement d'Object, et les quelques types primitifs peuvent également être automatiquement encadrés dans de telles classes. Cela permet d’écrire des conteneurs d’objets une seule fois, pour conserver les pointeurs sur Object. Java 5 a introduit les génériques, qui suppriment les moulages que nécessitent de tels 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 plans instanciés par le compilateur selon les besoins pour différents types. Allez-vous interdire l’utilisation de modèles (et de macros) et choisir la méthode C pour écrire le même code de conteneur encore et encore pour différents types ou pour utiliser des pointeurs vides? (Attendez, Java n’a pas de pointeur vide)! Êtes-vous sûr que cela augmenterait la maintenabilité?
Une langue décente a une multitude de fonctionnalités conçues pour fonctionner ensemble. En interdisant les fonctionnalités du langage A parce que le langage B ne les possède 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 tout cohérent.
Cela ne veut pas dire que vous ne devez pas restreindre les fonctionnalités autorisées de C ++. Le C ++ est un langage grand, développé historiquement, qui permet au programmeur de faire ce qu'il veut au-dessus de la sécurité et de la facilité d'utilisation, et toutes ses fonctionnalités, dans toute leur flexibilité, ne sont pas nécessaires pour construire de bons programmes. De nombreuses normes de codage limitent l'utilisation de certaines fonctionnalités. Par exemple, les directives de Google interdisent généralement 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 uniquement dans le cadre de C ++.
la source
Object
est à peu près unvoid*
pour la plupart des utilisations - Pourtant, beurk.finally
n'est pas un remplacement pour eux. Les deux langues sont fondamentalement différentes.J'ai débattu de la possibilité de publier une autre réponse alors que vous avez déjà un numéro qui atteint des conclusions qui semblent tout à fait raisonnables: votre idée est essentiellement une catastrophe imminente. Je pense cependant qu'ils n'ont pas réussi à indiquer certaines raisons extrêmement pertinentes derrière cette conclusion.
Les différences entre Java et C ++ sont beaucoup plus profondes que les détails sur lesquels vous semblez vous être concentré.
Par exemple, vous parlez d'interdire l'héritage multiple en C ++. Premièrement, je ferai remarquer que cela manque simplement le point. Java définit les "interfaces" comme des éléments distincts 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. Le C ++ analogique le plus proche fournit une interface de mise en œuvre en Java est hérite d' une autre classe. En tant que tel, pour maintenir les deux alignés raisonnablement bien, vous devez probablement utiliser l'héritage multiple en C ++, mais vous souhaitez limiter certaines de ces classes de base de la même manière que Java restreint une interface par rapport à une classe (c'est-à-dire qu’il spécifie les signatures de fonction mais, du moins dans la plupart des cas, pas les implémentations).
C'est à peine effleurer la surface des différences réelles entre les deux cependant. En réalité, là où le code Java est susceptible de définir des interfaces et des classes qui implémentent ces interfaces, le code C ++ est beaucoup plus susceptible de définir des modèles pouvant fonctionner avec toutes les classes répondant à ses exigences (pas uniquement celles définies spécifiquement pour implémenter l'interface). (s) il spécifie).
Si vous voulez honnêtement un code qui est fondamentalement "Java en utilisant la syntaxe C ++", vous devrez certainement interdire tout ce qui est similaire à ce dernier. Vous devrez limiter votre utilisation des modèles à peu près au niveau de "conteneur de T" pris en charge par les génériques Java. Malheureusement, le code C ++ deviendra un tel désordre que personne ne peut le conserver 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 pouvant être converti dans une autre langue à l'avenir, efforcez-vous de le rendre aussi propre et lisible que possible. L'idéal est d'écrire du pseudo-code tout en l'exécutant. Des approches C ++ modernes bien écrites et qui idéalisent beaucoup plus étroitement que le sous-ensemble que vous avez suggéré. Quelle que soit la façon dont vous l'écrivez, si vous traduisez jamais en Java, vous devrez traduire le code, pas seulement la syntaxe des instructions individuelles.
la source
Si vous envisagez d'écrire du code dans la langue X, passez le temps nécessaire pour bien apprendre le langage et utiliser 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 "mot à mot" d'une langue à une autre, que ce soit du japonais vers l'anglais ou de Java vers C ++. Il est bien préférable de commencer par bien comprendre le problème et d’exprimer la solution de la manière la plus naturelle pour le langage utilisé.
Il y a des années, j'ai vu un programme C ne comportant aucune indentation et chaque déclaration commençait à la colonne 7, car l'auteur du code était un programmeur Fortran qui utilisait C. D'autres programmeurs Fortran étaient nerveux à propos de ces choses nouvelles appelées pointeurs. Je n'avais pas le cœur de mentionner les pointeurs entre eux, je pense qu'ils se seraient évanouis sur place.
Imaginez embaucher quelqu'un pour maintenir ce code à l'avenir. S'il s'agit d'un bon code C ++, vous pourrez embaucher un développeur C ++ compétent et ils devraient pouvoir s'y retrouver. S'il s'agit de "Java en C ++", ni les développeurs C ++ ni Java n'auront facilement la compréhension du code.
la source
Toutes vos raisons peuvent être réfutées:
Cela ne signifie pas que la fonctionnalité n'est pas bonne (aucune fonctionnalité ne peut être intrinsèquement mauvaise). Cela signifie simplement que la fonctionnalité a été fréquemment mal utilisée (ou impossible à mettre en œuvre en raison de concepts fondamentaux, tels que les pointeurs directs vs le ramassage des ordures). Par définition, Java est conçu pour être plus facile et plus convivial pour les programmeurs, d’où la suppression des fonctionnalités qui se sont révélées facilement abusables.
Oh ça peut l'être? Voyons le code C ++ le plus simple:
Oups, aucune fonctionnalité "spécifique à une langue" n'est utilisée, pourtant, les développeurs Java ne la maintiennent pas! Parce qu'en Java, vous déréférencez avec "." alors qu'ici c'est "->.
Ou C #. Ou Haskell. Ou Python. Ou Ruby. Ou COBOL (oui, vous pouvez!). Comment pouvez-vous dire l'avenir?
Tout à fait opposé. Chaque fonctionnalité a été introduite afin de rendre la programmation plus facile et donc plus facile à gérer. Ex: prenez un programme fonctionnant sur des flotteurs. Maintenant, mettez à niveau pour gérer les nombres complexes. Une surcharge d'opérateur à la rescousse!
Mais Java a plusieurs héritages! Cela s'appelle "interface". L'implémentation de Java est une solution de contournement problématique pour éviter le diamant redouté causé par tout ce qui en dérive
Object
. Cela se fait en introduisantinterface
quel est le seul but est d'être quelque chose qui ne dérive pasObject
. 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 ++ devait toujours résoudre un problème qui n'existait jamais.
Vous avez également mentionné très peu "de choses que C ++ possède mais que Java ne fait pas". L'une des plus grandes différences entre C ++ et Java réside dans le contrôle de la disposition de la mémoire. Vous pouvez créer un tableau de pointeurs sur des objets (comme en Java) OU 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 Java, quelque chose d'aussi caché et subtil que celui-ci se placerait sur ma liste beaucoup plus haut que ce qui est évident et reconnaissable à première vue, comme l'héritage multiple ou les opérateurs surchargés.
Ligne de fond: Un code propre est un code propre. Java ou C ++ - même différence. Reste simple. Les complications inutiles sont la principale cause de mauvais code.
la source
Non, vous ne devez généralement pas écrire en C ++ comme s'il s'agissait de Java, et vous ne devez absolument pas omettre les fonctionnalités du langage C ++ qui ne sont pas présentes en Java.
D'une part, Java est un déchet ordonné et n'a donc pas d'équivalent du mot clé "delete" de C ++. Bon, vous implémentez donc un programme sans suppression, car selon vos règles, il 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 se produire dans un jeu open source.
De même, Java n’a rien de comparable aux pointeurs C ++, ce qui exclut de nombreuses 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.
Les meilleures directives seraient les suivantes:
Item (3) signifie que vous ne devriez pas avoir de code pour programmeurs Java en C ++ sans les avoir formés en C ++. Il y a des différences subtiles mais très importantes qu'ils pourraient ne pas apprendre s'ils essayaient de le traiter comme un étrange dialecte de Java.
L'élément (2) signifie que, si votre héritage est particulièrement inconfortable pour votre équipe (par exemple) et s'il existe une solution adéquate qui ne l'utilise pas, il peut être préférable d'utiliser cette solution alternative. Cela dépend toutefois de votre équipe. D'autre part, 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 ++ qui, on peut le nier, devraient être évitées. Si vous voulez savoir ce que c'est, demandez aux programmeurs C ++ , plutôt qu'aux programmeurs d'un autre langage. Quelques exemples pour commencer sont l' arithmétique de pointeur (pas de consensus universel) et goto.
la source
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 à vos déclarations individuellement.
Cela a été assez bien répondu: Java n'est pas "la bonne partie" de C ++, et il n'y a aucune raison de le penser.
En particulier, bien que les mérites de chaque fonctionnalité C ++ individuelle soient discutables, de nombreuses fonctionnalités de C ++ 11 / C ++ 14 qui ne font pas partie de Java ne sont pas nécessairement exclues car les concepteurs Java pensaient qu’elles étaient une mauvaise idée. À titre d’exemple, jusqu’à la version 8, Java n’avait pas de lambda, mais ils ont été introduits au C ++ dans la norme C ++ 11. Avant Java 8, votre hypothèse selon laquelle les fonctionnalités C ++ manquantes dans Java étaient absentes de par leur conception, car elles ne sont "pas bonnes" aurait laissé entendre que lambdas en tant que fonctionnalité de langage n'est "pas bon" (à la grande horreur des LISPers, probablement assez horrifié d'apprendre que vous semble réellement comme Java). Mais maintenant, les concepteurs Java ont mis leur Stamp of Approval (TM) sur les lambdas, ils sont donc maintenant une bonne chose.
Pour aller un peu plus loin, même dans 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 de la machine virtuelle Java plutôt qu'à une décision consciente que l'approche plus flexible est mauvaise pour un client. perspective de conception de la langue.
C'est la principale chose à laquelle je voulais réagir.
De manière générale, il peut être intéressant d'obtenir des critiques de code de programmeurs qui ne connaissent pas très bien le langage que vous utilisez. Ils peuvent vous donner de précieux commentaires sur la clarté de vos noms et commentaires de fonction / méthode, et (comme votre question l’implique correctement), si la langue est similaire à une ou plusieurs langues qu’ils connaissent déjà, ils pourront peut-être suivre le flux de base du programme. et potentiellement attraper des erreurs de logique.
Cependant, il est pas le cas que ce genre d'examen ne sera jamais « aussi bien que » ou « équivalent à » examen des développeurs qui savent en fait la langue que vous utilisez. Cela est essentiellement dû au fait que donner à une langue l' apparence d'une autre dissimulera en général des différences subtiles, tandis que se faire se comporter comme une autre (en particulier dans le cas de C ++ et de Java) peut être non idiomatique pour le langage et / ou peut-être encore trop déroutant pour les relecteurs.
Tout d’abord, réfléchissons à ce que cela signifierait de faire en sorte que C ++ "ressemble" à Java. Comme un cas simple, vous pouvez utiliser
new
pour instancier des objets, comme en Java:Mais les objets instanciés de cette façon utilisent
->
au lieu d'.
appeler des méthodes, donc si vous voulez que les appels de méthode ressemblent à Java, vous devez plutôt écrire:Mais cela n’est pas idiomatique; en particulier, la mémoire doit ensuite être nettoyée à l'aide d' un code
delete &foo
que certains développeurs expérimentés en C ++ pourraient même ne pas comprendre . De toute façon, il y a de drôles de symboles non-Java qui parsèment, donc nous ne pouvons pas vraiment faire en sorte que le langage "ressemble" à Java. (Vous pouvez éliminer en*new
utilisant#define New *new
, ou, pire,#define new *new
mais ensuite vous implorez simplement que vos collègues développeurs vous haïssent.) 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 pas vraiment faire en sorte que l’utilisation des objets ressemble à celle qu’elle a en Java sans fuites de mémoire.Mais le C ++ moderne inclut des pointeurs partagés intelligents, qui se comportent beaucoup comme les références de variable gérées par la mémoire de Java. Donc, partout en Java que vous pourriez écrire
Foo foo = new Foo();
, vous pouvez écrire:Vous utilisez maintenant une fonctionnalité de langage qui ressemble beaucoup à Java sous le capot. Mais tout à coup, vous avez beaucoup à expliquer aux relecteurs non-C ++: qu'est-ce que c'est
shared_ptr
? Quels sont les subtils "pièges" demake_shared
? (Il utilise une transmission parfaite, qui présente certains cas d'échec et peut conduire à l'appel du "mauvais" constructeur.) Pourquoi les méthodes doivent-elles être appelées avec->
, mais l'utilisation.
de certaines méthodes est autorisée par le compilateur? (shared_ptr
a ses propres méthodes.) Si la méthodeFoo::reset(void)
existe, un développeur non averti peut essayer de l'appelerfoo.reset()
, qui (s'il n'y a qu'un seul pointeur partagé pointant vers cette instance ouFoo
lorsque l'appel a lieu) supprimera la mémoire sous-jacente et sera annuléefoo
, et Les développeurs Java ne risquent pas d'attraper ce problème.De plus, C ++ a beaucoup de pièges qui sont spécifiques à la langue. Autant que je sache, la plupart des développeurs C ++ apprennent à gérer ces écueils en développant progressivement leur propre langage pour des pratiques C ++ "sûres", ce qui est souvent assez unique pour eux ou pour leur équipe de développement (voir par exemple la réponse existante qui mentionne la Les pratiques de codage de Google et le commentaire à ce sujet indiquant 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), se heurtent généralement à une variation de "bien, arrêtez de le mal utiliser". Je sais que cela est une vue 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 langue, mais il ne semble être une certaine attitude défensive vis-à-vis, par exemple, d’un comportement indéfini (voir par exemple une grande partie de la discussion dans le 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 est tout à fait valable - même louable - d'essayer de prendre en compte ce qui pourrait arriver à votre code à l'avenir pendant la phase de conception.
Mais, premièrement, cette considération particulière semble être une possibilité lointaine: le code est généralement soit réutilisé tel quel (par exemple, vous pouvez brancher tout ou partie du code C ++ actif dans un logiciel Java futur utilisant une interface JNI), ou le réécrire entièrement à la place. que directement manuellement "transcrit".
Et, deuxièmement, vous dites plus tard:
Cela annule essentiellement votre point "converti en Java". Si le logiciel est écrit en C ++ idiomatique puis converti en Java idiomatique, il n’ya aucune raison de s’attendre à ce que cette conversion soit (ou pourrait!) Être réalisée en appliquant un mappage précis un à un des fonctionnalités C ++ aux fonctionnalités Java.
Vous ne comprenez pas ce que vous voulez dire ici, mais je suis en quelque sorte d’accord avec une partie de ceci: à moins que vous ne soyez très prudent, et même lorsque vous êtes prudent, les fonctionnalités C ++ peuvent entraîner des problèmes de maintenabilité. Le C ++ FQA Lite (un site Web critique du langage et de ses adeptes de quelqu'un qui semble au moins le comprendre assez bien) déclare que
VEUILLEZ NOTER: Si vous êtes un fan de C ++ et que vous répondez à ce point dans ma réponse, vous êtes enclin à passer directement aux commentaires pour faire valoir que l'auteur de la FQA ne comprend pas réellement le C ++ ou qu'il est fallacieux dans la plupart de ses arguments. , notez que (1) deux phrases exactement après que je le cite, je reconnais que la FQA est une source très partiale, et (2) peu importe ce que je veux dire si l’auteur de la FQA comprend ou non C ++ et je n'essaie pas de critiquer le C ++, et vous devriez lire le reste du message sans supposer que je suis anti-C ++ simplement parce que j'ai cité la FQA. Fin de la note.
De même, Linus Torvalds déteste le C ++ pour cette raison (avertissement: link implique beaucoup de jurons, dans le style tristement célèbre de Linus).
De toute évidence, ces questions sont très biaisées, mais même les partisans du C ++ disent souvent qu'il ne faut pas utiliser l'intégralité de l'ensemble des fonctionnalités du langage (à nouveau, reportez-vous aux consignes de codage de Google; Bjarne Stroustrup, créateur du C ++, par exemple). , a publiquement déclaré: "Dans C ++, il existe un langage beaucoup plus petit et plus propre qui a du mal à sortir").
Je pense donc que l’idée selon laquelle les fonctionnalités C ++ sont trop faciles à utiliser, en particulier si vous venez de l’arrière-plan Java, a du mérite. En outre, l’idée d’atténuer ces problèmes en se limitant à un sous-ensemble de la langue présente des avantages.
Cependant, décider quel sous-ensemble utiliser en utilisant un langage différent ne semble pas être la bonne approche, à moins que le "langage différent" soit C, car il existe vraiment un sous-ensemble du langage C ++ ressemblant à C. (Linus fait référence à cela dans son discours ci-dessus, et Scott Meyers appelle même ce sous-ensemble un "sous-langage".) Le paradigme d'exécution de Java (ramassé, fonctionnant sur une machine virtuelle) est tellement différent du C ++ qu'il est il n’est pas clair qu’il existe des leçons utiles à tirer de l’utilisation de C ++, et comme indiqué ci-dessus, essayer de tirer des leçons de 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" du langage sur une compréhension de la façon dont le langage peut être utilisé idiomatiquement. Si vous souhaitez un sous-ensemble assez restrictif qui tire toujours parti de nombreuses fonctionnalités de C ++ autres que celles proposées par C, la directive de codage susmentionnée de Google pourrait être un bon point de départ. Bien sûr, vous aurez des développeurs qui disent qu’il n’ya "pas d’argument rationnel" pour certaines restrictions de Google , mais à moins que vous ne cherchiez à engager Alexandrescu hors de son travail sur le langage D (qui devrait vous dire quelque chose), probablement d'accord. C'est certainement mieux que d'essayer de transformer le 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 réalisation de Bjarne Stroustrup et Herb Sutter.
Le seul autre moyen de remédier aux faiblesses du C ++ consiste à choisir un langage différent. On dirait que vous aimez Java et que vous pensez qu'il est possible que ce projet soit éventuellement converti en Java. Comme indiqué dans une autre réponse, vous pouvez simplement ... commencer par Java.
Il y a deux raisons pour lesquelles vous pourriez vraiment avoir besoin d'utiliser autre chose que Java:
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 du genre
constexpr
, ce qui n'aurait aucun sens dans un langage partiellement JIT comme Java, est une indication d'architecture invalide. Je suis plus ouvert à l'idée que l'utilisation excessive de la méta-programmation de gabarits puisse poser plus de problèmes qu'elle n'en vaut la peine, en particulier à l'heureconstexpr
actuelle pour l'évaluation des fonctions au moment de la compilation, mais il est clairconstexpr
qu'il n'y a pas de défaut de conception si utilisez-le: vous vous assurez simplement que certains calculs sont effectués avant même d'exécuter le code, ce qui représente un gain de performances impressionnant (voir, par exemple, cette entrée pour le problème à n corps de The Benchmark Game , qui surpasse toutes les entrées, sauf une autre écrit en C ++,la source
import SomeVeryBasicPackage
et juste faire cela ? » Poser une question avancée et la première réponse est presque inévitablement le long des lignes de « Pourquoi ne pas vousimport SomeMagicalPackage
et faites juste que ? »Non.
Si "par l'environnement du projet" vous êtes limité à utiliser le C ++, alors il est inutile de penser à une autre technologie, même si vous préférez / espérez personnellement l'utiliser / l'évangéliser.
Que "Technology X" ou "Y" prenne en charge une fonctionnalité donnée ne devrait avoir aucune incidence sur la manière dont vous construisez votre application C ++.
C'est une application C ++, vraisemblablement pour une "bonne raison" (maintenant ou dans le passé), vous devriez donc l'écrire en tant qu'application C ++, en utilisant ce que cette "boîte à outils" fournit.
Si et quand il est nécessaire de porter l'application vers une autre technologie, alors (et seulement alors), vous pourriez envisager des fonctionnalités sur d'autres plates-formes. Il ne sert à rien de "se couper le nez pour contrarier votre visage", au risque que quelque chose se produise. Rappelez-vous cependant que la réécriture en gros est une opération coûteuse et risquée que la direction ne pourra probablement pas entreprendre sans une très bonne raison de le faire.
Il y a quelques années, il y avait eu un débat similaire («utiliser ou ne pas utiliser») dans le monde Visual Basic [.Net], où quelqu'un avait eu la brillante idée d'écrire des applications Visual Basic sans utiliser aucun des [langages de base]. fonctionnalité fournie par l'espace de noms Microsoft.VisualBasic. Ce serait comme essayer d'écrire une application C ++ sans le std :: namespace; OK, c’est possible, mais pourquoi, sur terre, est-ce que quelqu'un de sensé pourrait en prendre la peine?
la source
Microsoft.VisualBasic
espace de noms est un peu exagéré. Cela fait de nombreuses années que je ne l'ai pas utilisé pour la dernière fois, mais au moins au début, il s'agissait principalement d'une compatibilité en amont avec VB6 (et / ou de faire en sorte que les programmeurs VB6 se sentent «chez eux»); il fournissait principalement des fonctionnalités déjà disponibles dans le reste du cadre sous une forme plus moderne (et mieux intégrée); il était donc rarement logique de l'utiliser dans les nouveaux projets. Au contraire, l'std::
espace de noms est l'endroit où réside la bibliothèque standard entière. L'éviter, ce serait comme éviter l'ensemble du BCL dans .NET.Les réponses actuelles disent toutes que c'est une mauvaise chose à faire, car vous devriez tirer parti du langage que vous utilisez et également 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.
Éviter les fonctionnalités C ++ complexes telles que l'héritage multiple, la surcharge des opérateurs et la définition de votre propre modèle est une chose.
Mais tout problème qui fait plus que la tâche la plus simple:
Il n'y a pas un sous-ensemble commun de Java et C ++ qui permette ce qui précède, par conséquent, 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 éboueurs.)
Cependant, vous pourriez exiger que le code soit écrit de manière à ce qu'un développeur Java puisse comprendre ce qui se passe (mais pas le "comment" détaillé), ce qui serait judicieux.
Vous pouvez également concevoir votre propre langage que vous avez implémenté à la fois en C ++ et en JAVA .....
la source
Personne ne devrait écrire un code que les autres développeurs ne comprennent pas. Si vous pensez que le verrouillage linguistique est un problème, attendez qu'il soit verrouillé par le 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 dans lequel un langage a été utilisé pour une raison quelconque, mais que de nombreux développeurs actuels et peut-être futurs ne le comprennent pas vraiment.
J'imagine que les développeurs Java sont susceptibles d'écrire le C ++ comme ils l'é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 à gérer avec un peu d’instructions / documentation C ++ pour vos développeurs Java que la grosse boule de désordre Java avec laquelle elles seraient autrement coincées.
Cela a été un argument sur les problèmes des programmeurs BASIC passant à des langages orientés objet. Ce n'est pas qu'ils mettent en œuvre des pratiques de POO au détriment des nouveaux développeurs qui ne le comprennent pas, mais qu'ils ne le mettent pas du tout. S'ils le font, ils se trompent généralement. Si quelque chose est mal fait, il faut l’enlever quelle que soit la raison.
Autre que quelqu'un copiant et collant aveuglément du code, il le fera dans de nombreux domaines qu'il ne comprend pas de toute façon.
la source