Question

J'ai hérité d'un programme 10K en ligne écrit en langage assembleur 8051 qui nécessite quelques changements. Malheureusement, il est écrit dans les meilleures traditions de code spaghetti. Le programme - écrit en un seul fichier - est un labyrinthe de CALL et déclarations LJMP (environ 1200 au total), avec des sous-routines ayant plusieurs entrées et / ou des points de sortie, si elles peuvent être identifiés comme des sous-routines du tout. Toutes les variables sont globales. Il y a des commentaires; certains sont corrects. Il n'y a pas de tests existants, et pas de budget pour refactoring.

Un peu d'histoire sur l'application: Le code contrôle un centre de communication dans une application automatique qui est actuellement déployé au niveau international. Il gère simultanément deux flux en série (à l'aide d'un processeur de communication séparé) et peut être de parler à un maximum de quatre différents dispositifs physiques, chacun à partir d'un autre fournisseur. Le fabricant de l'un des appareils a récemment fait un changement ( « Oui, nous avons fait un changement, mais absolument est le logiciel même! ») Qui provoque certaines configurations du système à ne fonctionnent plus, et ne l'intéresse pas immuable, il (quelle qu'elle soit ils ne changent pas).

Le programme a été écrit par une autre société, transféré à mon client, puis modifié il y a neuf ans par un autre consultant. Ni la société d'origine, ni le consultant, sont disponibles en ressources.

D'après l'analyse du trafic sur l'un des bus série, je suis venu avec un hack, qui semble fonctionner, mais il est laid et ne traite pas la cause racine. Si j'avais une meilleure compréhension du programme, je crois que je pourrais aborder le problème réel. J'ai environ une semaine avant congelés pour soutenir une fin de la date du mois de navire le code.

Question originale: Je dois comprendre assez bien le programme pour faire les changements sans rupture. Quelqu'un at-il développé des techniques pour travailler avec ce genre de désordre?

Je vois quelques grandes suggestions ici, mais je suis limité par le temps. Cependant, je peux avoir une autre occasion à l'avenir de poursuivre certains des cours d'action plus impliqués.

Était-ce utile?

La solution

D'abord, je voudrais essayer d'entrer en contact avec les personnes qui ont développé à l'origine du code ou qui, au moins maintenu avant moi, obtenir, espérons assez d'informations pour obtenir une compréhension de base du code en général, de sorte que vous pouvez commencer à ajouter commentaires utiles à ce.

Peut-être que vous pouvez même trouver quelqu'un pour décrire les plus importantes API (y compris leur signature, les valeurs de retour et fin) pour le code. Si l'état global est modifié par une fonction, cela devrait également être explicité. De même, commencer à faire la distinction entre les fonctions et les procédures, ainsi que des registres d'entrée / sortie.

Vous devez faire très clairement à votre employeur que cette information est nécessaire, si elles ne siègent pas que vous croyez, demandez-leur en fait avec vous en face de ce code pendant que vous décrivez ce que vous êtes censé faire et comment vous doivent le faire (reverse engineering). Avoir un employeur avec une formation en informatique et la programmation sera effectivement être utile dans ce cas!

Si votre employeur ne dispose pas d'un tel contexte technique, demandez-lui d'apporter un autre programmeur / collègue d'expliquer vos pas pour lui, cela lui permet en fait de lui montrer que vous êtes sérieux et honnête à ce sujet, parce qu'il est un vrai problème -. non seulement de votre point de vue (assurez-vous d'avoir des collègues qui connaissent ce « projet »)

Si elle est disponible et réalisable, je voudrais aussi dire très clairement, que la sous- traitance (ou à tout le moins en contact avec) les anciens développeurs / mainteneurs (si elles ne travaillent plus pour votre entreprise, qui est) pour aider à documenter ce code serait être une condition préalable pour améliorer de façon réaliste le code dans un court laps de temps et de veiller à ce qu'il peut être plus facilement maintenu à l'avenir.

Soulignez que toute cette situation est due à des lacunes dans le processus précédent de développement de logiciels et que ces mesures contribueront à améliorer la base de code. Ainsi, la base de code sous sa forme actuelle est un problème croissant et tout ce qui est fait maintenant pour gérer ce problème est un investissement pour l'avenir.

Cela en soi est aussi important de les aider à évaluer et à comprendre votre situation: Pour faire ce que vous êtes censé faire maintenant est loin d'être trivial, et ils devraient le savoir - si seulement pour définir leurs attentes droite (par exemple en ce qui concerne les délais et de la complexité de la tâche).

En outre, je personnellement commencer à ajouter des tests unitaires pour les parties que je comprends assez bien, pour que je puisse commencer lentement refactoring / réécriture du code.

En d'autres termes, une bonne documentation et des commentaires de code source sont une chose, mais avoir une suite de tests complète est une autre chose importante, personne ne peut attendre de manière réaliste de modifier une base de code inconnu sans aucun moyen mis en place pour tester des fonctionnalités clés.

Étant donné que le code est 10K, je chercherais aussi dans l'affacturage des sous-routines dans des fichiers séparés pour fabriquer des composants plus identifiables, de préférence en utilisant des enveloppes d'accès au lieu des variables globales et les noms de fichiers intuitifs.

D'ailleurs, je voudrais examiner des mesures pour améliorer encore la lisibilité du code source en diminuant la complexité, ayant des sous routines avec de multiples points d'entrée (et peut-être même différentes signatures de paramètres?) Ressemble à un moyen sûr d'obscurcir le code inutilement .

De même, d'énormes routines sous pourraient également être refactorisés en plus petits pour aider à améliorer la lisibilité.

Ainsi, l'une des premières choses, je regarderais en faire serait de déterminer les choses qui le rendent vraiment compliqué à assimilez la base de code, puis retravailler les parties, par exemple en scindant sous routines énormes avec entrées multiples les points en sous routines distinctes qui appellent les uns les autres au lieu. Si cela ne peut se faire pour des raisons de performance ou les frais généraux appel, utilisez des macros à la place.

En outre, si elle est une option viable, je considère que des portions du code progressivement ré-écriture en utilisant un langage de plus haut niveau,soit en utilisant un sous-ensemble de C, ou au moins en utilisant assez excessive des macros d'assemblage pour aider à normaliser la base de code, mais aussi pour aider à localiser les bugs potentiels.

Si une réécriture progressive dans C est une option réalisable, d'une façon possible de commencer serait de transformer toutes les fonctions évidentes en fonctions C dont les corps sont -dans le début- copié / collé à partir du fichier de montage, de sorte que vous vous avec des fonctions C avec beaucoup de montage en ligne.

Personnellement, je voudrais aussi essayer l'exécution du code dans un simulateur rel="noreferrer"> à l'étape facilement à travers le code et nous espérons commencer à comprendre les plus importants blocs de construction (tout en examinant le registre et l'utilisation de la pile), un bon simulateur 8051 avec un débogueur intégré devrait être mis à la disposition pour vous si vous avez vraiment de le faire en grande partie sur votre propre.

Cela aussi vous aider à trouver la séquence d'initialisation et la structure principale de la boucle ainsi qu'un graphe d'appels.

Peut-être, vous pouvez même trouver un bon simulateur source 80851 ouvert qui peut être facilement modifié pour fournir également un plein automatiquement graphe d'appels, en faisant simplement une recherche rapide, j'ai trouvé gsim51 , mais il y a évidemment plusieurs autres options, différentes des systèmes propriétaires ainsi.

Si je dans votre situation, je dirais même envisager l'externalisation de l'effort de modifier mes outils pour simplifier le travail avec ce code source, à savoir de nombreux projets de SourceForge acceptent les dons et vous pouvez peut-être parler de votre employeur dans le parrainage d'une telle modification.

Si pas financièrement, peut-être en vous fournissant des correctifs correspondant à elle?

Si vous utilisez déjà un produit propriétaire, vous pourriez même être en mesure de parler avec le fabricant de ce logiciel et en détail vos besoins et demandez-leur s'ils sont prêts à améliorer ce produit de cette façon ou si elles peuvent au moins exposer une interface pour permettre aux clients de faire ces personnalisations (une forme d'API interne ou peut-être même des scripts de colle simples).

Si elles ne répondent pas, indiquer que votre employeur a pensé à utiliser un produit différent pour un certain temps et que vous étiez le seul en insistant sur ce produit particulier à utiliser ...; -)

Si le logiciel attend certains d'E / S du matériel et des périphériques, vous voudrez peut-être envisager d'écrire une boucle de simulation de matériel correspondant à exécuter le logiciel dans un émulateur.

En fin de compte, je sais pertinemment que je serais personnellement beaucoup plus profiter du processus de personnalisation d'autres logiciels pour me aider à comprendre un tel monstre de code spaghetti, que pas à pas manuellement le code et émulateur jouer moi-même, peu importe combien de gallons de le café que je peux obtenir.

Obtenir un graphe d'appels utilisable à partir d'un open source émulateur 8051 ne devrait pas prendre beaucoup plus longtemps que dire un week-end (au plus), car cela signifie que la plupart du temps à chercher CALL opcodes et enregistrer leurs adresses (position et cible), de sorte que tout est déversés dans un fichier pour une consultation ultérieure.

Avoir accès à un moyen serait en fait aussi grande aux internes d'un émulateur inspecter davantage le code, par exemple pour trouver des motifs récurrents de opcodes (disons 20-50 +), qui peuvent être prises en compte dans les fonctions autonomes / procédures, cela pourrait effectivement contribuer à réduire la taille et de la complexité de la base de code encore plus loin.

L'étape suivante serait probablement d'examiner la pile et enregistrer l'utilisation. Et pour déterminer le type / taille des paramètres de fonction utilisés, ainsi que leur gamme de valeur -. Afin que vous puissiez concevoir des tests unitaires correspondants

En utilisant des outils comme point / graphviz pour visualiser la structure de la séquence d'initialisation et la boucle principale elle-même, sera une joie pure par rapport à faire tout ce genre de choses manuellement.

En outre, vous finirez réellement des données utiles et les documents qui peuvent servir de base pour une meilleure documentation dans le long terme.

Autres conseils

Je crains qu'il n'y ait pas de solution miracle à ce genre de problème. Je trouve la seule solution est d'imprimer le fichier ASM puis d'aller dans un endroit tranquille et pour simuler l'exécution de la ligne de programme en ligne dans votre esprit (en écrivant le contenu des registres et des emplacements de mémoire sur un bloc-notes). Après un certain temps, vous trouvez cela ne prend pas aussi longtemps que vous attendez. Préparez-vous à passer de nombreuses heures à faire cela et boire des litres de café. Après un certain temps, vous aurez une compréhension de ce qu'il fait et vous pouvez envisager des changements.

Est-ce que 8051 ont tous les ports inutilisés IO? Si elle ne et vous ne pouvez pas savoir quand certaines routines sont appelées alors ajouter du code à envoyer ces ports de rechange haut ou bas. ensuite lorsque le programme est en cours d'exécution montre ces ports avec un oscilloscope.

Bonne chance

Je sais que cela semble fou .... mais je suis au chômage (j'ai pris mauvais moment pour dire au partenaire marjority aller en enfer) et ont un peu de temps libre. Je serais prêt à jeter un coup d'oeil. Je l'habitude d'écrire assemblage pour la pomme] [et le PC d'origine. Si je pouvais jouer avec votre code sur le simulateur pendant deux heures, je pourrais vous donner une idée si j'ai une chance de documenter pour vous (sans runing mes vacances imprévues). Depuis que je ne sais rien de 8051 cela pourrait ne pas être possible pour quelqu'un comme moi, mais le simulateur semblait prometteur. Je ne veux pas d'argent pour le faire. Sa juste assez pour obtenir une exposition à 8051 le développement intégré. Je vous ai dit cela sonnerait fou.

Trouver un autre JOB- sérieux! A défaut du livre « travailler efficacement avec le code existant » pourrait Aide- si je pense qu'il fait référence au code existant code sans tests unitaires.

Je l'ai fait ce genre de chose deux ou trois fois. Quelques recommandations:

  • Commencez par examiner le schéma, cela devrait vous aider à comprendre ce que ports et broches de vos modifications souhaitées impact.
  • Utilisez grep pour trouver tous les appels, branches, des sauts et des retours. Ceci peut aider à comprendre le flux et identifier les morceaux de code.
  • Regardez le vecteur de réinitialisation et tableau interrompre pour identifier la lignes principales.
  • Utilisez grep pour créer une référence croisée pour toutes les étiquettes de code et les données références (si votre assembleur outils ne peuvent pas le faire pour vous).

Gardez à l'esprit la loi de Hofstadter: Il faut toujours plus longtemps que prévu, même si vous prenez en compte la loi de Hofstadter .

Bonne chance.

Comment comprenez-vous la plate-forme matérielle de ce code est en cours d'exécution sur?

  • Est-il été mis en mode hors tension (Pcon = 2) pour économiser l'énergie Si oui, comment est-il été réveillé. (Une remise à zéro ou interruption matérielle)

  • Avez-vous d'attendre pour l'oscillateur écuries après une mise sous tension avant de faire des communications série

  • Est-il été mis en mode veille (Pcon = 1)

Y at-il différentes versions du matériel dans le domaine?

Assurez-vous que vous avez toutes les différentes variations de matériel de test.

Ne perdez pas votre temps avec un simulateur - il est très difficile de travailler avec et vous devez faire beaucoup d'hypothèses sur le matériel. Procurez-vous un Dans Emulator Circuit (ICE) et exécuter sur le matériel.

Le logiciel a été écrit en assembleur pour une raison que vous devez savoir pourquoi. c'est à dire. - les contraintes de mémoire - contraintes de vitesse

Il peut y avoir une raison que ce code est un gâchis

Regardez le fichier de lien pour:

ESPACE XDATA, IDATA et de l'espace CODE:

S'il n'y a pas d'espace de code libre ou Xdata ou Idata?

L'auteur d'origine peut avoir Optimizationed à entrer dans l'espace mémoire disponible.

Si tel est le cas vous avez besoin de parler au développeur d'origine pour savoir ce qu'il a fait .

Vous n'avez pas besoin d'un budget spécial pour refactoring et essais - ils vous économiser de l'argent et vous permettent de travailler plus vite - accéder. Il est la technique que vous devez utiliser pour ajouter des modifications à l'héritage, le code hérité parce qu'il est le meilleur moyen de le faire sans « sans rupture ».

La plupart du temps, je pense qu'il ya un compromis où vous obtenez plus de qualité en échange pour passer plus de temps, mais avec le code existant que vous n'êtes pas familier avec, je pense qu'il est plus rapide de faire des tests - vous devez exécuter le code avant de l'expédier, non?

Ceci est l'une des rares fois où je vais vous recommander de mettre vos compétences générales pour travailler et présenter votre PM / directeur / CXO avec votre raisonnement derrière une nouvelle écriture et les économies de temps / coût impliqué dans cette une entreprise

Couper en morceaux.

J'ai eu un problème similaire avec un logiciel 8052. Ainsi, la société a hérité d'un tel animal, le code ROM intégral (64 Ko), environ 1,5 Mo de modules de spaghetti de montage ainsi que deux modules PL 3000 lignes / M composées cette monstruosité de codage. Les développeurs originaux du logiciel ont été mort depuis longtemps (cela ne signifie pas qu'il y avait personne, mais bien personne qui comprendrait dans son ensemble), les compilateurs compilent ce sont des milieu des années 80 en cours d'exécution sur un émulateur MDS-70, et plusieurs critiques les modules sont à la limite de ces compilateurs. Comme ajouter un symbole global, et l'éditeur de liens se briserait. Ajouter un autre symbole dans un fichier ASM, et le compilateur se briserait.

Alors, comment on pourrait commencer à couper ça?

D'abord, vous aurez besoin d'outils. Notepad ++ par exemple, est une chose très agréable car il peut être utilisé pour traverser la recherche sur plusieurs fichiers à la fois, idéal pour trouver des modules renvoient un symbole global. Ceci est probablement l'élément le plus crucial.

Si possible, obtenir des documents que vous pouvez trouver sur le logiciel. Le problème le plus immédiat pour résoudre ces bêtes est de comprendre comment ils sont à peu près composés, ce qui est leur architecture. Cela est généralement pas inclus dans le logiciel lui-même, pas même si elle est par ailleurs bien commenté.

Pour l'architecture vous-même, d'abord, vous pouvez essayer de construire un graphe d'appel . Il est plus simple à faire que d'un graphe de flux de données car, généralement, il y a moins d'appels et des sauts inter-fichiers que les variables globales. Pour ce graphique d'appel considèrent que les symboles globaux en supposant que les fichiers source sont supposés être des modules (ce qui est pas nécessairement vrai, mais le plus souvent ils devraient être).

Pour ce faire, utilisez votre outil de recherche de fichiers croix, créer une grande liste (par exemple dans OpenOffice Calc) où vous collectez que le symbole est défini dans quel fichier et quels fichiers vous référer à ce symbole appelant.

Alors voler quelques grandes (!) Feuilles du traceur, et commencer à dessiner. Si vous êtes très compétent dans certains logiciels de graphique, vous pouvez l'utiliser, mais à moins que c'est ainsi, il est plus susceptible de vous retenir. croquis Donc, un graphique montrant d'appel qui fichier a des appels auxquels d'autres fichiers (ne présentant pas les symboles eux-mêmes, avec quelque 50 fichiers, vous ne seriez pas en mesure de le gérer).

Très probablement le résultat de ce sera un spaghetti. L'objectif est de redresser ceci pour obtenir un arbre hiérarchique avec une racine (qui sera le fichier contenant le point d'entrée du programme) sans boucles. Vous pouvez dévorer plusieurs feuilles au cours de ce processus de redressement itérativement la Bête. Vous pouvez également trouver certains fichiers sont tellement emmêlés entre qu'ils ne peuvent pas être représentés sans boucles. Ce cas, il est plus probable qu'un seul « module » obtenu en quelque sorte séparé en deux fichiers, ou plusieurs modules conceptuels ont été empêtré. Retour à la liste des appels, et regrouper les symboles pour ainsi couper les fichiers problématiques en unités indépendantes plus petites (vous devrez vérifier le fichier lui-même trop pour les sauts locaux ici pour voir votre coupe supposée est possible).

A la fin, sauf si vous travaillez déjà ailleurs pour votre propre bien, vous obtiendrez un graphique d'appel hiérarchique avec des modules conceptuels. De cela, il est possible de déduire l'architecture intentionnelle du logiciel et des travaux supplémentaires.

Le prochain objectif est l'architecture . Votre carte déjà fait, vous devrez naviguer le long du logiciel, comprendre ce Threads (interrompre et tâches principales du programme), et aux fins brutes de chacun des modules / fichiers source. Comment vous pouvez le faire et ce que vous obtenez ici dépend plus du domaine d'application.

Quand ces deux sont faites, le « repos » est assez simple. Par ceux-ci, vous devez essentiellement savoir ce que chaque partie de la chose est censé faire, et si vous savez ce que vous traitez probablement avec quand vous commencez à travailler sur un fichier source. Il est cependant important que chaque fois que vous trouvez dans une source quelque chose « fishy », quele programme semble faire quelque chose hors de propos, pour revenir à votre graphique de l'architecture et de l'appel, et apporter des corrections si nécessaire.

Pour le reste les méthodes d'autres mentionnées appliquent bien. Je viens d'exposer ceux-ci pour donner un aperçu sur ce qui peut être fait dans les cas vraiment hideux. Je voudrais avoir seulement 10K lignes de code pour traiter l'époque ...

Je dirais que la réponse de IanW (juste imprimer et garder le traçage) est probablement le meilleur. Cela dit, j'ai un peu à l'idée de mur:

Essayez d'exécuter le code (probablement le binaire) à travers un dissimulateur qui peut reconstruire le code C (si vous pouvez en trouver un pour le 8051). Peut-être qu'il identifiera quelques routines vous ne pouvez pas (facilement).

Peut-être que ça va aider.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top