Slide 1

Slide 1 text

Hello

Slide 2

Slide 2 text

Be the quality you want to see in the World

Slide 3

Slide 3 text

Code quality metrics

Slide 4

Slide 4 text

How many of you calculate code metrics in ObjC?

Slide 5

Slide 5 text

It's a long story

Slide 6

Slide 6 text

Introduction What are code metrics?

Slide 7

Slide 7 text

You get what you measure — Joshua Appelman

Slide 8

Slide 8 text

Code metrics are a set of software measures

Slide 9

Slide 9 text

Cool.

Slide 10

Slide 10 text

But.

Slide 11

Slide 11 text

" Why should I bother about that? "

Slide 12

Slide 12 text

Because you want: To understand which methods/classes should be reworked Your development team to identify potential risks To track progress during software development

Slide 13

Slide 13 text

And, ultimately, because you — your codebase

Slide 14

Slide 14 text

Slide 15

Slide 15 text

" When should I use that? "

Slide 16

Slide 16 text

Basically, when you Have a large codebase Work in heterogeneous teams Are writing an audit Want to get a rapid overview of an inherited codebase

Slide 17

Slide 17 text

No content

Slide 18

Slide 18 text

" When should I use that? " Practically everyday

Slide 19

Slide 19 text

Which code metrics?

Slide 20

Slide 20 text

# lines of code / # of files

Slide 21

Slide 21 text

Cyclomatic complexity func 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") } } }

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

Code coverage

Slide 24

Slide 24 text

Duplications (CPD)

Slide 25

Slide 25 text

Depth of inheritance

Slide 26

Slide 26 text

Class coupling

Slide 27

Slide 27 text

NCSS

Slide 28

Slide 28 text

HSLOCR

Slide 29

Slide 29 text

HSLOCR Holy Sh*t / Lines of Code Ratio

Slide 30

Slide 30 text

LASER

Slide 31

Slide 31 text

LASER LAser Shark Exposure Rate

Slide 32

Slide 32 text

No content

Slide 33

Slide 33 text

Slide 34

Slide 34 text

How to generate code metrics?

Slide 35

Slide 35 text

PMD

Slide 36

Slide 36 text

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

Slide 37

Slide 37 text

Clang Static Analyzer

Slide 38

Slide 38 text

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

Slide 39

Slide 39 text

AppCode

Slide 40

Slide 40 text

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

Slide 41

Slide 41 text

Slide 42

Slide 42 text

gcovr

Slide 43

Slide 43 text

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

Slide 44

Slide 44 text

OCLint

Slide 45

Slide 45 text

OCLint Inspired by PMD and by the AppCode static analyzer Based on Clang Exports to the PMD file format

Slide 46

Slide 46 text

OCLint Detects: • Empty control flow statements • Unused code • Complicated code (high cyclomatic/NPath complexity, deep statements) • Redundant if statements • Long methods, long parameter list

Slide 47

Slide 47 text

OCLint Rules are extensible You can write your own

Slide 48

Slide 48 text

OCLint - Installing http://docs.oclint.org/en/dev/intro/installation.html Make the binary available from your path

Slide 49

Slide 49 text

Tools

Slide 50

Slide 50 text

SonarQube

Slide 51

Slide 51 text

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

Slide 52

Slide 52 text

SonarQube - Installing $ brew install sonar $ brew install sonar-runner # Front end

Slide 53

Slide 53 text

SonarQube Runner

Slide 54

Slide 54 text

SonarQube Runner Is the frontend for executing sonar Reads a sonar-project.properties file in the project folder

Slide 55

Slide 55 text

SonarQube Objective-C plugin

Slide 56

Slide 56 text

SonarQube Objective-C plugin Developed by Octo Technologies, Paris github.com/octo-technology/sonar-objective-c Aggregates: • OCLint results • Test coverage (via Cobertura) • CPD

Slide 57

Slide 57 text

SonarQube Objective-C plugin - Installing build from sources: $ mvn install

Slide 58

Slide 58 text

" When should I use that? " Practically everyday

Slide 59

Slide 59 text

Automate!

Slide 60

Slide 60 text

Automate!!

Slide 61

Slide 61 text

Automate!!!

Slide 62

Slide 62 text

Automate!!!

Slide 63

Slide 63 text

A real life project 1. Jenkins 2. xcodebuild/xctool/xcpretty 3. OCLint 4. Run Tests 5. Run gcovr 6. Sonar

Slide 64

Slide 64 text

Warning: bash Proceed with caution

Slide 65

Slide 65 text

Let's dive in

Slide 66

Slide 66 text

1. Jenkins Runs project jobs A job can consist in compilation, testing, analysis, deployment tasks Jobs can be parametrized

Slide 67

Slide 67 text

2. xcodebuild/xctool/xcpretty $ /usr/bin/xcodebuild [params] > xcodebuild.log

Slide 68

Slide 68 text

3. OCLint $ oclint-xcodebuild # Generates compile_commands.json $ oclint-json-compilation-database > -- -report-type pmd -o sonar-reports/oclint.xml

Slide 69

Slide 69 text

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"

Slide 70

Slide 70 text

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

Slide 71

Slide 71 text

6. Sonar-Runner - Property file sonar.projectKey=nsspaindemo sonar.projectName=NSSpainDemo sonar.language=objc sonar.projectDescription=NSSpainDemo sonar.sources=NSSpainDemo/ sonar.objectivec.project=NSSpainDemo.xcodeproj

Slide 72

Slide 72 text

Putting it all together #!/bin/bash BUILD_CMD_SUFFIX="-project ${PROJECT_NAME}.xcodeproj -derivedDataPath ${PWD}/DerivedData -configuration Debug" \ # Clean the folders rm -rf ${PWD}/sonar-reports rm -rf ${PWD}/DerivedData mkdir ${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 tests GCC_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 $?

Slide 73

Slide 73 text

No content

Slide 74

Slide 74 text

No content

Slide 75

Slide 75 text

No content

Slide 76

Slide 76 text

Final thoughts

Slide 77

Slide 77 text

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

Slide 78

Slide 78 text

You get what you measure — Joshua Appelman

Slide 79

Slide 79 text

Share the results with your team Improve continuously

Slide 80

Slide 80 text

Be the quality you want to see in the World

Slide 81

Slide 81 text

Slide 82

Slide 82 text

Thank y—u!

Slide 83

Slide 83 text

Simone Civetta @viteinfinite