chris clarke
software development that works…or something
Sloppy Code equals Buggy Code ?
April 26, 2007 on 10:35 pm | In Tools n Stuff |Having witnessed a lot of bugs recently, big and small, in some legacy code - there seems to be some patterns emerging. The root causes of the bugs are often found deep inside big classes, often with some suspicious looking commented-out code and the odd TODO floating nearby. Even when implementing new features, I’ve found myself spending most of my time trawling through these larger species of classes trying to work out what they are doing. I find myself deleting chunks of commented out code and tripping over scary looking TODO’s saying things like ‘Fix this when I figure out what it should do’ or ‘Hack - fix me’. These bigger, sloppier classes are minefields for potential bugs and quicksand for productivity.
Having read Ivan and Nat’s attempt at a Real-time Sloppographer, from the Scrapheap Challenge at SPA 2007, I was inspired to come up with a similar utility for measuring Sloppiness in the way it had affected me.
mostLikelyToBeBuggyTop10.py is a quick bit of python I wrote to measure sloppiness based on the things I’ve encountered:
- size - bigger files get more sloppy points
- TODOs - more TODOs, more sloppy points
- does it have a Test? - if not - more sloppy points
- number of comments - maybe slightly controversial - but the more comments, the more sloppy points - i’ve found files with big chunks of commented out code so it’s useful for me
# mostLikelyToBeBuggyTop10.py
import os, re, sys
todoPattern = re.compile('Todo|TODO')
commentPattern = re.compile('//')
excludePattern = re.compile('Test.java')
def howBuggyIs(javaFile):
lines = open(javaFile).readlines()
numberOfLinesMetric = len(lines)
numberOfCommentsMetric = len([l for l in lines if commentPattern.search(l) and not todoPattern.search(l)])
numberOfTodosMetric = len(todoPattern.findall(''.join(lines)))
wouldBeTestName = os.path.basename(javaFile).replace('.java', 'Test.java')
hasTest = len([f for f in javaFilesCopy if f.endswith(wouldBeTestName)]) > 0
buggyMetric = numberOfLinesMetric (numberOfTodosMetric * 50) (numberOfCommentsMetric * 10)
if not hasTest:
buggyMetric *= 10
return buggyMetric
def bugMetric(x, y):
return howBuggyIs(y) - howBuggyIs(x)
if __name__ == "__main__":
if len(sys.argv) == 1:
print 'Usage: python mostLikelyToBeBuggyTop10.py path [excludePattern]'
print ' e.g. '
print ' python mostLikelyToBeBuggyTop10.py .'
print ' python mostLikelyToBeBuggyTop10.py src/java Test'
sys.exit(1)
if len(sys.argv) == 3:
excludePattern = re.compile(sys.argv[2])
javaFiles = []
for root, dirs, files in os.walk(sys.argv[1], topdown=False):
javaFiles.extend([os.path.join(root, name) for name in files if name.endswith('.java')])
javaFilesCopy = list(javaFiles)
javaFiles.sort(bugMetric)
javaFiles = [f for f in javaFiles if not excludePattern.search(f)]
for mostBuggy in javaFiles[:10]:
print mostBuggy
Sorry, some characters don’t show up, such as ‘+’, but you can get the original here: mostLikelyToBeBuggyTop10.py
No Comments yet »
RSS feed for comments on this post. TrackBack URI
Leave a comment
Sloppy Code equals Buggy Code ?
April 26, 2007 on 10:35 pm | In Tools n Stuff |Having witnessed a lot of bugs recently, big and small, in some legacy code - there seems to be some patterns emerging. The root causes of the bugs are often found deep inside big classes, often with some suspicious looking commented-out code and the odd TODO floating nearby. Even when implementing new features, I’ve found myself spending most of my time trawling through these larger species of classes trying to work out what they are doing. I find myself deleting chunks of commented out code and tripping over scary looking TODO’s saying things like ‘Fix this when I figure out what it should do’ or ‘Hack - fix me’. These bigger, sloppier classes are minefields for potential bugs and quicksand for productivity.
Having read Ivan and Nat’s attempt at a Real-time Sloppographer, from the Scrapheap Challenge at SPA 2007, I was inspired to come up with a similar utility for measuring Sloppiness in the way it had affected me.
mostLikelyToBeBuggyTop10.py is a quick bit of python I wrote to measure sloppiness based on the things I’ve encountered:
- size - bigger files get more sloppy points
- TODOs - more TODOs, more sloppy points
- does it have a Test? - if not - more sloppy points
- number of comments - maybe slightly controversial - but the more comments, the more sloppy points - i’ve found files with big chunks of commented out code so it’s useful for me
# mostLikelyToBeBuggyTop10.py
import os, re, sys
todoPattern = re.compile('Todo|TODO')
commentPattern = re.compile('//')
excludePattern = re.compile('Test.java')
def howBuggyIs(javaFile):
lines = open(javaFile).readlines()
numberOfLinesMetric = len(lines)
numberOfCommentsMetric = len([l for l in lines if commentPattern.search(l) and not todoPattern.search(l)])
numberOfTodosMetric = len(todoPattern.findall(''.join(lines)))
wouldBeTestName = os.path.basename(javaFile).replace('.java', 'Test.java')
hasTest = len([f for f in javaFilesCopy if f.endswith(wouldBeTestName)]) > 0
buggyMetric = numberOfLinesMetric (numberOfTodosMetric * 50) (numberOfCommentsMetric * 10)
if not hasTest:
buggyMetric *= 10
return buggyMetric
def bugMetric(x, y):
return howBuggyIs(y) - howBuggyIs(x)
if __name__ == "__main__":
if len(sys.argv) == 1:
print 'Usage: python mostLikelyToBeBuggyTop10.py path [excludePattern]'
print ' e.g. '
print ' python mostLikelyToBeBuggyTop10.py .'
print ' python mostLikelyToBeBuggyTop10.py src/java Test'
sys.exit(1)
if len(sys.argv) == 3:
excludePattern = re.compile(sys.argv[2])
javaFiles = []
for root, dirs, files in os.walk(sys.argv[1], topdown=False):
javaFiles.extend([os.path.join(root, name) for name in files if name.endswith('.java')])
javaFilesCopy = list(javaFiles)
javaFiles.sort(bugMetric)
javaFiles = [f for f in javaFiles if not excludePattern.search(f)]
for mostBuggy in javaFiles[:10]:
print mostBuggy
Sorry, some characters don’t show up, such as ‘+’, but you can get the original here: mostLikelyToBeBuggyTop10.py
No Comments yet »
RSS feed for comments on this post. TrackBack URI
Leave a comment
Powered by Cheese.
RSS Entries Feed.
RSS Comments Feed
^Top^