2010-05-19 6 views
1

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

+0

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. –

Répondre

2

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" 
+0

Qu'est-ce que ce script? – OscarRyz

+0

Il tente de produire toutes les références Java/JSP dans un ensemble de fichiers. – Amarsh

4

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

+0

Il pourrait être difficile de trouver des unités testables s'il s'agit d'un gros moloch. – tangens

+0

Certainement! C'est là que ce livre aide. En traitant avec des bases de code anciennes et grandes. – cherouvim

+0

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

3

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é!

2

Si vous voulez tracer l'exécution de votre code Java, vous pouvez utiliser un outil appelé InTrace.