Code Style and Code Smell

by Andrii Shyshkalov <andrii@enswer.net>

Plan

  • Code style
  • Code smell
  • Practical copy / clone & run

Code Style

"Code is read much more often than it is written", Python's BDFL

Git commits are fewer and more meaningful

Do you like these git diffs ?


In [5]:
from IPython.display import Image
Image(filename='code/git_diff.png')


Out[5]:

The difference is the spacing only!

If style is kept by everyone, these things don't happen;

git blame and other tools become more useful

Code autoformatter

  • ensures consistent styles between files and developers
  • built-in code formatter in vim is insufficient
  • should complain every time you save

I will show how to get one working for Python and C++

Code smell

Indicates potential and often real problems with files

Spot a problem


In [12]:
from IPython.display import Image
Image(filename='code/vim_no_lint.png')


Out[12]:

Anyone? BTW, this code is in production...

Spot a problem - help wanted


In [9]:
from IPython.display import Image
Image(filename='code/vim_lynt_warn_0.png')


Out[9]:

Memory leak is almost guaranteed if used with unique_ptr, shared_ptr, or new and delete.

Python example

See a problem?


In [ ]:
def debug_memory_leak(objects, old_seconds):
    for obj in objects:
        if obj.get_age() >= old_seconds:
            has_old_objecs = True
    else:
        has_old_objects = False

    if has_old_objects:
        # don't attempt to clean
        collect_debug_info(objects)

has_old_objects variable is spelled as has_old_objecs inside a loop.

Same example with pyflakes


In [14]:
from IPython.display import Image
Image(filename='code/vim_py_lynt.png')


Out[14]:

For non-vim users:

  • emacs has similar integration scripts
  • sublime might work, too

Not emacs/vim user?

since you are here, I guess you'll switch soon :)

and I'll show standalone tools at the end

Configuring Vim: Python

Python-mode project does excellent job at integrating tools inside vim https://github.com/klen/python-mode

Use pathogen, and then it's easy:

mkdir -p ~/.vim/autoload ~/.vim/bundle
curl -Sso ~/.vim/autoload/pathogen.vim https://raw.github.com/tpope/vim-pathogen/master/autoload/pathogen.vim
cd ~/.vim/
mkdir -p bundle && cd bundle
git clone git://github.com/klen/python-mode.git

Add this to your ~/.vimrc:

" Pathogen load
filetype off

call pathogen#infect()
call pathogen#helptags()

filetype plugin indent on
syntax on

" configures the python-mode itself:
let g:pymode = 1
let g:pymode_lint = 1


New Apparently, one can also install it using debian package: https://github.com/klen/python-mode#debian-packages

My config

my .vimrc has these, adapt to yourself:

let g:pymode = 1
" Disable python folding
let g:pymode_folding = 0
let g:pymode_doc = 1
let g:pymode_doc_bind = 'K'
let g:pymode_syntax_builtin_objs = 1
let g:pymode_syntax_all = 1
let g:pymode_syntax_highlight_self = 1
let g:pymode_lint = 1
let g:pymode_lint_unmodified = 1  " on every save regardless of changes
let g:pymode_lint_checker = ['pylint', 'pyflakes', 'pep8', 'mccabe']
let g:pymode_lint_ignore = "W0704,C0103,C0111,R0904

Python-mode in action


In [16]:
from IPython.display import Image
Image(filename='code/vim_py_lynt.png')


Out[16]:

C++ style & lint for Vim (1)

First, we need newest clang. Visit this page http://llvm.org/apt/ and get one for your debian/ubuntu. For precise:

wget -O - http://llvm.org/apt/llvm-snapshot.gpg.key | sudo apt-key add -

and add these lines to /etc/apt/clang.list :

deb http://llvm.org/apt/precise/ llvm-toolchain-precise main
deb-src http://llvm.org/apt/precise/ llvm-toolchain-precise main
# 3.4
deb http://llvm.org/apt/precise/ llvm-toolchain-precise-3.4 main
deb-src http://llvm.org/apt/precise/ llvm-toolchain-precise-3.4 main
# Common
deb http://ppa.launchpad.net/ubuntu-toolchain-r/test/ubuntu precise main

you'll also need to configure ppa for latest g++-4.8 https://launchpad.net/~ubuntu-toolchain-r/+archive/ppa :

sudo apt-add-repository ppa:ubuntu-toolchain-r/ppa
sudo apt-get update
sudo apt-get install clang-3.4 clang-3.4-doc libclang-common-3.4-dev libclang-3.4-dev libclang1-3.4 libclang1-3.4-dbg libllvm-3.4-ocaml-dev libllvm3.4 libllvm3.4-dbg lldb-3.4 llvm-3.4 llvm-3.4-dev llvm-3.4-doc llvm-3.4-examples llvm-3.4-runtime clang-modernize-3.4 clang-format-3.4 python-clang-3.4 lldb-3.4-dev

C++ style & lint for Vim (2)

Compile flint https://github.com/shishkander/flint or get it yourself:

mkdir -p ~/bin
cd ~/bin
wget http://shishkander.org.ua/flint

Flint is Facebook product, now written in D :)

C++ style & lint for Vim (3)

Now, get the linter integration plugin for vim: https://bitbucket.org/tim_heap/linters.vim

git clone https://bitbucket.org/tim_heap/linters.vim ~/.vim/bundle/linters

and in ~/.vimrc add:

" Universal linter handling for vim
"   I already have python-mode, so I don't need python linter.
let g:linters_disabled_filetypes = ['python']
if executable("flint")
    " we don't want to bother with errors if flint isn't installed.
    let g:linters_extra = [['cpp', 'flint %s &> %s', ['%f(%l): %m']]]
endif

C++ style & lint for Vim (4)

Get my modified script of original clang-format-3.4.py (http://clang.llvm.org/docs/ClangFormatStyleOptions.html)

cd ~/.vim/
wget http://shishkander.org.ua/clang-format-3.4.py

and in ~/.vimrc add:

" Clang C++ formatter
map <C-I> :pyf /home/andrii/.vim/clang-format-3.4.py<CR>
imap <C-I> <ESC>:pyf /home/andrii/.vim/clang-format-3.4.py<CR>i

C++ style & lint for Vim in action


In [18]:
from IPython.display import Image
Image(filename='code/vim_lynt_warn_0.png')


Out[18]:

TODO

All this is work in progress over last 2 years.

In the coming weeks, I'll create git repo with all this right there, and share it at my github.

I really want your .vim tricks, so talk to me :)

Thank you!