Folks, je viens de rejoindre cette société qui a un énorme arbre source basé sur JSP/Servlet et EJB 1.2. Aucune documentation n'existe. Le code a été écrit sur sept ans, avec un grand nombre de changements non documentés. Y at-il un outil qui peut m'aider à suivre l'exécution? Mettre un point d'arrêt ne m'aide pas beaucoup.java tracing spaghetti code
Répondre
Un grand merci pour les contributions de tous. Ce fut une expérience d'apprentissage merveilleuse. J'ai fini par écrire mon script shell, qui produit un rapport html. Je joins le fichier complet ici.
S'il vous plaît noter que je ne suis pas un programmeur shell régulier, et je travaillais sur ce après les heures .. d'où la norme du code n'est pas trop bon. Il a beaucoup de travail coupé/passé sur Internet. Cela fonctionne cependant, et présente l'approche que vous pouvez prendre pour parcourir votre code sphegatti.
Cordialement Amarsh
#!/usr/bin/bash
# check the number of command line arguments
clear
echo "### CodeCrawler starting"
# test input parameters
if [[ $# < 2 ]]; then
echo "usage: % crawl inputFile/inputDir outputDir"
exit -1
fi
# the working directory is C:\CodeCrawler
cd /cygdrive/c/CodeCrawler
# find all files tha require analysis
if [ -d $1 ]; then
find $1 | grep "\.java$" > allFiles$2
find $1 | grep "\.jsp$" >> allFiles$2
find $1 | grep "\.htm$" >> allFiles$2
find $1 | grep "\.html$" >> allFiles$2
else if [ -f $1 ]; then
find $1 > allFiles$2
fi
fi
# get total no. of files to be scanned
totalFiles=$(cat allFiles$2 | wc -l)
scannedNoOfFiles=0;
echo "### No of files to scan : $totalFiles"
# create the index.html file
rm -rf $2; mkdir $2;cd $2
echo "<html><body bgcolor=\"#ccffff\"><h3>$1</h3>" > dir.html
# crawl through the entire directory
for rootFile in $(cat ../allFiles$2); do
scannedNoOfFiles=$((scannedNoOfFiles+1));echo;echo "### Scanning $scannedNoOfFiles/$totalFiles"
# create a dir for the output
rootFileDir=$(echo $rootFile | tr '/' '\n' | tail -1).dir
echo "### Storing output in $rootFileDir"
rm -rf $rootFileDir
mkdir $rootFileDir
cd $rootFileDir
# append to the index.html file
rootFileDirName=$(echo $rootFile | tr '/' '\n' | tail -1)
echo "<a href=\"$rootFileDir/index.html\" target=\"fileFrame\">$rootFileDirName</a><br>" >> ./../dir.html
# obtain all external jsp references
touch jsp.cwl
cat $rootFile | grep "\.jsp" | tr "'\"\?<>=,()[] " '\n' | sed 's/\.\.//g' | grep "\.jsp" | grep -v "http" | sort -u > tmp
for line in $(cat tmp);do
echo /$line | sed 's/\/\//\//g' >> jsp.cwl
done
# obtain all external js references
touch js.cwl
cat $rootFile | sed 's/\.jsp//g' | grep "\.js" | tr "'\"\?<>=,()[] " '\n' | sed 's/\.\.//g' | grep "\.js" | grep -v "http" | sort -u > tmp
for line in $(cat tmp);do
echo /$line | sed 's/\/\//\//g' >> js.cwl
done
# obtain all external css references
touch css.cwl
cat $rootFile | grep "\.css" | tr "'\"\?<>=,()[] " '\n' | sed 's/\.\.//g' | grep "\.css" | grep -v "http" | sort -u > tmp
for line in $(cat tmp);do
echo /$line | sed 's/\/\//\//g' >> css.cwl
done
# obtain all external htm references
touch htm.cwl
cat $rootFile | grep "\.htm" | tr "'\"\?<>=,()[] " '\n' | sed 's/\.\.//g' | grep "\.htm" | grep -v "http" | sort -u > tmp
for line in $(cat tmp);do
echo /$line | sed 's/\/\//\//g' >> htm.cwl
done
# obtain all database references
touch db.cwl
cat $rootFile | grep -i "select.*from" | sed 's/from/\nfrom/g' | sed 's/FROM/\nFROM/g' | grep -i "from" | sed 's/from//g'| sed 's/FROM//g' | awk '{print $1}' | tr '[;"]' ' ' | uniq > db.cwl
cat $rootFile | sed "s/.prepareStatement(\"/\nX_X_X/g" | grep "X_X_X" | sed "s/X_X_X//g" | tr '[ ,\$ ]' '\n' | head -1 | uniq >> db.cwl
# obtain all references to java classes. we include everything with signature com. and exclude "www" and "flight"
cat $rootFile | tr '["=%;/<>@\t) ]' '\n' | grep "com\." | grep -v "codepassion\." | grep -v "www" | grep -v "flight" | sort -u > tmp
echo > tmpDirectReferences
cat tmp | grep "(" >> tmpDirectReferences # directReferences are like au.com.mycompany.servlet.MiscServlet.getCckey()
echo > tmpDirectReferences
cat tmp | grep -v "(" >> tmpJavaFiles # javaFiles are like Person aPerson; ... aPerson.getPolicy()
# read directReferences and produce the class.cwl file by identifying class and method
echo "#D# Looking for direct references"
while read classLine; do
methodName=$(echo $classLine | tr '\.' '\n' | tail -1 | sed 's/(//g')
className=$(echo $classLine | sed "s/\.$methodName(//g" | tr '[()]' ' ')
echo $methodName >> $className.cwl
echo "### class: $className method:$methodName"
echo $className >> tmpDirectReferencesReformed
done < tmpDirectReferences
# read javaFiles every fully qualified class name and grab the class from it. then grab the method from it
echo "#J# Looking for indirect references"
while read classLine; do
className=$(echo $classLine | tr '\.' '\n' | tail -1)
echo "#F# find: $classLine"
# indirect references are in the form className objectName ... and then objectName.methodName
cat $rootFile | grep "$className .*;" | sed -e "s/$className[ \t]\+\([a-zA-Z0-9_]\+\)[ \t]*[;=].*/\1/g" | sed 's/^[ \t]*//;s/[ \t]*$//' | sort -u > tmp$ClassName
# read tmp$className and find all properties and method references
while read methodLine; do
cat $rootFile | grep "$methodLine\." | tr '[ (]' '\n' | sed "s/$methodLine\./\n$methodLine\./g" | grep "$methodLine\." | sort -u | grep -v "[\"%]" | grep -v ".com." | tr '.' '\n' | grep -v "$methodLine" >> $classLine.cwl
done < tmp$ClassName
# direct references are className.methodName
cat $rootFile | grep "[()\"']$className\." | tr ' (' '\n' | grep "$className" | tr '.' '\n' | grep -v "$className" >> $classLine.cwl
cat $rootFile | grep "$className\." | tr ' (' '\n' | grep "$className" | tr '.' '\n' | grep -v "$className" >> $classLine.cwl
done < tmpJavaFiles
# consolidate all information to generate the html files
echo "### Generating index.html"
rootFileName=$(echo $rootFile | tr '/' '\n' | tail -1)
touch index.html
echo "<html><head><title>$rootFileName</title></head><body bgcolor=\"#ffffcc\">" >> index.html
echo "<h3>$rootFile</h3>" >> index.html
# put all java classes
echo "<br><h3>Referenced classes</h3>">> index.html
cat tmpDirectReferencesReformed | uniq >> tmpJavaFiles;cat tmpJavaFiles | uniq > tmpJavaFilesU; mv tmpJavaFilesU tmpJavaFiles
while read aLine; do
echo "- <a href=\"$aLine.html\" target=\"methodFrame\">$aLine</a><br>" >> index.html
done < tmpJavaFiles
# put all DBs
echo "<br><h3>Referenced Tables</h3>">> index.html
while read aLine; do
echo "- $aLine<br>" >> index.html
done < db.cwl
# put all JSPs
echo "<br><h3>Referenced JSPs</h3>">> index.html
while read aLine; do
echo "- $aLine<br>" >> index.html
done < jsp.cwl
# put all JSs
echo "<br><h3>Referenced JavaScript</h3>">> index.html
while read aLine; do
echo "- $aLine<br>" >> index.html
done < js.cwl
# put all htms
echo "<br><h3>Referenced htm</h3>">> index.html
while read aLine; do
echo "- $aLine<br>" >> index.html
done < htm.cwl
# put all css
echo "<br><h3>Referenced css</h3>">> index.html
while read aLine; do
echo "- $aLine<br>" >> index.html
done < css.cwl
echo "</body></html>" >> index.html
# generate a html for each class file and put all accessed methods in it
for aLine in $(ls *.cwl); do
cat $aLine | uniq > tmp; mv tmp $aLine
fileName=$(echo $aLine | sed 's/\.cwl//g')
echo "#G# generating $fileName.html"
echo "<html><body bgcolor=\"#ffddee\">" >> $fileName.html
echo "<h3>$fileName</h3>" >> $fileName.html
for bLine in $(cat $aLine | sort); do
echo "$bLine<br>" >> $fileName.html
done
echo "</body></html>" >> $fileName.html
done
# cleanup and return
#rm *.cwl *tmp*
cd ..
done
echo "</body></html>" >> ./dir.html
rm ../allFiles$2
echo "### CodeCrawler finished"
Pourquoi les points d'arrêt ne sont-ils pas utiles? Faire un pas dans le code avec le débogueur devrait fonctionner. Que le code soit spaghetti ou non ne devrait pas affecter la "débugabilité" du système.
Sur la façon de gérer ce gâchis, je suggère d'écrire des tonnes de tests unitaires pour le système existant. Cela vous permettra de mieux comprendre le programme et d'être dans une meilleure situation pour les refactorisations dès qu'elles seront nécessaires (évidemment très bientôt). Jetez un oeil à http://amzn.com/0131177052
Il pourrait être difficile de trouver des unités testables s'il s'agit d'un gros moloch. – tangens
Certainement! C'est là que ce livre aide. En traitant avec des bases de code anciennes et grandes. – cherouvim
les points d'arrêt n'aident pas puisque la plupart des piles d'appels de méthode sont très profondes. logique métier en jsps et javascript ajouter à la difficulté. Je me demandais s'il pouvait y avoir une pile trace de quelle méthode appelée quoi (un peu comme regarder les instructions log.trace si le code était bien écrit), je peux simplement parcourir la séquence pour comprendre quelle est l'histoire. Le profileur produit une liste de toutes les méthodes appelées, mais pas dans une séquence particulière. – Amarsh
Le bon vieux truc peut aider ici si vous êtes autorisé à modifier le code: mettre beaucoup System.err.println()
à des points stratégiques. Il montre le flux du programme, qui est probablement la première étape pour découvrir le code inconnu.
La trace peut également afficher certaines valeurs de variables ou même une trace de pile (utilisez new Exception().printStackTrace(System.err)
). Pour éviter un flot de messages, la trace peut être protégée par une condition préalable qui exécute le println
seulement si cela en vaut la peine.
Assurez-vous de mettre dans chaque message la classe actuelle et la méthode à référencer. Le message montre clairement l'emplacement du code println
, et cela aidera beaucoup à enlever toutes les traces quand vous avez terminé!
Si vous voulez tracer l'exécution de votre code Java, vous pouvez utiliser un outil appelé InTrace.
- 1. Tracing ordre d'exécution en Java
- 2. Nettoyage de Legacy Code "en-tête spaghetti"
- 3. Comment traiter le code spaghetti asynchrone?
- 4. Postgresql Tracing
- 5. Recursion Tracing
- 6. Tracing Fonctions Erlang - formes courtes
- 7. CrossHair Tracing Problème Dans JFreeChart
- 8. Git fusionner Spaghetti - Comment y remédier?
- 9. Comment faire ray tracing dans OpenGL moderne?
- 10. Erreur lors de l'utilisation de 'EF Tracing Data Provider'
- 11. Comment exécuter du code Java en utilisant du code Java?
- 12. Java Code Obfuscate
- 13. Java Map hash code
- 14. Optimisation du code Java
- 15. Java Byte Code Visualizer
- 16. sans code java
- 17. Code temporel en Java
- 18. reformater code java
- 19. code vb équivalent pour un code java
- 20. Exécution du code Java de l'intérieur Java
- 21. Eclipse: arrêt du code (java)
- 22. Comprendre le code Java Byte
- 23. conversion du code Java C++
- 24. Scala en java code: $ colon
- 25. code source "undecompilable" en java
- 26. emballage java code en eclipse
- 27. Java: refactoring/optimisation de code
- 28. EOFException dans mon code Java
- 29. Bloc Java indépendant du code
- 30. Comment compiler le code java?
Vous pouvez essayer https://github.com/alfredxiao/jackplay, qui vous donne la capacité de traçage dans vos méthodes sans changement de code ni redéploiement. –