Showing posts with label clean code. Show all posts
Showing posts with label clean code. Show all posts

Python Coding Standard, Metrics and Test Coverage

Motivation

My motivation in seeking a coding standard, static code metrics analyzer and test coverage tool is multifaceted.  I want to know that my Python code is formatted in a way that is accepted by the community.  I want to be able to quickly check the cyclomatic complexity of code.  It is my intent to test drive my code.  Therefore, I wanted a tool which could show me and others the level of code coverage and any areas that need to be brought under test.

Note that the preferred download for all three of these tools is a .tar.gz format file.  On a Windows system you’ll need a tool like 7-zip.  All of this guidance is intended for use with Python 2.7 and PyCharm 1.5.4.  You need to add C:\Python27\ to your PATH environment variable in order to successfully install these tools.

PEP8

PEP8 is a tool that provides guidance that you are following proper Python coding formatting.  Download from here: http://pypi.python.org/pypi/pep8

Extract the PEP8 folder.  Using a command prompt change to the extracted PEP8 folder directory.  Run: python setup.py install There should now be a pep8.exe and pep8-script.py in your python installations scripts directory.  You can now delete the extracted PEP8 folder.

PEP8 with PyCharm

From http://www.in-nomine.org/2010/12/14/pycharm-and-external-lint-tools/

PyCharm already has a number of features present in various tools to lint/check your source code with, but offers a way to hook up external tools. Under File > Settings is a section called IDE Settings. One of the headings here is called External Tools. Select this heading and then press the Add... button on the right hand pane to configure a new external tool.

In the Edit Tool window that now appeared fill in a name, e.g. PEP8 and a group name Lint and add a description. Next point the Program to the location of the pep8.exe executable, e.g. C:\Python27\Scripts\pep8.exe. ForParameters you need to use $FilePath$ and Working directory should be same as the Python scripts directory. Once done, you can close it by pressing the OK button.

Now add a filter to the external tool to get click-and-go-to behavior

image

See http://www.jetbrains.com/pycharm/webhelp/add-filter-dialog.html for how to add filters.

use this for the spec: $FILE_PATH$:$LINE$:$COLUMN$:.*

image

Select a file either in the navigator or editor panes.

Then from menu can go to Tools > Lint > PEP8

You'll also have links you can click on for the PEP8 output.

Following my initial installation notes on a second machine I was getting a urllib.parse error from PEP8.exe, "no module named parse" Seemed like this problem is related to distribute. Pulled down the latest from http://pypi.python.org/pypi/distribute Nope, wouldn't install. Looking like issue with C:\python27\lib\urllib2.py.  Web pointed me to reinstall setuptools http://pypi.python.org/pypi/setuptools  Installed that… tried to install distribute again… still no go… X|  Ended up doing a python setup.py install to get distribute installed.  Now, PEP8 works!

PyMetrics

PyMetrics is a tool for doing static code analysis.  Download it here: https://github.com/ipmb/PyMetrics/downloads There is a tar.gz on SourceForge. However, the pymetrics runner does not have the .py extension which causes problems with extraction on a Windows System.

Extract your downloaded file.  Change to that directory and run python setup.py install  You can now delete the extracted folder.  Now if you look in your Python scripts directory you'll find a pymetrics.py

Set up as an external tool in PyCharm as with PEP8.

image

The --nosql and --nocsv options tell the tool to not generate associated SQL insert code and suppresses the generation of a related CSV file.

Sample output from DarkMatterLogger.py

An earlier version of the DarkMatterLogger.py that was analyzed can be found here: https://gist.github.com/1218497

C:\Python27\python.exe C:\Python27\Scripts\pymetrics C:\macts\source\spikes\DarkMatterLogger.py
=== File: C:\macts\source\spikes\DarkMatterLogger.py ===
Module C:\macts\source\spikes\DarkMatterLogger.py is missing a module doc string. Detected at line 1

Basic Metrics for module C:\macts\source\spikes\DarkMatterLogger.py
--------------------------------------------------------------
          4    maxBlockDepth
         12    numBlocks
       3726    numCharacters
          2    numClasses
         15    numComments
          5    numFunctions
         24    numKeywords
        104    numLines
        668    numTokens

         14.42 %Comments

Functions DocString present(+) or missing(-)
--------------------------------------------
- DarkMatterLogger.__init__
- DarkMatterLogger.sendMessage
- DarkMatterViewer.__init__
- DarkMatterViewer.__init__.msg_consumer
- main

Classes DocString present(+) or missing(-)
------------------------------------------

- DarkMatterLogger
- DarkMatterViewer

McCabe Complexity Metric for file C:\macts\source\spikes\DarkMatterLogger.py
--------------------------------------------------------------
          1    DarkMatterLogger.__init__
          1    DarkMatterLogger.sendMessage
          1    DarkMatterViewer.__init__
          2    DarkMatterViewer.__init__.msg_consumer
          1    __main__
          4    main

COCOMO 2's SLOC Metric for C:\macts\source\spikes\DarkMatterLogger.py
--------------------------------------------------------------
         55    C:\macts\source\spikes\DarkMatterLogger.py
*** Processed 1 module in run ***

Process finished with exit code 0

Coverage.py

Coverage.py is a tool for doing code coverage analysis.  Download it here: http://pypi.python.org/pypi/coverage  If you have a 64bit installation you’ll want to make sure you use the .tar.gz and not succumb to using a prepackaged exe.

Downloaded the coverage-3.5.1.tar.gz version.  Extract folder from gzipped tar file.  Chang to directory of download and: python setup.py install  Now if look in c:\python27\lib\site-packages will see coverage-3.5.1-py2.7.egg Look in the scripts dir and a coverage.exe and coverage-script.py will be seen.

Gather metrics on your code with: coverage run class.py

Then get the report with: coverage report -m

The -m says show the line #s of statements that were not executed.  Use coverage erase to get rid of previously run data.  During my experimenting every run would get rid of previous data. 

Set up as an external tool in PyCharm like other tools.  Except had to do one for the run and another for the report.  Others are integrating into their environment using nose.

Name: Coverage

For program: C:\Python27\Scripts\coverage.exe

For parameters: run $FileName$

Working directory: $FileDir$

Name: Coverage Report

For program: C:\Python27\Scripts\coverage.exe

For parameters: report -m

Working directory: $FileDir$

Coverage Sample Output

C:\Python27\Scripts\coverage.exe run C:\macts\source\spikes\ArgumentsTests.py
...........
----------------------------------------------------------------------
Ran 11 tests in 0.004s

OK

Process finished with exit code 0

Coverage Report Sample Output

C:\Python27\Scripts\coverage.exe report -m
Name             Stmts   Miss  Cover   Missing
----------------------------------------------
arguments           33      0   100%  
argumentstests      45      0   100%  
----------------------------------------------
TOTAL               78      0   100%  

Process finished with exit code 0

Summary

By integrating these three tools into your development process you’ll increase the community acceptance of the code you produce as well as increase the quality of the code you produce.

Hot on the edges, raw in the middle

Use the microwave at 100% to cook or reheat and you can end up with something that is hot on the edges or the outside, yet raw in the middle.

However, if you utilize the manual settings, like 60% power level with more time you will find that the food is more evenly cooked.  Or better yet, consult the manual and use the correct settings for the food type and quantity.

In the software development processes, breathing time/thinking time is good.

100% full bore gets you done.  However, when you have time to think about the system you may experience remorse.  To extend the microwave analogy--perhaps,  you have a nice shiny UI but rotten messy code under the hood.  With an appropriate “cooking temperature” you’d have both a nice UI and good code under the hood.

Clean code motivates

sweaty_hat I’m still dripping as I’m writing this.  (Okay, maybe not now, but when I did the voice memo recording I was!)  I’m just feeling very inspired and want to get this down in bits.

A lot of people talk about code smell, what it is, how to detect it and anti-patterns.  However, the thing that struck me today was this:  I was out mowing the yard.  The temperature was like a billion degrees, it was humid and I was mowing uphill no matter which way I turned!  So basically, it was hard work.  The thing that struck me was that I hit a section of air that smelled like a fragrant fabric softener.  It really perked me up.  I felt rejuvenated and mowed with more gusto.  I looked forward to returning to the portion of the yard that had the scent in the air.

The crossover

That got me thinking about code smell.  Besides code taking us more time to work through because of quality issues, there is also the issue that it smells!  It is repulsive, it is repugnant, it is de-motivating!  Who wants to go work on the smelly code?  No one wants to do it.  It is like being told to retrieve a book that is in a library that is located in the middle of a landfill.  No one wants to do that.  I think there is a psychological aspect of smelly code that should be considered.  That is, people want to stay away from stinky code.

On the flip side, are you excited when you get to go work in clean code?  Code that is well factored, code that uses patterns, code that you can understand, code that is a joy to work with.  I know that I can honestly say that if I have an application to work on and I know that it exhibits the qualities above, has a good design and has a reasonable amount of documentation I get excited about working on it.

Also, when I’m working in clean code I don’t want to be the one that dirties it up—regardless of who wrote it.

In conclusion, I would counsel that messy code besides having quality issues is also de-motivating.  Clean code, good smelling code is a joy to work with.  Strive for clean code.