Je ne connais pas grand chose à propos de D, mais beaucoup, beaucoup de programmeurs C ++ que je connais ne l'aiment pas du tout, et je dois personnellement en convenir - je n'aime pas le look de D et je ne le prendrai pas de plus près.
Afin de comprendre pourquoi D ne gagne pas en puissance, vous devez commencer par comprendre ce qui attire les gens vers C ++. En un mot, la raison numéro un est le contrôle. Lorsque vous programmez en C ++, vous avez un contrôle total sur votre programme. Voulez-vous remplacer la bibliothèque standard? Vous pouvez. Voulez-vous faire des lancers de pointeur dangereux? Vous pouvez. Voulez-vous violer const-correct? Vous pouvez. Voulez-vous remplacer l'allocateur de mémoire? Vous pouvez. Vous voulez copier la mémoire brute sans vous soucier de son type? Si tu le veux vraiment. Voulez-vous hériter de plusieurs implémentations? C'est ton enterrement. Enfer, vous pouvez même obtenir des bibliothèques de récupération de place, comme le collecteur Boehm. Ensuite, vous rencontrez des problèmes tels que les performances, qui suivent de près le contrôle: plus un programmeur a de contrôle, plus il peut optimiser son programme.
Voici quelques éléments que j'ai vus lors d'une petite recherche et de discussions avec quelques personnes qui l'ont essayée:
Hiérarchie de types unifiée. Les utilisateurs C ++ utilisent très rarement l'héritage, la plupart des programmeurs C ++ préfèrent la composition et les types ne doivent être liés par l'héritage que s'il existe une très bonne raison de le faire. Le concept d'objet viole fortement ce principe en liant tous les types. En outre, cela enfreint l'un des principes les plus fondamentaux du C ++: vous n'utilisez que ce que vous voulez. Ne pas avoir le choix d'hériter d'Object, et les coûts qui en découlent, vont tout à fait à l'encontre de ce que C ++ représente comme langage pour donner au programmeur le contrôle de son programme.
J'ai entendu parler de problèmes de fonctions et de délégués. Apparemment, D possède à la fois des fonctions et des délégués en tant que types de fonction appelables à l'exécution, et ils ne sont pas identiques, mais ils sont interchangeables ou ... quelque chose? Mon ami a eu pas mal de problèmes avec eux. C’est définitivement une dégradation de C ++, ce qui est déjà fait std::function
et vous avez terminé.
Ensuite, vous avez la compatibilité. D n'est pas particulièrement compatible avec C ++. Je veux dire, aucun langage n'est compatible avec le C ++, avouons-le, à l'exception de C ++ / CLI, qui est une sorte de triche, mais en tant que barrière à l'entrée, il faut le mentionner.
Ensuite, il y a d'autres choses. Par exemple, il suffit de lire l’entrée Wikipedia.
import std.metastrings;
pragma(msg, Format!("7! = %s", fact_7));
pragma(msg, Format!("9! = %s", fact_9));
printf
est l’une des fonctions les moins sûres jamais conçues, dans la même famille que de gros problèmes comme celui gets
de l’ancienne bibliothèque C Standard. Si vous le recherchez sur Stack Overflow, vous trouverez de nombreuses questions relatives à son utilisation abusive. Fondamentalement, printf
est une violation de DRY- vous donnez le type dans la chaîne de format, puis vous le redonnez quand vous lui donnez un argument. Une violation de DRY dans laquelle, si vous vous trompez, de très mauvaises choses se produisent, par exemple si vous modifiez un typedef d'un entier 16 bits en un 32 bits. Il n’est pas non plus extensible du tout. Imaginez ce qui se passerait si tout le monde inventait ses propres spécificateurs de format. Les iostreams de C ++ peuvent être lents et leur choix d'opérateur peut ne pas être le plus grand. Leur interface peut utiliser le travail, mais leur sécurité est fondamentalement garantie, et DRY n'est pas violé et ils peuvent être étendus facilement. Ce n'est pas quelque chose dont on peut parler printf
.
Pas d'héritage multiple. Ce n'est vraiment pas la méthode C ++. Les programmeurs C ++ s'attendent à avoir un contrôle total sur leur programme et le langage qui applique ce dont vous ne pouvez pas hériter enfreint ce principe. En outre, cela rend l'héritage (encore plus) fragile, car si vous passez d'un type d'interface à une classe parce que vous voulez fournir une implémentation par défaut ou quelque chose, tout le code de votre utilisateur est soudainement cassé. Ce n'est pas une bonne chose.
Un autre exemple est string
et wstring
. En C ++, il est déjà très pénible de devoir convertir entre eux. Cette bibliothèque prend en charge l’Unicode. Cette ancienne bibliothèque C n’utilise que const char*
la même fonction et doit écrire différentes versions de la même fonction en fonction du type d’argument de chaîne souhaité. Notamment, les en-têtes Windows, par exemple, contiennent des macros extrêmement irritantes pour faire face au problème, qui peuvent souvent interférer avec votre propre code. Ajouter dstring
à la combinaison ne fera qu'empirer les choses, car maintenant, au lieu de deux types de chaînes, vous devez en gérer trois. Avoir plus d'un type de chaîne va augmenter les problèmes de maintenance et introduire du code répétitif traitant des chaînes.
Scott Meyers écrit:
D est un langage de programmation conçu pour aider les programmeurs à relever les défis du développement logiciel moderne. Pour ce faire, il favorise des modules interconnectés via des interfaces précises, une fédération de paradigmes de programmation étroitement intégrés, une isolation de threads imposée par le langage, une sécurité de type modulaire, un modèle de mémoire efficace, etc.
L'isolation de thread appliquée par la langue n'est pas un avantage. Les programmeurs C ++ attendent un contrôle total de leurs programmes, et le langage qui force quelque chose n’est certainement pas ce que le médecin a prescrit.
Je vais aussi mentionner la manipulation de chaîne au moment de la compilation. D a la capacité d'interpréter le code D au moment de la compilation. Ce n'est pas un plus. Prenez en compte les énormes maux de tête causés par le préprocesseur relativement limité de C, bien connu de tous les programmeurs vétérans du C ++, puis imaginez à quel point cette fonctionnalité sera utilisée à mauvais escient. La possibilité de créer du code D au moment de la compilation est excellente, mais elle devrait être sémantique et non syntaxique.
De plus, vous pouvez vous attendre à un certain réflexe. D a garbage collection, que les programmeurs C ++ associeront à des langages tels que Java et C # qui lui sont assez directement opposés dans les philosophies, et les similitudes syntaxiques les rappelleront également. Ce n'est pas nécessairement objectivement justifiable, mais c'est quelque chose qu'il convient de noter.
Fondamentalement, il n'offre pas beaucoup de choses que les programmeurs C ++ ne peuvent pas déjà faire. Il est peut-être plus facile d'écrire un métaprogramme factoriel en D, mais nous pouvons déjà écrire des métaprogrammes factoriels en C ++. Peut-être qu'en D, vous pouvez écrire un traceur de rayons au moment de la compilation, mais personne ne veut vraiment le faire de toute façon. Comparé aux violations fondamentales de la philosophie C ++, ce que vous pouvez faire en D n’est pas particulièrement remarquable.
Même si ces problèmes ne sont que des problèmes à la surface, je suis presque sûr que le fait que D ne ressemble pas du tout à C ++ est probablement une bonne raison pour que de nombreux programmeurs C ++ ne migrent pas vers D. Peut-être que D doit faire un meilleur travail de publicité lui-même.