Travailler sur les bases de codes du patrimoine (ou la vie d'un entrepreneur) (Français (French))

Travailler sur les bases de codes du patrimoine (ou la vie d'un entrepreneur)

Comments

NOTE: Apart from English (and even then it's questionable, I'm Scottish). These are machine translated in languages I don't read. If they're terrible please contact me.
You can see how this translation was done in this article.

Wednesday, 06 November 2024

//

Less than a minute

Présentation

En tant que développeur indépendant, l'un des ensembles de compétences dont vous avez besoin pour apprendre rapidement est de travailler efficacement sur les bases de code existantes. J'ai eu de la chance d'avoir construit un tas de systèmes à partir de--scratch; c'est un JOY en tant que développeur expérimenté, mais ce n'est pas toujours le cas.

Les défis

Les systèmes hérités présentent d'importants défis, surtout lorsque les développeurs/architectes clés (si vous avez la chance de les avoir) sont passés à autre chose.

Documentation

Cela est souvent négligé surtout dans les petites entreprises. En général, vous avez besoin de 4 types de documents clés :

  1. Guides des nouveaux développeurs Alors comment exécutez-vous le projet localement (plus à ce sujet en une minute), quelles considérations y a-t-il (si par exemple vous avez besoin d'un cadre différent de celui actuel, particulièrement vrai avec Node tristement).
  2. Docs de déploiement en ces jours où l'IC/CD est considéré comme la norme d'or du déploiement, il est souvent négligé que vous devez savoir comment déployer le système manuellement. Cela est particulièrement vrai si vous travaillez sur un système qui a été autour pendant un certain temps et a beaucoup d'étapes manuelles.
  3. Procédures de résolution des problèmes; que faites-vous lorsque le système tombe en panne? Qui appelez-vous? Quelles sont les principales choses à vérifier? Cela est souvent négligé, mais c'est CRUCIAL dans un système de production.
  4. Docs architecturaux / de conception système; comment le système fonctionne-t-il? Quels sont les éléments clés? Quelles sont les principales dépendances? Pensez à cela comme votre feuille de route lors de l'apprentissage d'un nouveau système. Il donne un aperçu de haut niveau du fonctionnement du système qui peut être critique (en particulier dans les systèmes plus grands et distribués). Il faut indiquer quels dépôts de code source sont utilisés, quels systèmes CI/CD sont utilisés, quelles bases de données sont utilisées pour chaque élément de l'application. Cela peut englober n'importe quoi d'un diagramme simple à un diagramme UML complet de chaque composant du système. Par exemple, dans une application de réaction, cela comprendrait généralement un diagramme des composants et de la façon dont ils interagissent entre eux et avec tous les services de soutien. Dans une application.NET Core, cela comprendrait un diagramme des services et de la façon dont ils interagissent les uns avec les autres (et les systèmes frontal end et autres systèmes backend) et éventuellement ASP.NET Views et quels services ils peuvent utiliser.

La documentation est l'une des choses que nous, en tant que développeurs, haïssons souvent de faire (ce n'est PAS du code), mais c'est crucial. Comme vous pouvez le voir I LOVE Markdown, avec les similaires de Sirmaid et PlantUML, vous pouvez créer des diagrammes et des diagrammes de flux vraiment agréables qui peuvent être inclus dans votre documentation.

Il doit être COURANT; les développeurs parlent souvent de bit-rot; où les dépendances d'un projet deviennent obsolètes / risques de sécurité pur et simple. Cela vaut aussi pour la documentation; si elle n'est pas courante, elle n'est pas utile.

Il y a différents niveaux de documentation mais en général chaque fois que vous changez de code qui est mentionné dans un document que vous devez mettre à jour ce document.

Fonctionnement local du système

Il s'agit souvent d'un défi, surtout si le système existe depuis un certain temps. Vous devez savoir quelle version de Node /.NET etc., quelle version de la base de données, quelle version du framework etc. Cela est souvent négligé, mais c'est CRUCIAL de se lever et de fonctionner rapidement.

J'ai souvent vu des développeurs dire que ce n'est pas pertinent en ces jours de systèmes cloud et de grandes applications distribuées, mais je ne suis pas d'accord; vous devez être en mesure d'exécuter le système localement pour déboguer les problèmes rapidement et efficacement.

  1. Profilage - cela semble être devenu une compétence «développeur avancé seulement», mais il est crucial de pouvoir profiler votre code pour voir où sont les goulets d'étranglement. Cela est particulièrement vrai dans un système hérité où vous n'avez peut-être pas le luxe de pouvoir réécrire le système à partir de zéro. Des outils comme dotTrace et dotMemorysont inestimables ici. En particulier dans les applications ASP.NET; les plus grands problèmes sont généralement les « fuites » dans le système; fuites de mémoire, fuites de connexion, etc. Alors que votre application semble exécuter FINE pour un peu, vous trouvez soudain qu'il s'écrase / en utilisant toute la mémoire sur le serveur.
  2. Trouver des problèmes dans le débogueur - Aimez-le ou pas les jours de Response.Write en ASP classique sont terminés. Pour une application même modestement complexe (surtout celles que vous n'avez pas écrites), il est crucial de « passer à travers » le code. Pour suivre une demande depuis sa création jusqu'au service pour identifier ce qui se passe, quelles exceptions peuvent ne pas être prises, etc.
  3. Logging - Encore une fois souvent négligé (désolé mais pas de filtre d'exception ASP.NET Core en haut de la pile ne suffit pas). Se référant à mon poste précédent, l'enregistrement est une partie critique sur le travail dans le code LOCALLY. Rappelez-vous que vous pouvez utiliser des types de journalisation des clients (par exemple en utilisant Générateurs de sources d'exploitation forestière) dans ASP.NET Core. Vous pouvez ensuite spécifier les types d'événements qui doivent être enregistrés et ceux qui ne devraient pas l'être. Ceci est crucial dans un système hérité où vous n'avez peut-être pas le luxe de pouvoir réécrire le système à partir de zéro. Pour l'application Insights vous pouvez vouloir Voyages d'utilisateur et d'autres fonctionnalités; cependant, soyez conscient ça devient cher vite si vous utilisez LogInformation pour chaque demande. Vous pouvez utiliser un processeur de télémétrie personnalisé pour filtrer les demandes que vous ne voulez pas enregistrer.
  4. Tester - Trop souvent je vois les développeurs 'test in preprod' ou penser que le test unitaire puis vérifier est ENOUGH en termes de test. Son RARELY EST, il y a beaucoup de valeur dans les deux utilisant un outil comme Resharper / NCrunch pour exécuter automatiquement des tests unitaires; cependant rappelez-vous que les tests unitaires sont juste cela; ils testent une 'unité' de code. Vous devez conserver la visibilité dans la façon dont le système fonctionne réellement de concert avec d'autres composants. C'est là qu'interviennent les tests d'intégration; ils testent comment le système fonctionne dans son ensemble. Vous pouvez utiliser un outil comme SpecFlow d'écrire ces tests dans un format lisible par l'homme. Encore une fois, crucial dans un système hérité où vous n'avez peut-être pas le luxe de pouvoir réécrire le système à partir de zéro.

Dans EVERY projet, je travaille sur la première étape est de faire fonctionner le système (ou une grande partie de celui-ci) localement. En voyant le code, en exécutant le code, en débogant le code, vous pouvez avoir une idée du fonctionnement du système.

La base de codes

Dans chaque système, c'est votre source de vérité, peu importe ce que disent les docs, ce que les autres vous disent sur la façon dont il doit fonctionner c'est comment il FAUT fonctionner.

C'est souvent difficile, c'est comme trouver votre chemin dans une nouvelle ville sans feuille de route. Heureusement dans les applications, vous avez un point d'entrée (une page charge / un appel d'API frontal etc.) Choisissez un point et commencez par là.

Utilisez tout ce dont vous avez besoin pour interagir avec elle, que ce soit PostMan, Rider's HttpClient ou même une page web. Accrochez votre débogueur, faites l'appel et suivez-le. Rincer et répéter pour chaque partie du système.

Refactoration

D'une manière générale, laissez-le jusqu'à ce que vous compreniez le système. C'est toujours tentant de "jeter et recommencer" mais de résister à cette tentation. Surtout pour un système en cours d'exécution ŒUVRES reconstruire / même refactoriser un système est un risque HUGE. Oui, c'est FUN mais pour chaque ligne de code que vous changez, vous risquez d'introduire de nouveaux bugs passionnants.

Comme tout le reste (surtout lors de la passation de contrats), vous devez justifier le travail que vous effectuez sur un système. L'une ou l'autre de ces justifications doit être axée sur l'un des éléments suivants :

  1. Résultats - le système est lent et doit être accéléré (à nouveau attention, ce que VOUS trouvez lent peut être la façon dont le système est conçu pour fonctionner). Faire une partie de fumer rapidement peut introduire des problèmes plus loin dans le système. Allez-vous "tuer" le serveur de base de données, si vous faites trop de requêtes avez-vous un mécanisme qui ne causera pas d'exceptions en cascade?
  2. Sécurité - le système n'est pas sûr et doit être sécurisé. Il s'agit d'un système difficile, surtout dans un système hérité. Avec bit-rot vous pouvez trouver que le système utilise d'anciennes versions de bibliothèques qui ont connu des problèmes de sécurité. C'est une bonne justification pour le travail; cependant, soyez conscient que vous pourriez avoir besoin de refactorer un LOT du système pour le mettre à jour; encore une fois menant à la question des « nouveaux bogues ».
  3. Maintenabilité - le système est difficile à entretenir et doit être plus facile à entretenir. En général, cela devient beaucoup de travail; la durée de vie actuelle de la base de codes le justifie-t-elle? Si vous passez plus de temps à faire ces changements pour améliorer la maintenance que vous n'auriez jamais économisé pour le client, alors cela ne vaut pas la peine (et encore, changé de code == nouveaux bogues).
  4. Expérience utilisateur - Je donne généralement la priorité à ces questions. Pour une utilisateur peu importe si votre code est meilleur de 1%; ce sont eux qui PAYENT pour le travail que vous faites à la fin. Si vous pouvez faire leur expérience mieux que cela en vaut la peine. Cependant, soyez conscient que cela peut être une « pente glissante » de changements; vous pouvez trouver que vous changez un LOT du système pour faire un petit changement pour l'utilisateur.

Le travail sur les systèmes hérités

Cela est souvent négligé, en particulier par les développeurs. Vous devez être en mesure de justifier le travail que vous faites sur un système. C'est particulièrement vrai dans un environnement contractuel où vous êtes payé à l'heure. En fin de compte, ce n'est pas VOTRE code et pas votre argent. Le POURQUOI vous faites un changement est souvent plus important que le changement lui-même.

J'ai travaillé comme entrepreneur depuis plus d'une décennie maintenant, ce n'est pas EASY; comme un entrepreneur chaque heure de votre temps est un « coût » pour le client. Vous devez ajouter de la valeur de déplacement au système que vous coûtez. Si vous n'êtes pas alors vous serez rapidement à la recherche d'un nouveau contrat.

En tant que développeurs, nous avons tendance à être des gens d'affaires merdiques, nous nous concentrons sur la "perfection" à chaque tour. En réalité, vous n'avez pas besoin de faire un système "parfait" (je dirais qu'il n'y a pas de telle chose); vous avez juste besoin de fournir de la valeur au client.

Dans le cadre d'un engagement à plus long terme, il s'agit notamment de veiller à ce que nouveaux le code est maintenu et rentable à exécuter. Dans les systèmes hérités, c'est MUCH HARDER. Il faut souvent traverser un marécage, c'est-à-dire qu'en apprenant le système, vous ne pouvez pas offrir beaucoup de valeur. I'm not making any changes vous pensez I'm just learning the system. C'est une erreur; vous apprenez le système pour le rendre meilleur. Vous apprenez le système pour le rendre plus efficace. Vous apprenez le système pour le rendre plus durable. Si un client ne peut pas accepter cette étape, alors vous devez être très prudent sur la façon dont vous communiquez cela (ou cherchez un nouveau contrat).

Le peuple

Encore une fois souvent négligé, beaucoup de temps que vous êtes amené en tant qu'entrepreneur parce qu'une personne clé est partie (ne vous mêlez pas à la politique de cela; ce n'est pas votre préoccupation). Vous devez être en mesure de travailler avec les gens qui sont là pour atteindre les objectifs du projet. Dans un contrat, vous aurez généralement les modalités de votre engagement énoncées (dans mon contrat actuel, c'est « améliorer la fiabilité et réduire les coûts de fonctionnement ») ; concentrez-vous sur cela. Si vous n'êtes pas sûr de ce que cela signifie alors ASK.

Gardez à l'esprit qui est votre contact direct; surtout dans les premiers mois. Tenez-les informés (vous n'aurez probablement pas de nouvelles fonctionnalités pour vous vanter au fur et à mesure que vous serez épinglés sur le fonctionnement du système). J'envoie généralement un courriel sommaire chaque semaine / deux semaines à mon contact direct; c'est une bonne façon de les tenir informés de ce que vous faites et de ce que vous trouvez.

Rappelez-vous, c'est la personne qui approuvera votre facture; il ne devrait pas y avoir de surprises au moment de la facture. Une fois que vous commencez à vérifier en code régulièrement, c'est moins un problème; vous avez un enregistrement de exactement ce que vous avez fait et l'impact qu'il a eu. D'ici là, vous devez les tenir informés. Ils ont besoin de savoir ce que tu as fait et pourquoi ils devraient te payer pour ça.

Fiabilité

Encore une fois, revenez au code hérité; si vous faites un changement en général, vous devez le déployer.Même les meilleurs d'entre nous vont FUCK UP de temps en temps, en particulier dans les systèmes de code hérités, il y aura quelque chose Tu ne pouvais pas savoir. quand vous vous déployez. Cela revient à l'enregistrement - si vous avez un serveur de mise en scène l'ont enregistré un LOT (mais conservé pour une courte période) puis lorsque vous déployez à CET vous pouvez recueillir plus d'informations sur ce qui a échoué.

Peu importe à quel point vous êtes bon, combien de tests locaux vous avez fait nous sommes tous humains. Il s'agit d'un élément clé de la règle « ne pas déployer le vendredi »; attendez-vous à ce qu'un déploiement cause un nouveau problème sur un système. Soyez prêt à travailler jusqu'à ce qu'il soit résolu. Si vous ne savez pas pourquoi il a échoué, ajoutez plus de tests pour reproduire le problème et plus de journalisation pour vous assurer d'attraper des problèmes similaires à l'avenir.

En particulier pour les systèmes de production votre système de mise en scène peut ne pas être 1:1 (surtout en ce qui concerne la charge), outil comme k6 peut vous aider à simuler la charge (même mieux localement où vous pouvez faire un profilage approprié comme mentionné précédemment).

Déploiement

Encore une fois, la ferveur de l'IC/DC est souvent négligée dans la raison d'être de celles-ci. C'est simple, tu vas te défoncer. Avoir une façon très rapide et efficace de déployer un système signifie que lorsque vous faites la casse, vous pouvez également la réparer plus rapidement. Si votre système de révision de code CI signifie qu'il faut 2 jours pour obtenir un PR fusionné, alors c'est le plus rapide que vous pouvez raisonnablement fi un système. Si votre système de CD signifie que vous supprimez le système de fonctionnement; s'habituez à LONG nuits.

Un mécanisme efficace de fixation et de déploiement du code est essentiel à un pipeline de développement efficace. S'il faut plus de temps pour déployer une correction qu'il a fallu pour trouver et implémenter cette correction dans le code, alors vous êtes moins susceptible de corriger des choses.

'Fixing Legacy Apps'

J'ai mis ceci en citations car il s'agit d'un problème; pour les applications héritées (surtout lorsque le retravail à grande échelle est hors limites) il y a deux approches principales.

  • Patchs en cours d'exécution

C'est le processus de simple fixation du code existant ; assurez-vous encore une fois que vous testez soigneusement et avez des processus en place pour revenir / redéployer rapidement toutes les corrections. Je ne mentirai pas ce type de développement est rarement FUN car vous êtes encore probablement en train de passer à travers le marais de la base de code existante. Cependant, c'est un mal nécessaire dans de nombreux cas.

Comme d'habitude, vous devez vous assurer que vous avez SOME FORMULAIRE de test pour excerciser le code courant; idéalement, il devrait également tester l'échec pour le problème que vous essayez de résoudre AVANT de faire la correction . Ils IDYLL pour cela est d'avoir un test d'unité qui cible étroitement la zone de code que vous devez fixer, mais cela est souvent en dehors du champ de travail pour les grands systèmes distribués.

J'utiliserais généralement un système de tests dans cet ordre de préférence :

  1. Tests unitaires - encore une fois, ceux-ci sont préférés car vous pouvez cibler ceux-ci pour seulement exercer le code sur lequel vous travaillez. Cependant, dans un système hérité, ces systèmes ne sont souvent pas présents et extrêmement difficiles à adapter (par exemple dans un système avec de nombreux appels extérieurs / qui est désordonné dans la façon dont il construit; ne pas utiliser le DI par exemple).
  2. Tests d'intégration - Il s'agit d'un terme surchargé car il peut couvrir n'importe quoi d'un test unitaire qui passe par plusieurs couches de code (celles-ci sont mieux évitées) à l'utilisation des similaires de l'excellent Vérifier jusqu'aux tests de Sélénium. En général, vous voulez tester le système dans son ensemble; cependant, soyez conscient que ces tests peuvent être lents et cassants. L'utilisation de Verify peut souvent être une excellente approche pour les systèmes existants car vous pouvez au moins « vérifier » que vous ne brisez pas la surface API du système.
  3. Tests manuels - CHAQUE développeur devrait essayer d'exécuter des tests manuels pour tout contrôle de code. Il suffit de s'assurer que ce que vous attendez de l'utilisateur (ce peut être un utilisateur réel ou un autre composant du système interagissant avec votre code) pour voir ce qu'il voit réellement. Cela peut être aussi simple que d'exécuter le système localement et de vérifier la sortie d'une page ou aussi complexe que d'exécuter une suite complète de tests sur un serveur de mise en scène.
  • Peautage de l'oignon Pour travailler sur les systèmes anciens, vous n'aurez généralement pas le luxe d'un retravail complet. C'est là que j'utilise l'approche de la peau d'oignon.

Pour vous permettre de mettre à niveau les PARTS d'un système, vous pouvez identifier des composants qui peuvent être séparés d'un monolithe existant en un microservice (pour une certaine valeur de'micro'). Cela peut être une excellente façon de commencer à moderniser un système sans risque de retravailler complètement. Des exemples communs pourraient consister à diviser les paramètres de l'API en nouveaux projets qui utilisent des éléments plus mis à jour. La terreur de DRY peut cependant entrer en jeu ici. Une solution mal structurée comporte souvent beaucoup de composants « d'aide » ou « de service » qui devraient vraiment être dans différents projets (ou même dans des paquets nuget pour une réutilisation plus globale).

Je vais couvrir cette approche plus loin dans un futur article car c'est un élément clé de la façon dont je travaille sur les systèmes anciens et pas évident pour de nombreux développeurs.

Se faire payer

Maintenant que nous avons tout cela hors de la façon dont il arrive le problème épineux de paiement. J'ai une règle générale :

Tous les problèmes de paiement que je cherche à passer à autre chose

S'ils sont en retard de paiement; dépend de votre contrat mais au MOINS dans les 30 jours mais généralement plus près de 7; c'est un mauvais signe. S'il y a des gravats sur votre facture (pickle-and-dimeing) pensez à savoir si l'entreprise est capable de payer vos services sur une base continue.

Ne vous moquez pas de cela; si vous avez fait votre travail, vous devez être payé en temps opportun. Peu importe à quel point vous l'appréciez; si un mauvais client peut vous exploiter, ils le feront. Ça n'en vaut jamais la peine.

Soyez honnête; ne facturez que le temps que vous avez réellement travaillé; assurez-vous qu'il est clair ce que vous avez fait et pourquoi vous l'avez fait.

J'ai dirigé des équipes de développeurs et j'ai été un développeur; j'ai été un entrepreneur et j'ai été un client. J'ai vu de tous les côtés et je peux vous le dire; si vous n'êtes pas payé à temps, alors vous devez passer à autre chose. Sur le côté inverse si vous avez un entrepreneur (ou un ETP) qui ne livre pas, alors vous devez traiter cela rapidement. Tout le monde a des luttes personnelles, mais surtout dans un environnement contractuel, vous devez fournir de la valeur ou ne pas facturer pour le temps quand vous ne l'êtes pas.

Quant au tarif, vous trouverez votre niveau; personnellement je charge plus pour des projets où j'ai plus de responsabilités (ou qui ne semblent pas amusants). Je charge moins pour les projets où j'apprends une nouvelle technologie ou pour les startups. J'ai aussi travaillé moins de jours mais j'ai maintenu mon taux stable. Mais n'acceptez pas un taux bas; vous êtes un professionnel et vous devriez être payé comme tel.

En conclusion

C'est tout. Je ne travaille plus aujourd'hui et demain pour les funérailles de ma grand-mère et je panique franchement un peu que j'ai un système d'héritage HUGE à apprendre, donc j'ai pensé vomir mes pensées sur ce que le travail sur ces systèmes est comme et les défis.

logo

©2024 Scott Galloway