Code quality par Simone Civetta

83
Hello

Transcript of Code quality par Simone Civetta

Hello

Be the quality you want to see in the

World

Code quality metrics

How many of you calculate code metrics

in ObjC?

It's a long story

IntroductionWhat are code metrics?

You get what you measure— Joshua Appelman

Code metrics are a set of software measures

Cool.

But.

" Why should I bother about that? "

Because you want:

To understand which methods/classes should be reworked

Your development team to identify potential risks

To track progress during software development

And, ultimately, because you ♥ your codebase

" When should I use that? "

Basically, when you

Have a large codebase

Work in heterogeneous teams

Are writing an auditWant to get a rapid overview of an inherited codebase

" When should I use that? "

Practically everyday

Which code metrics?

# lines of code / # of files

Cyclomatic complexityfunc example(a: Int, b: Int, c:Int, d:Int) { // 1 if a == b { // 2 println("Hello") } else if (c == d) { // 3 for index in 1...5 { // 4 println("Hello") } } else { // 5 switch c { case 1: // 6 println("Hello") case 2: // 7 println("Hello") default: // 8 println("Hello") } }}

NPath complexityfunc example(a:Int, b:Int) { if a > 10 { println(1) } else { println(2) } if a > b { println(3) } else { println(4) }}// Result: 4

Code coverage

Duplications (CPD)

Depth of inheritance

Class coupling

NCSS

HSLOCR

HSLOCRHoly Sh*t / Lines of Code Ratio

LASER

LASERLAser Shark Exposure Rate

How to generate code metrics?

PMD

PMD

Java static analyzer - a must-have of the Java developer

Supports Java, JavaScript, XML

Identifies:• Unused variables

• Empty catch blocks

• Unnecessary object creation

• Cyclomatic/NPath complexity

Clang Static Analyzer

Clang Static Analyzer

Part of the Clang project

Run as standalone or included via Xcode

Analyzes the different execution paths (Abstract Syntax Tree)

Detects wether some paths can lead to problems

AppCode

AppCode

Performs checks for:

• Clang analysis

• Class errors (hidden scopes, missing implementations)

• Data flow analysis

• Obsolete vs Modern syntax checking

• String localisation control

• Unavailable/deprecated APIs

gcovr

gcovr

Generates code coverage reports from .gcda and .gcno files

Exports to the Cobertura1 XML format

.gcda and .gcno files are generated by setting

• GCC_GENERATE_TEST_COVERAGE_FILES

• GCC_INSTRUMENT_PROGRAM_FLOW_ARCS

1 - Cobertura: an open source tool for measuring Java code coverage

OCLint

OCLint

Inspired by PMD and by the AppCode static analyzer

Based on Clang

Exports to the PMD file format

OCLint

Detects:• Empty control flow statements

• Unused code

• Complicated code (high cyclomatic/NPath complexity, deep statements)

• Redundant if statements

• Long methods, long parameter list

OCLint

Rules are extensible

You can write your own

OCLint - Installing

http://docs.oclint.org/en/dev/intro/installation.html

Make the binary available from your path

Tools

SonarQube

SonarQube

A Web Application for Continuous Inspection of code quality

Acts as an hub for code metrics

Integrates with other tools such as PMD, Cobertura or OCLint

SonarQube - Installing

$ brew install sonar

$ brew install sonar-runner # Front end

SonarQube Runner

SonarQube Runner

Is the frontend for executing sonar

Reads a sonar-project.properties file in the project folder

SonarQube Objective-C plugin

SonarQube Objective-C plugin

Developed by Octo Technologies, Parisgithub.com/octo-technology/sonar-objective-c

Aggregates:• OCLint results

• Test coverage (via Cobertura)

• CPD

SonarQube Objective-C plugin - Installing

build from sources:$ mvn install

" When should I use that? "

Practically everyday

Automate!

Automate!!

Automate!!!

Automate!!!

A real life project

1. Jenkins

2. xcodebuild/xctool/xcpretty

3. OCLint

4. Run Tests

5. Run gcovr

6. Sonar

Warning:bash

Proceed with caution

Let's dive in

1. Jenkins

Runs project jobs

A job can consist in compilation, testing, analysis, deployment tasks

Jobs can be parametrized

2. xcodebuild/xctool/xcpretty

$ /usr/bin/xcodebuild [params] > xcodebuild.log

3. OCLint

$ oclint-xcodebuild # Generates compile_commands.json

$ oclint-json-compilation-database > -- -report-type pmd -o sonar-reports/oclint.xml

4. Run tests

$ GCC_GENERATE_TEST_COVERAGE_FILES=YES > GCC_INSTRUMENT_PROGRAM_FLOW_ARCS=YES > /usr/bin/xcodebuild test | xcpretty -tc --report junit > --output "${PWD}/sonar-reports/TEST-report.xml"

5. Run gcovr

$ ./scripts/gcovr -r . PATH/TO/DUCKING/DERIVEDDATA/ > --exclude .*Tests.* --xml > > "${PWD}/sonar-reports/coverage.xml"

6. Sonar-Runner - Property file

sonar.projectKey=nsspaindemosonar.projectName=NSSpainDemosonar.language=objcsonar.projectDescription=NSSpainDemosonar.sources=NSSpainDemo/sonar.objectivec.project=NSSpainDemo.xcodeproj

Putting it all together

#!/bin/bash

BUILD_CMD_SUFFIX="-project ${PROJECT_NAME}.xcodeproj -derivedDataPath ${PWD}/DerivedData -configuration Debug" \

# Clean the foldersrm -rf ${PWD}/sonar-reportsrm -rf ${PWD}/DerivedDatamkdir ${PWD}/sonar-reports

# Build/usr/bin/xcodebuild ${BUILD_CMD_SUFFIX} -scheme "${DEFAULT_SCHEME}" \ -sdk "${DEFAULT_SDK}" > xcodebuild.log

# Generate compile commands/usr/local/bin/oclint-xcodebuild/usr/local/bin/oclint-json-compilation-database "${PWD}/${PROJECT_NAME}" \ -- -report-type pmd -o sonar-reports/oclint.xml

# Run testsGCC_GENERATE_TEST_COVERAGE_FILES=YES \ GCC_INSTRUMENT_PROGRAM_FLOW_ARCS=YES \ /usr/bin/xcodebuild ${BUILD_CMD_SUFFIX} -scheme "${DEFAULT_SCHEME}" \ -sdk "${DEFAULT_SDK}" test | xcpretty -tc --report junit \ --output "${PWD}/sonar-reports/TEST-report.xml"

# Generate coverage report./scripts/gcovr -r . \ ${PWD}/DerivedData/Build/Intermediates/"${DEFAULT_SCHEME}".build/Debug-iphonesimulator/"${DEFAULT_TARGET}".build/Objects-normal/i386 \ --exclude .*Tests.* --xml > "${PWD}/sonar-reports/coverage.xml"

# Send results to SonarQube/usr/local/bin/sonar-runner

exit $?

Final thoughts

Final thoughts

• Automate, automate, automate

• Code metrics are not Gospel

• Static analysis alone is not enough

• Pick a range of complementary metrics

• Be honest with yourself

• Aim for all metrics rather than excelling in a single one

You get what you measure— Joshua Appelman

Share the results with your teamImprove continuously

Be the quality you want to see in the

World

Thank y♥u!

Simone Civetta@viteinfinite