May 14, 2023
Si vous voulez livrer rapidement, vos tests ont le dernier mot
Articles de la page d'accueil d'InfoQ Si vous voulez
Articles de la page d'accueil d'InfoQ Si vous voulez livrer rapidement, vos tests ont le dernier mot
06 juin 2023 23 min de lecture
par
Jorge Fernández Rodríguez
revu par
Matt Campbell
Je pense que vous conviendrez que le génie logiciel est spécial par rapport à d'autres professions. Les choses changent radicalement et rapidement. Il faut beaucoup de puissance cérébrale juste pour rester à jour.
Peut-être qu'en conséquence de cela, nous nous accrochons à certaines pratiques ou idées générales bien établies (même si elles nous causent des problèmes ou ne correspondent pas à certains cas). Ces pratiques essaient de couvrir la plupart des cas, mais ne peuvent pas tous les couvrir. Cependant, ces pratiques nous réconfortent. Nous avons besoin d'avoir quelque chose qui ne change pas, qui se sente en sécurité et qui libère notre esprit du fardeau de penser si cela convient ou non. Nous passons en mode pilote automatique.
Le problème avec cela est que nous voulons que le développement logiciel se comporte comme une chaîne de montage : une fois la chaîne de montage construite, nous n'y touchons jamais. Nous fonctionnons tout le temps de la même manière. Cela peut fonctionner avec nos voies CI/CD pendant un certain temps, mais malheureusement, cela ne fonctionne pas toujours bien avec notre code.
Codez, déployez et mettez à l'échelle Java à votre façon. Microsoft Azure prend en charge votre charge de travail avec de nombreux choix, que vous travailliez sur une application Java, un serveur d'applications ou un framework. Apprendre encore plus.
C'est même pire parce que parfois le message est transmis tellement de fois qu'il en perd son essence et à un moment donné, on prend cette pratique comme faisant partie de notre identité, on la défend, et on ne laisse pas entrer des points de vue différents. Surtout s'ils demandent apparemment plus d'efforts. D'autres fois, nous voulons simplement nous intégrer et ne pas suggérer de nouvelles idées.
Lorsque nous codons, nous devons lutter contre cela et réfléchir dans chaque cas si la pratique correspond au scénario actuel. Considérez les « meilleures pratiques » comme des « meilleures pratiques génériques ».
Un exemple de cela est les nombreuses façons dont agile peut être mal interprété. L'essence a été perdue dans certains cas.
Dans cet article, je soutiens que l'essence de l'agilité est souvent perdue parce que la mise en œuvre de l'agilité se concentre souvent sur les mauvaises choses. Par définition, quelque chose d'agile peut facilement changer de direction et réagir rapidement aux changements.
Nous essayons d'atteindre cette réactivité avec des pratiques de différentes natures : techniques, comme le CI/CD (Intégration Continue/Déploiement Continu), et stratégiques, comme le développement par itérations. Cependant, nous oublions souvent l'agilité lorsque nous traitons du cœur du développement logiciel : le codage. Imaginez que vous préparez votre repas ou dessert préféré sans l'ingrédient principal de la recette. C'est ce que nous faisons lorsque nous recherchons l'agilité sans tenir compte du code.
Cela peut arriver parce que l'amélioration du code semble effrayante et compliquée ou qu'il peut être facile d'entrer dans des terriers de lapin (tout cela peut être facilité). C'est peut-être simplement parce qu'il n'est pas facile de voir l'effet négatif que certaines solutions ont sur notre maniabilité ; transformer les développements futurs en cauchemar : le contraire de l'agilité. Au lieu de se concentrer sur le code, trop d'attention est portée à la perfection dans nos processus (de méthodologies telles que Scrum), qui sont moins importants et tentent de résoudre le problème sans s'attaquer au problème principal.
Enfin, je suggère que nous devons donner plus de visibilité à l'effet que le code a sur les développements futurs, (et par conséquent, l'avenir de l'entreprise). Espérons que l'IA puisse nous aider à quantifier cela avec quelque chose comme un coefficient qui, non seulement nous indiquerait la qualité, mais aussi prédirait à quel point le développement sera plus lent en fonction de nos choix potentiels. Je pense que quelque chose comme ça pourrait aider les entreprises à réaliser qu'elles doivent investir dans le développement durable. Les discussions sur le moment où s'attaquer à la dette technique feraient partie de l'histoire.
Dans cet article, je vais me concentrer sur une pratique de codage qui n'est souvent pas assez remise en question et qui joue un rôle essentiel dans l'agilité : la manière conventionnelle de tester.
Je présenterai également "l'immunité au changement", une stratégie que j'ai récemment découverte et qui peut vous aider à atteindre des objectifs et à changer de nombreuses habitudes ; non seulement les habitudes de codage, mais aussi d'autres habitudes dans votre vie. De plus, cela illustre un des points que j'évoquais dans mon article précédent : on veut atteindre la maniabilité en changeant certaines pratiques/habitudes mais on se sabote inconsciemment car on ignore le rôle que joue le codage dans l'atteinte de cet objectif.
Espérons que nous soyons d'accord sur le fait que les (bons) tests automatisés nous apportent un énorme avantage : nous pouvons modifier le code et vérifier rapidement qu'aucune fonctionnalité existante ne casse. Les tests sont notre filet de sécurité.
Cependant, ils ne sont pas bon marché, donc les coûts doivent être compensés, et cela ne se produit qu'après un certain temps. Plus il fonctionne, plus nous en tirons de valeur. Mais si nous modifions le test, le "compteur de bénéfices" du test se remet à zéro.
En plus de compenser les coûts, nous devons considérer une autre chose : lorsque nous créons un test, nous faisons de notre mieux pour garantir que le test est correct, mais nous ne pouvons pas être sûrs à 100 %. Si nous pouvions être sûrs que tout code que nous écrivons est correct, nous n'aurions même pas besoin de tests en premier lieu, n'est-ce pas ?
Les tests ne nous donnent confiance qu'avec le temps. Considérez ce qui suit : imaginez qu'à chaque fois qu'un test s'exécute, il nous apporte un point de confiance. S'il tourne 1000 fois, on gagne 1000 points de confiance.
Si à un moment donné on découvre un bug dans le test, on perd les 1000 points de confiance. Nous pensions qu'il nous protégeait, mais ce n'était pas le cas.
De la même manière, si nous devons refactoriser la logique vérifiée par le test et que le test se casse, nous ne pouvons plus être sûrs que la logique métier ou le test sont corrects. Nous perdons également les points de "confiance" que nous avons accumulés. C'est comme si nous construisions un nouveau filet de sécurité.
C'est un investissement dans l'avenir. Les humains et les entreprises pensent rarement aux investissements à long terme, mais heureusement, les avantages des tests automatisés sont largement acceptés (bien que de temps en temps j'entende des histoires de quelqu'un qui n'adopte toujours pas les tests automatisés).
D'autres investissements à long terme, comme le maintien de la flexibilité du code grâce à des refactorisations, ne sont malheureusement pas aussi largement adoptés. Espérons que les idées pas du tout innovantes mentionnées dans cet article aident à éliminer les obstacles à cela.
Chaque fois que j'ajoute de nouvelles fonctionnalités, je suis reconnaissant pour les tests qui ont été écrits, en particulier dans les gros services avec beaucoup de fonctionnalités. Je ne peux pas imaginer devoir vérifier chacun d'entre eux manuellement. Ce serait un non-sens, vu à quel point je serais plus lent.
Cependant, ils peuvent également présenter des inconvénients si nous ne suivons pas la stratégie appropriée à notre cas. Une stratégie de test inappropriée peut ralentir la livraison et détériorer le bonheur et l'expérience des développeurs.
Découvrons-les ensemble avec les questions suivantes:
Tous vos tests unitaires vérifient-ils les classes ou les méthodes de manière isolée ?
Si la réponse est oui, et que vous vous moquez fortement des dépendances, vous en aurez peut-être assez de préparer une simulation après l'autre, pour découvrir dans certains cas que la simulation n'était pas assez réelle et que la logique ne fonctionne pas comme elle le devrait. J'espère que vous le découvrirez avant de passer à la production et que vous n'aurez pas à faire beaucoup de changements.
Avez-vous parfois l'impression que les tests restreignent la façon dont vous pouvez modifier le code ?
Je suppose que c'est un oui aussi. Parfois, le code existant ne correspond plus à la nouvelle fonctionnalité ou devient trop compliqué. Vous décidez de le refactoriser. Cela prend 10 ou 15 minutes car c'est un petit changement et BOOOOM, de nombreux tests ne compilent plus ou échouent. Adapter les tests et le faire prend un temps déraisonnable, beaucoup plus long que d'adapter le code. Vous finiriez par passer des jours pour un changement de 10 à 15 minutes. POURQUOI???!!!! Le comportement n'a pas changé.
Si la fonctionnalité n'est pas modifiée, idéalement, les tests ne devraient pas se casser. Si vous adaptez les tests, pouvez-vous sauter à nouveau sur le filet de sécurité ? Et rappelez-vous que le « compteur de bénéfices » et le « compteur de confiance » des tests sont réinitialisés lorsque vous les modifiez.
Nous verrons plus tard que dans de nombreux cas, nous pouvons éviter cette situation et éviter d'ajouter des hacks. Parce que les hacks nous donnent l'illusion que nous livrons rapidement, du moins au début. Mais il s'agit d'un investissement de courte durée et qui nous frappera : le code devient rigide et après quelques mois, nous passerons beaucoup plus de temps à comprendre le code et à le modifier. Même après quelques jours, nous ne nous souviendrons pas de ce que fait le code. Et cela ira de mal en pis, sans même penser aux mauvaises nouvelles recrues qui ont encore moins de contexte. Cependant, si votre base de code est jonchée de hacks, vous n'aurez pas à vous en préoccuper trop longtemps, car ils ne resteront probablement pas longtemps.
Votre suite de tests comporte-t-elle de nombreux tests d'intégration et e2e (de bout en bout) ?
Les tests d'intégration ont tendance à survivre à plus de changements que les tests unitaires, mais ils sont beaucoup plus lents.
Si vous avez développé de nombreux tests e2e, vous avez probablement vécu une expérience douloureuse :
La douleur s'aggrave si les tests e2e impliquent de nombreux composants connectés via le réseau (mais s'il vous plaît, ne construisez pas de Big Ball of Mud pour éviter cela).
Ainsi, une mauvaise stratégie de test à elle seule peut ruiner votre livraison. Les tests unitaires peuvent "nous empêcher" d'écrire un meilleur code. Peu importe si vos rituels "agiles" sont au rendez-vous. Vous avez envie d'avoir une camisole de force (ou plus d'une, si nous devenons paranoïaques en ajoutant de plus en plus de tests, en essayant d'être sûr à 200%). Pendant ce temps, les dents acérées des concurrents, qui peuvent s'adapter plus rapidement aux changements de l'océan du marché, se rapprochent de nous, et la camisole de force ne vous laissera même pas bouger. Ils ne seront pas non plus utiles contre ces dents.
Donc, quelques questions clés que j'aimerais que vous vous posiez après avoir lu ceci :
Regardons une simplification d'un scénario que je vois souvent. Une application backend implémentée à l'aide de Spring. Je vois généralement un mappage 1-1 entre les classes de production et de test, comme dans l'image :
[Cliquez sur l'image pour la voir en grand format]
La "classe avec la logique principale" est souvent appelée un "service". Parfois, le service est spécifique par entité de domaine, parfois le service représente un concept plus abstrait.
Parfois, la "logique principale" s'étend également aux composants du framework tels que les contrôleurs ou les écouteurs. Non seulement la ligne entre le framework et la logique métier devient floue, mais aussi la ligne qui distingue ce qui peut être mieux testé dans les tests unitaires ou les tests d'intégration. En conséquence, je vois parfois des scénarios similaires dans les tests unitaires et les tests d'intégration. C'est inutile et coûteux.
Avoir un test unitaire par classe a du sens lorsque les classes contiennent des fonctionnalités complexes. Lorsque cela se produit, il est difficile d'identifier les erreurs, donc avoir de petits morceaux de code aide à localiser les problèmes plus rapidement. C'est en fait l'un des arguments qui soutiennent les tests unitaires. Gardez à l'esprit que je dis "fonctionnalité complexe" et non "logique complexe" car il est toujours possible d'implémenter une fonctionnalité simple de manière complexe.
Imaginez maintenant que vous deviez ajouter une fonctionnalité ou modifier la logique parce que les exigences ont changé. Cela arrive rarement, n'est-ce pas ? ;). L'implémentation actuelle ne correspond pas à la nouvelle idée ou au nouveau contexte. Comme presque toujours, il y a deux options : le piratage sale ou le refactoring. Nous choisissons bien sûr toujours le refactoring :
[Cliquez sur l'image pour la voir en grand format]
Imaginez que la scission soit propre (il suffit de déplacer certaines méthodes vers la nouvelle classe) et que l'ancienne classe conserve une référence à la nouvelle classe. Est-il judicieux de diviser la classe de test afin de conserver le mappage 1-1 ? Qu'est-ce que nous gagnons? Nous pourrions simplement garder le test tel quel (seulement un léger changement est nécessaire).
Dans le cas où le refactor était plus complexe, imaginez que la logique (détails d'implémentation) a été adaptée en 20 minutes. Comme nous l'avons déjà mentionné, les tests ne sont pas si rapides à changer.
Concernant les tests on voit deux choses :
Nous voyons que chaque type a certains avantages. Alors peut-être pouvons-nous combiner le meilleur de l'intégration et des tests unitaires conventionnels. Traditionnellement, une unité est une classe ou une méthode. C'est du moins ainsi que je l'ai appris il y a longtemps. Il peut sembler que l'idée de ne pas tester une classe de manière isolée est fausse. Mais peut-être que le concept d'"unité" pourrait bénéficier de sa propre "refactorisation".
Pendant longtemps, je me suis demandé pourquoi je ne voyais pas les gens en parler. Après un certain temps, j'ai trouvé des articles et des vidéos sur le sujet et j'ai eu une image plus claire de cela et d'autres concepts tels que les différents types de doubles de test lorsque j'ai lu le livre Unit Testing Principles, Practices, and Patterns de Vladimir Khorikov.
Donc si ce n'est pas une classe, qu'est-ce qu'une unité ? Qu'en est-il d'une fonctionnalité, répartie sur plusieurs méthodes ou classes ? Vous pourriez dire "Attendez, cela ressemble à un test d'intégration". Eh bien, pas exactement. Je vais emprunter quelques définitions du livre :
Un test unitaire :
Un test d'intégration ne répond pas à au moins un des critères mentionnés.
Un bon test unitaire :
Ainsi, la notion d'« unité » semble désormais plus abstraite et plus souple. De plus, sous les tests d'intégration, nous pouvons considérer beaucoup de choses telles que les tests système, les tests e2e, etc.
Passons donc à un niveau de granularité supérieur. Regroupons la logique initiale dans un module et apportons quelques modifications supplémentaires :
[Cliquez sur l'image pour la voir en grand format]
La première chose que nous avons faite est de regrouper la logique du domaine dans un ordre relativementpetit module. Je ne sais pas si cela aidera, mais considérez les modules comme un microservice à l'intérieur d'un microservice. Comment petit? Comme pour presque toutes les décisions, il n'y a pas de règle unique à suivre. Gardez à l'esprit que l'exemple est une simplification : il peut y avoir plusieurs entités impliquées ou aucune, et il peut y avoir plus de classes autour.
Il est important de garder à l'esprit les compromis :
Avantages :
Désavantages:
Gardez à l'esprit qu'il peut être judicieux d'avoir un test spécifique pour des fonctionnalités vraiment complexes.
La deuxième chose que nous avons faite est de séparer le domaine des composants du framework.
Une des fonctions des frameworks comme Spring est de coller différents éléments d'une application. Ce que nous voulons faire ici est similaire à l'architecture hexagonale, c'est-à-dire les ports et les adaptateurs : les contrôleurs, les écouteurs, les filtres, les DAO ou d'autres constructions de framework sont des ports qui connectent la logique du domaine (cœur de l'application) au monde extérieur. Idéalement, ces composants ne contiennent pas de connaissances du domaine. Par exemple, les contrôleurs, les écouteurs et les filtres contiennent exclusivement un appel à la logique de domaine (et, si nécessaire, un autre appel à la logique qui mappe les données dans un format plus convivial pour le modèle de domaine).
Avantages :
Une extension de la séparation du domaine et de la logique du cadre consiste à garder la logique du domaine pour chaque fonctionnalité rapprochée, afin d'assurer la cohésion. Toute la logique liée à cette fonctionnalité est implémentée dans ce module, et non répartie autour de plusieurs modules.
J'ai déjà vécu un cauchemar, ayant besoin de fouiller dans la base de code d'un monolithe pour trouver tous les endroits qui doivent changer. Nous avons débogué intensivement pendant des mois, et le changement principal a été effectué en deux jours.
Nous avons juste besoin de tests d'intégration pour tout ce qui n'est pas testé dans les tests unitaires, comme les autres fonctionnalités du framework : configuration des points de terminaison, sérialisation, désérialisation des données et des erreurs, accès aux données, appels à distance, authentification. Un test de fumée pour le cas heureux pourrait également être intéressant.
Le dernier point que je veux mentionner concerne les tests e2e. e2e sont BEAUCOUP PLUS chers que les tests d'intégration, alors utilisez-les avec précaution :
Une alternative aux tests e2e pour ces scénarios non critiques pourrait être d'utiliser des tests pilotés par contrat.
Je me souviens de plusieurs cas où cette approche m'aurait aidé. La plus importante a été une période où nous avons dû développer un algorithme pour un système d'enchères.
La première implémentation de l'algorithme semblait initialement bonne, mais nous avons commencé à découvrir des scénarios délicats chaque semaine après la publication. Nous avons commencé à les corriger individuellement et la mise en œuvre est rapidement devenue trop complexe et nous avons fini par avoir un incident.
Après cela, nous l'avons revu et avons trouvé une approche différente. Nous nous sommes retrouvés avec 75 % de code en moins et la mise en œuvre était beaucoup plus simple. C'était la bonne partie.
Le plus triste est que les tests unitaires ont vérifié de nombreuses méthodes individuellement et nous en avions un tas. Si nous avions testé la logique en tant qu'unité de fonctionnalité, nous aurions économisé 12 jours de travail (sur 15) et beaucoup de frustration causée en refaisant tous les tests.
Ainsi, en plus de tous les avantages mentionnés, cette approche des tests peut augmenter votre bonheur en tant que développeur/équipe. D'autres stratégies visant à livrer plus rapidement nécessitent de convaincre des personnes extérieures à votre environnement le plus proche, ce qui peut être très difficile. Celui-ci est entre vos mains.
En résumé:
Et gardez à l'esprit que :
Je ne dis pas que tester de cette manière est bon pour tout le monde et tout le temps. Vous devez évaluer si cela peut vous aider et dans quels cas. Comme je l'ai mentionné, cela peut être particulièrement utile dans les environnements agiles, où il y a beaucoup d'expérimentation, le domaine est créé et évolué par itérations, et de nouvelles fonctionnalités sont régulièrement intégrées. Beaucoup de ces actions bénéficieraient de refactorisations.
Certains de ces avantages peuvent également être obtenus avec le TDD (développement piloté par les tests) si nous le faisons consciemment. Malheureusement, encore une fois, nous avons tendance à trop nous concentrer sur l'outil ou la technique sans en comprendre l'essence, et ce qu'il était censé accomplir à l'origine, donc nous n'en tirons rien et nous finissons par l'abandonner.
Adopter des pratiques comme celle-ci nécessite de changer les habitudes et nous savons à quel point cela peut être difficile. Nous pensons que la volonté est ce dont nous avons besoin, mais ce n'est pas suffisant. Je veux partager une approche que j'ai récemment découverte. Il est décrit dans le livre Immunity to Change: How to Overcome It and Unlock the Potential in Yourself and Your Organization, par Lisa Lahey, Ed.D. et Robert Kegan, Ph.D., membres de la Harvard Graduate School of Education.
Nous essayons souvent de mettre en œuvre des changements par la seule volonté. Leur théorie est que cela peut ne pas fonctionner parce que nous avons quelque chose de similaire à un "système immunitaire" qui agit contre les changements, sabotant toutes nos tentatives. Donc, pour adopter un changement, nous devons d'abord découvrir ce "système immunitaire" et travailler sur ses racines.
Ce "système immunitaire" a été développé dans le passé. Au fil du temps, nous essayons d'atteindre nos objectifs. Pour les atteindre, nous suivons une série d'étapes :
Ces concepts forment la base du processus qu'ils ont mis en œuvre. Je vais décrire les étapes très brièvement:
Si nous constatons que les hypothèses ne sont plus valables, nous y travaillons. Cela facilite l'adoption du changement.
Dans le podcast "Dare to Lead", Lisa Lahey et Brené Brown mettent l'immunité au changement en pratique à travers un exemple tiré de la propre vie de Brené. Il comporte deux parties (première partie et deuxième partie). J'écoute souvent des podcasts tout en faisant d'autres tâches, mais cela valait la peine d'être écouté très attentivement.
Le podcast commence par une question puissante de Brené : "Pourquoi voulons-nous tous nous transformer et personne ne veut changer ?". Ils continuent de parler de la façon dont nous avons tendance à associer l'échec au changement avec le fait de ne pas le vouloir suffisamment ou de fausses intentions. Ils mentionnent que les intentions ne sont pas tout, car les personnes dont la vie est en danger et qui veulent vivre, échouent encore parfois à changer.
Plus tard, ils travaillent sur un exemple, qui nous est probablement familier : Brené dit qu'elle veut être plus disciplinée avec l'équipe pour avoir des réunions régulières.
Lisa guide Brené avec quelques questions pour l'aider à remplir les colonnes. Pour Brené, c'est une clé pour se faciliter la vie et réussir. Malgré cela, et que c'est quelque chose qu'elle-même peut changer par elle-même, elle n'a pas été en mesure de mettre en œuvre le changement.
Brené est alors surprise lorsqu'elle découvre les engagements non exprimés, les hypothèses et les inquiétudes qui la sabotent et ont conduit à la situation actuelle. Elle dit qu'elle a appris dans le passé que la discipline et la créativité s'excluent mutuellement et qu'elle pense donc qu'avec des réunions régulières, elle perdra du temps pour ce qu'elle aime le plus : du temps pour être créative. Elle saute donc ces réunions, mais elle finit par avoir de nombreuses réunions ponctuelles en conséquence. Parce qu'elle veut montrer qu'elle est une leader accessible, dit-elle. Cela l'a aidée à atteindre de nombreux objectifs, mais maintenant elle y consacre trop de temps et se rend compte que le fait d'avoir des réunions régulières n'aggravera pas la situation, mais pourrait lui faire gagner beaucoup de temps.
En fin de compte, Lisa suggère qu'elle doit trouver des moyens de valider cette nouvelle conviction que la discipline et la créativité sont en effet compatibles. L'objectif est de créer de nouvelles voies neuronales et de remplacer les anciennes qui ont été creusées pendant des années.
Je pense que nous pouvons bénéficier de cette stratégie de deux manières : ce sabotage de notre "système immunitaire" illustre ce que nous faisons lorsque nous essayons d'être agiles tout en ignorant l'apparence de notre code. Je crois que cela peut être appliqué dans de nombreux aspects de nos vies :
Si, par exemple, nous prenons le cas du passage à cette nouvelle stratégie de test comme exemple, nous aurions besoin de savoir ce que nous voulons réaliser avec le changement, et pourquoi c'est plus important que d'autres choses. Pour moi, dans mon contexte actuel, la flexibilité est essentielle.
En ce qui concerne ce que nous pourrions faire qui va à l'encontre de l'objectif, pourquoi nous le faisons et les hypothèses que nous avons faites qui déclenchent ces activités, nous pourrions penser que notre vie pourrait être plus facile si nous le faisions de la manière habituelle parce que nous avons juste besoin de continuer par inertie. On trouve aussi des raisons de ne pas le faire : "C'est comme ça qu'on a toujours fait les tests, et comme on nous a appris à le faire. Tout le monde le fait comme ça, donc ça doit être correct".
Donc, pour lutter contre cela, nous devons exprimer les effets secondaires négatifs et réécrire ces croyances, puis trouver un moyen de prouver que les hypothèses sont fausses, et enfin mettre en œuvre le changement.
Si vous voulez plus de détails, vous pouvez consulter les ressources liées dans le podcast Dare to lead mentionné ci-dessus (première et deuxième partie), leur site Web ou leur livre.
Écrire pour InfoQ a ouvert de nombreuses portes et augmenté les opportunités de carrière pour moi. J'ai pu m'engager profondément avec des experts et des leaders d'opinion pour en savoir plus sur les sujets que j'ai abordés. Et je peux également diffuser mes apprentissages à la communauté technologique au sens large et comprendre comment les technologies sont utilisées dans le monde réel.
J'ai découvert le programme de contributeur d'InfoQ plus tôt cette année et je l'apprécie depuis ! En plus de me fournir une plate-forme pour partager l'apprentissage avec une communauté mondiale de développeurs de logiciels, le système d'évaluation par les pairs d'InfoQ a considérablement amélioré mon écriture . Si vous cherchez un endroit pour partager votre expertise logicielle, commencez à contribuer à InfoQ.
J'ai commencé à écrire des nouvelles pour la file d'attente InfoQ .NET afin de me tenir au courant de la technologie, mais j'en ai retiré tellement plus. J'ai rencontré des gens compétents, obtenu une visibilité mondiale et amélioré mes compétences en écriture.
Devenir éditeur pour InfoQ a été l'une des meilleures décisions de ma carrière . Cela m'a mis au défi et m'a aidé à grandir de tant de façons . Nous aimerions avoir plus de monderejoins notre équipe.
InfoQ recherche un rédacteur en chef à temps plein pour rejoindre l'équipe internationale et toujours distante de C4Media. Rejoignez-nous pour couvrir les technologies les plus innovantes de notre époque, collaborer avec les praticiens du logiciel les plus brillants au monde et aider plus de 1,6 million d'équipes de développement à adopter de nouvelles technologies et pratiques qui repoussent les limites de ce que les logiciels et les équipes peuvent offrir !
Un résumé du contenu de la semaine dernière sur InfoQ envoyé tous les mardis. Rejoignez une communauté de plus de 250 000 développeurs seniors. Voir un exemple
Nous protégeons votre vie privée.
Vous devez enregistrer un compte InfoQ ou vous connecter ou vous connecter pour publier des commentaires. Mais il y a tellement plus derrière l'inscription.
Tirez le meilleur parti de l'expérience InfoQ.
HTML autorisé : a,b,br,blockquote,i,li,pre,u,ul,p
HTML autorisé : a,b,br,blockquote,i,li,pre,u,ul,p
HTML autorisé : a,b,br,blockquote,i,li,pre,u,ul,p
Rejoignez une communauté d'experts. Tous vos tests unitaires vérifient-ils les classes ou les méthodes de manière isolée ? Avez-vous parfois l'impression que les tests restreignent la façon dont vous pouvez modifier le code ? Votre suite de tests comporte-t-elle de nombreux tests d'intégration et e2e (de bout en bout) ? small Pourquoi voulons-nous tous nous transformer et personne ne veut changer ? Jorge Fernández Rodriguez a ouvert de nombreuses portes et augmenté les opportunités de carrière Le système d'évaluation par les pairs de Vivian Hu InfoQ a considérablement amélioré mon écriture Oghenevwede Emeni a obtenu une visibilité mondiale et amélioré mes compétences en écriture Edin Kapić les meilleures décisions de ma carrière m'ont aidé à grandir façons rejoindre notre équipe Thomas Betts Rédacteur en chef à temps plein L'InfoQ Tirez le meilleur parti de l'expérience InfoQ.